blob: 64b43c82175223e50fffc619af245f60279a3dc3 [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/AArch64AddressingModes.h"
11#include "MCTargetDesc/AArch64MCExpr.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000012#include "MCTargetDesc/AArch64MCTargetDesc.h"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000013#include "MCTargetDesc/AArch64TargetStreamer.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000014#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000015#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000016#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000017#include "llvm/ADT/ArrayRef.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000018#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "llvm/ADT/SmallVector.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000020#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000021#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000023#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000025#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000028#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000029#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000030#include "llvm/MC/MCParser/MCAsmLexer.h"
31#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000032#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000033#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000034#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000035#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSubtargetInfo.h"
38#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000039#include "llvm/MC/MCTargetOptions.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000043#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000044#include "llvm/Support/MathExtras.h"
45#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000046#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000047#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000049#include <cassert>
50#include <cctype>
51#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000052#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000053#include <string>
54#include <tuple>
55#include <utility>
56#include <vector>
57
Tim Northover3b0846e2014-05-24 12:50:23 +000058using namespace llvm;
59
60namespace {
61
Sander de Smalencd6be962017-12-20 11:02:42 +000062enum class RegKind {
63 Scalar,
64 NeonVector,
65 SVEDataVector,
66 SVEPredicateVector
67};
Florian Hahnc4422242017-11-07 13:07:50 +000068
Tim Northover3b0846e2014-05-24 12:50:23 +000069class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000070private:
71 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000072
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000073 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000074 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000075
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000076 AArch64TargetStreamer &getTargetStreamer() {
77 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
78 return static_cast<AArch64TargetStreamer &>(TS);
79 }
80
Rafael Espindola961d4692014-11-11 05:18:41 +000081 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000082
83 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +000084 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +000085 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
86 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +000087 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +000088 bool parseRegister(OperandVector &Operands);
89 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
Sander de Smalenc88f9a12018-04-11 14:10:37 +000090 bool parseNeonVectorList(OperandVector &Operands);
Sander de Smalen5c625982018-04-13 12:56:14 +000091 bool parseOptionalMulVl(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000092 bool parseOperand(OperandVector &Operands, bool isCondCode,
93 bool invertCondCode);
94
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +000095 bool showMatchError(SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000096
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000097 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000098 bool parseDirectiveCPU(SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +000099 bool parseDirectiveInst(SMLoc L);
100
Tim Northover3b0846e2014-05-24 12:50:23 +0000101 bool parseDirectiveTLSDescCall(SMLoc L);
102
103 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000104 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000105
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000106 bool parseDirectiveReq(StringRef Name, SMLoc L);
107 bool parseDirectiveUnreq(SMLoc L);
108
Tim Northover3b0846e2014-05-24 12:50:23 +0000109 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
110 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
111 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000112 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000113 bool MatchingInlineAsm) override;
114/// @name Auto-generated Match Functions
115/// {
116
117#define GET_ASSEMBLER_HEADER
118#include "AArch64GenAsmMatcher.inc"
119
120 /// }
121
Sander de Smalen50d87022018-04-19 07:35:08 +0000122 OperandMatchResultTy tryParseScalarRegister(unsigned &Reg);
123 OperandMatchResultTy tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +0000124 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000125 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
126 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
127 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
128 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
129 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
Sander de Smalen93380372018-05-14 11:54:41 +0000130 template <bool IsSVEPrefetch = false>
Tim Northover3b0846e2014-05-24 12:50:23 +0000131 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000132 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000133 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
134 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
135 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
Sander de Smalen62770792018-05-25 09:47:52 +0000136 OperandMatchResultTy tryParseImmWithOptionalShift(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000137 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000138 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000139 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000140 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Sander de Smalen149916d2018-04-20 07:24:20 +0000141 template <bool ParseShiftExtend>
142 OperandMatchResultTy tryParseGPROperand(OperandVector &Operands);
Sander de Smaleneb896b12018-04-25 09:26:47 +0000143 template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +0000144 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000145 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000146 template <RegKind VectorKind>
147 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
148 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000149 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000150
151public:
152 enum AArch64MatchResultTy {
153 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
154#define GET_OPERAND_DIAGNOSTIC_TYPES
155#include "AArch64GenAsmMatcher.inc"
156 };
Joel Jones504bf332016-10-24 13:37:13 +0000157 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000158
Akira Hatanakab11ef082015-11-14 06:35:56 +0000159 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000160 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000161 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000162 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000163 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000164 MCStreamer &S = getParser().getStreamer();
165 if (S.getTargetStreamer() == nullptr)
166 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000167
Alex Bradbury0a59f182018-05-23 11:17:20 +0000168 // Alias .hword/.word/xword to the target-independent .2byte/.4byte/.8byte
169 // directives as they have the same form and semantics:
170 /// ::= (.hword | .word | .xword ) [ expression (, expression)* ]
171 Parser.addAliasForDirective(".hword", ".2byte");
172 Parser.addAliasForDirective(".word", ".4byte");
173 Parser.addAliasForDirective(".xword", ".8byte");
174
Tim Northover3b0846e2014-05-24 12:50:23 +0000175 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000176 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000177 }
178
179 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
180 SMLoc NameLoc, OperandVector &Operands) override;
181 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
182 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000183 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000184 unsigned Kind) override;
185
186 static bool classifySymbolRef(const MCExpr *Expr,
187 AArch64MCExpr::VariantKind &ELFRefKind,
188 MCSymbolRefExpr::VariantKind &DarwinRefKind,
189 int64_t &Addend);
190};
Tim Northover3b0846e2014-05-24 12:50:23 +0000191
192/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
193/// instruction.
194class AArch64Operand : public MCParsedAsmOperand {
195private:
196 enum KindTy {
197 k_Immediate,
198 k_ShiftedImm,
199 k_CondCode,
200 k_Register,
201 k_VectorList,
202 k_VectorIndex,
203 k_Token,
204 k_SysReg,
205 k_SysCR,
206 k_Prefetch,
207 k_ShiftExtend,
208 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000209 k_Barrier,
210 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000211 } Kind;
212
213 SMLoc StartLoc, EndLoc;
214
215 struct TokOp {
216 const char *Data;
217 unsigned Length;
218 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
219 };
220
Sander de Smalen149916d2018-04-20 07:24:20 +0000221 // Separate shift/extend operand.
222 struct ShiftExtendOp {
223 AArch64_AM::ShiftExtendType Type;
224 unsigned Amount;
225 bool HasExplicitAmount;
226 };
227
Tim Northover3b0846e2014-05-24 12:50:23 +0000228 struct RegOp {
229 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000230 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000231 int ElementWidth;
Sander de Smalen149916d2018-04-20 07:24:20 +0000232
233 // In some cases the shift/extend needs to be explicitly parsed together
234 // with the register, rather than as a separate operand. This is needed
235 // for addressing modes where the instruction as a whole dictates the
236 // scaling/extend, rather than specific bits in the instruction.
237 // By parsing them as a single operand, we avoid the need to pass an
238 // extra operand in all CodeGen patterns (because all operands need to
239 // have an associated value), and we avoid the need to update TableGen to
240 // accept operands that have no associated bits in the instruction.
241 //
242 // An added benefit of parsing them together is that the assembler
243 // can give a sensible diagnostic if the scaling is not correct.
244 //
245 // The default is 'lsl #0' (HasExplicitAmount = false) if no
246 // ShiftExtend is specified.
247 ShiftExtendOp ShiftExtend;
Tim Northover3b0846e2014-05-24 12:50:23 +0000248 };
249
250 struct VectorListOp {
251 unsigned RegNum;
252 unsigned Count;
253 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000254 unsigned ElementWidth;
255 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000256 };
257
258 struct VectorIndexOp {
259 unsigned Val;
260 };
261
262 struct ImmOp {
263 const MCExpr *Val;
264 };
265
266 struct ShiftedImmOp {
267 const MCExpr *Val;
268 unsigned ShiftAmount;
269 };
270
271 struct CondCodeOp {
272 AArch64CC::CondCode Code;
273 };
274
275 struct FPImmOp {
276 unsigned Val; // Encoded 8-bit representation.
277 };
278
279 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000280 const char *Data;
281 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000282 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000283 };
284
285 struct SysRegOp {
286 const char *Data;
287 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000288 uint32_t MRSReg;
289 uint32_t MSRReg;
290 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000291 };
292
293 struct SysCRImmOp {
294 unsigned Val;
295 };
296
297 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000298 const char *Data;
299 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000300 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000301 };
302
Oliver Stannarda34e4702015-12-01 10:48:51 +0000303 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000304 const char *Data;
305 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000306 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000307 };
308
Tim Northover3b0846e2014-05-24 12:50:23 +0000309 struct ExtendOp {
310 unsigned Val;
311 };
312
313 union {
314 struct TokOp Tok;
315 struct RegOp Reg;
316 struct VectorListOp VectorList;
317 struct VectorIndexOp VectorIndex;
318 struct ImmOp Imm;
319 struct ShiftedImmOp ShiftedImm;
320 struct CondCodeOp CondCode;
321 struct FPImmOp FPImm;
322 struct BarrierOp Barrier;
323 struct SysRegOp SysReg;
324 struct SysCRImmOp SysCRImm;
325 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000326 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000327 struct ShiftExtendOp ShiftExtend;
328 };
329
330 // Keep the MCContext around as the MCExprs may need manipulated during
331 // the add<>Operands() calls.
332 MCContext &Ctx;
333
David Blaikie960ea3f2014-06-08 16:18:35 +0000334public:
David Blaikie9f380a32015-03-16 18:06:57 +0000335 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000336
Tim Northover3b0846e2014-05-24 12:50:23 +0000337 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
338 Kind = o.Kind;
339 StartLoc = o.StartLoc;
340 EndLoc = o.EndLoc;
341 switch (Kind) {
342 case k_Token:
343 Tok = o.Tok;
344 break;
345 case k_Immediate:
346 Imm = o.Imm;
347 break;
348 case k_ShiftedImm:
349 ShiftedImm = o.ShiftedImm;
350 break;
351 case k_CondCode:
352 CondCode = o.CondCode;
353 break;
354 case k_FPImm:
355 FPImm = o.FPImm;
356 break;
357 case k_Barrier:
358 Barrier = o.Barrier;
359 break;
360 case k_Register:
361 Reg = o.Reg;
362 break;
363 case k_VectorList:
364 VectorList = o.VectorList;
365 break;
366 case k_VectorIndex:
367 VectorIndex = o.VectorIndex;
368 break;
369 case k_SysReg:
370 SysReg = o.SysReg;
371 break;
372 case k_SysCR:
373 SysCRImm = o.SysCRImm;
374 break;
375 case k_Prefetch:
376 Prefetch = o.Prefetch;
377 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000378 case k_PSBHint:
379 PSBHint = o.PSBHint;
380 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000381 case k_ShiftExtend:
382 ShiftExtend = o.ShiftExtend;
383 break;
384 }
385 }
386
387 /// getStartLoc - Get the location of the first token of this operand.
388 SMLoc getStartLoc() const override { return StartLoc; }
389 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000390 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000391
392 StringRef getToken() const {
393 assert(Kind == k_Token && "Invalid access!");
394 return StringRef(Tok.Data, Tok.Length);
395 }
396
397 bool isTokenSuffix() const {
398 assert(Kind == k_Token && "Invalid access!");
399 return Tok.IsSuffix;
400 }
401
402 const MCExpr *getImm() const {
403 assert(Kind == k_Immediate && "Invalid access!");
404 return Imm.Val;
405 }
406
407 const MCExpr *getShiftedImmVal() const {
408 assert(Kind == k_ShiftedImm && "Invalid access!");
409 return ShiftedImm.Val;
410 }
411
412 unsigned getShiftedImmShift() const {
413 assert(Kind == k_ShiftedImm && "Invalid access!");
414 return ShiftedImm.ShiftAmount;
415 }
416
417 AArch64CC::CondCode getCondCode() const {
418 assert(Kind == k_CondCode && "Invalid access!");
419 return CondCode.Code;
420 }
421
422 unsigned getFPImm() const {
423 assert(Kind == k_FPImm && "Invalid access!");
424 return FPImm.Val;
425 }
426
427 unsigned getBarrier() const {
428 assert(Kind == k_Barrier && "Invalid access!");
429 return Barrier.Val;
430 }
431
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000432 StringRef getBarrierName() const {
433 assert(Kind == k_Barrier && "Invalid access!");
434 return StringRef(Barrier.Data, Barrier.Length);
435 }
436
Tim Northover3b0846e2014-05-24 12:50:23 +0000437 unsigned getReg() const override {
438 assert(Kind == k_Register && "Invalid access!");
439 return Reg.RegNum;
440 }
441
442 unsigned getVectorListStart() const {
443 assert(Kind == k_VectorList && "Invalid access!");
444 return VectorList.RegNum;
445 }
446
447 unsigned getVectorListCount() const {
448 assert(Kind == k_VectorList && "Invalid access!");
449 return VectorList.Count;
450 }
451
452 unsigned getVectorIndex() const {
453 assert(Kind == k_VectorIndex && "Invalid access!");
454 return VectorIndex.Val;
455 }
456
457 StringRef getSysReg() const {
458 assert(Kind == k_SysReg && "Invalid access!");
459 return StringRef(SysReg.Data, SysReg.Length);
460 }
461
Tim Northover3b0846e2014-05-24 12:50:23 +0000462 unsigned getSysCR() const {
463 assert(Kind == k_SysCR && "Invalid access!");
464 return SysCRImm.Val;
465 }
466
467 unsigned getPrefetch() const {
468 assert(Kind == k_Prefetch && "Invalid access!");
469 return Prefetch.Val;
470 }
471
Oliver Stannarda34e4702015-12-01 10:48:51 +0000472 unsigned getPSBHint() const {
473 assert(Kind == k_PSBHint && "Invalid access!");
474 return PSBHint.Val;
475 }
476
477 StringRef getPSBHintName() const {
478 assert(Kind == k_PSBHint && "Invalid access!");
479 return StringRef(PSBHint.Data, PSBHint.Length);
480 }
481
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000482 StringRef getPrefetchName() const {
483 assert(Kind == k_Prefetch && "Invalid access!");
484 return StringRef(Prefetch.Data, Prefetch.Length);
485 }
486
Tim Northover3b0846e2014-05-24 12:50:23 +0000487 AArch64_AM::ShiftExtendType getShiftExtendType() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000488 if (Kind == k_ShiftExtend)
489 return ShiftExtend.Type;
490 if (Kind == k_Register)
491 return Reg.ShiftExtend.Type;
492 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000493 }
494
495 unsigned getShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000496 if (Kind == k_ShiftExtend)
497 return ShiftExtend.Amount;
498 if (Kind == k_Register)
499 return Reg.ShiftExtend.Amount;
500 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000501 }
502
503 bool hasShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000504 if (Kind == k_ShiftExtend)
505 return ShiftExtend.HasExplicitAmount;
506 if (Kind == k_Register)
507 return Reg.ShiftExtend.HasExplicitAmount;
508 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000509 }
510
511 bool isImm() const override { return Kind == k_Immediate; }
512 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000513
514 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
515
Sander de Smalen50ded902018-04-29 17:33:38 +0000516 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
517 return isImmScaled<Bits, Scale>(true);
518 }
519
520 template <int Bits, int Scale> DiagnosticPredicate isUImmScaled() const {
521 return isImmScaled<Bits, Scale>(false);
522 }
523
Sander de Smalenfe17a782018-04-26 12:54:42 +0000524 template <int Bits, int Scale>
Sander de Smalen50ded902018-04-29 17:33:38 +0000525 DiagnosticPredicate isImmScaled(bool Signed) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000526 if (!isImm())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000527 return DiagnosticPredicateTy::NoMatch;
528
Tim Northover3b0846e2014-05-24 12:50:23 +0000529 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
530 if (!MCE)
Sander de Smalenfe17a782018-04-26 12:54:42 +0000531 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000532
Sander de Smalen50ded902018-04-29 17:33:38 +0000533 int64_t MinVal, MaxVal;
534 if (Signed) {
535 int64_t Shift = Bits - 1;
536 MinVal = (int64_t(1) << Shift) * -Scale;
537 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
538 } else {
539 MinVal = 0;
540 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
541 }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000542
Tim Northover3b0846e2014-05-24 12:50:23 +0000543 int64_t Val = MCE->getValue();
Sander de Smalenfe17a782018-04-26 12:54:42 +0000544 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
545 return DiagnosticPredicateTy::Match;
546
547 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +0000548 }
549
Sander de Smalen245e0e62018-01-22 10:46:00 +0000550 bool isSVEPattern() const {
551 if (!isImm())
552 return false;
553 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
554 if (!MCE)
555 return false;
556 int64_t Val = MCE->getValue();
557 return Val >= 0 && Val < 32;
558 }
559
Tim Northover3b0846e2014-05-24 12:50:23 +0000560 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
561 AArch64MCExpr::VariantKind ELFRefKind;
562 MCSymbolRefExpr::VariantKind DarwinRefKind;
563 int64_t Addend;
564 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
565 Addend)) {
566 // If we don't understand the expression, assume the best and
567 // let the fixup and relocation code deal with it.
568 return true;
569 }
570
571 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
572 ELFRefKind == AArch64MCExpr::VK_LO12 ||
573 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
574 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
575 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
576 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
577 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
578 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000579 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
580 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
581 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000582 // Note that we don't range-check the addend. It's adjusted modulo page
583 // size when converted, so there is no "out of range" condition when using
584 // @pageoff.
585 return Addend >= 0 && (Addend % Scale) == 0;
586 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
587 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
588 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
589 return Addend == 0;
590 }
591
592 return false;
593 }
594
595 template <int Scale> bool isUImm12Offset() const {
596 if (!isImm())
597 return false;
598
599 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
600 if (!MCE)
601 return isSymbolicUImm12Offset(getImm(), Scale);
602
603 int64_t Val = MCE->getValue();
604 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
605 }
606
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000607 template <int N, int M>
608 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000609 if (!isImm())
610 return false;
611 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
612 if (!MCE)
613 return false;
614 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000615 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000616 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000617
Sander de Smalena1c259c2018-01-29 13:05:38 +0000618 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
619 // a logical immediate can always be represented when inverted.
620 template <typename T>
621 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000622 if (!isImm())
623 return false;
624 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
625 if (!MCE)
626 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000627
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000628 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000629 int64_t SVal = typename std::make_signed<T>::type(Val);
630 int64_t UVal = typename std::make_unsigned<T>::type(Val);
631 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000632 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000633
Sander de Smalena1c259c2018-01-29 13:05:38 +0000634 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000635 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000636
Tim Northover3b0846e2014-05-24 12:50:23 +0000637 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000638
Sander de Smalen62770792018-05-25 09:47:52 +0000639 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
640 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
641 /// immediate that can be shifted by 'Shift'.
642 template <unsigned Width>
643 Optional<std::pair<int64_t, unsigned> > getShiftedVal() const {
644 if (isShiftedImm() && Width == getShiftedImmShift())
645 if (auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
646 return std::make_pair(CE->getValue(), Width);
647
648 if (isImm())
649 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
650 int64_t Val = CE->getValue();
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000651 if ((Val != 0) && (uint64_t(Val >> Width) << Width) == uint64_t(Val))
Sander de Smalen62770792018-05-25 09:47:52 +0000652 return std::make_pair(Val >> Width, Width);
653 else
654 return std::make_pair(Val, 0u);
655 }
656
657 return {};
658 }
659
Tim Northover3b0846e2014-05-24 12:50:23 +0000660 bool isAddSubImm() const {
661 if (!isShiftedImm() && !isImm())
662 return false;
663
664 const MCExpr *Expr;
665
666 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
667 if (isShiftedImm()) {
668 unsigned Shift = ShiftedImm.ShiftAmount;
669 Expr = ShiftedImm.Val;
670 if (Shift != 0 && Shift != 12)
671 return false;
672 } else {
673 Expr = getImm();
674 }
675
676 AArch64MCExpr::VariantKind ELFRefKind;
677 MCSymbolRefExpr::VariantKind DarwinRefKind;
678 int64_t Addend;
679 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
680 DarwinRefKind, Addend)) {
681 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
682 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
683 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
684 || ELFRefKind == AArch64MCExpr::VK_LO12
685 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
686 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
687 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
688 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
689 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
690 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000691 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
692 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
693 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000694 }
695
Sander de Smalen98686c62018-05-29 10:39:49 +0000696 // If it's a constant, it should be a real immediate in range.
Sander de Smalen62770792018-05-25 09:47:52 +0000697 if (auto ShiftedVal = getShiftedVal<12>())
698 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
Diana Picusc93518d2016-10-11 09:17:47 +0000699
700 // If it's an expression, we hope for the best and let the fixup/relocation
701 // code deal with it.
702 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000703 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000704
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000705 bool isAddSubImmNeg() const {
706 if (!isShiftedImm() && !isImm())
707 return false;
708
Sander de Smalen98686c62018-05-29 10:39:49 +0000709 // Otherwise it should be a real negative immediate in range.
710 if (auto ShiftedVal = getShiftedVal<12>())
711 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000712
Sander de Smalen98686c62018-05-29 10:39:49 +0000713 return false;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000714 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000715
Sander de Smalen62770792018-05-25 09:47:52 +0000716 // Signed value in the range -128 to +127. For element widths of
717 // 16 bits or higher it may also be a signed multiple of 256 in the
718 // range -32768 to +32512.
719 // For element-width of 8 bits a range of -128 to 255 is accepted,
720 // since a copy of a byte can be either signed/unsigned.
721 template <typename T>
722 DiagnosticPredicate isSVECpyImm() const {
723 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
724 return DiagnosticPredicateTy::NoMatch;
725
726 bool IsByte =
727 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
728 if (auto ShiftedImm = getShiftedVal<8>())
729 if (!(IsByte && ShiftedImm->second) &&
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000730 AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
731 << ShiftedImm->second))
Sander de Smalen62770792018-05-25 09:47:52 +0000732 return DiagnosticPredicateTy::Match;
733
734 return DiagnosticPredicateTy::NearMatch;
735 }
736
Sander de Smalen98686c62018-05-29 10:39:49 +0000737 // Unsigned value in the range 0 to 255. For element widths of
738 // 16 bits or higher it may also be a signed multiple of 256 in the
739 // range 0 to 65280.
740 template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
741 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
742 return DiagnosticPredicateTy::NoMatch;
743
744 bool IsByte =
745 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
746 if (auto ShiftedImm = getShiftedVal<8>())
747 if (!(IsByte && ShiftedImm->second) &&
748 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
749 << ShiftedImm->second))
750 return DiagnosticPredicateTy::Match;
751
752 return DiagnosticPredicateTy::NearMatch;
753 }
754
Tim Northover3b0846e2014-05-24 12:50:23 +0000755 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000756
Tim Northover3b0846e2014-05-24 12:50:23 +0000757 bool isSIMDImmType10() const {
758 if (!isImm())
759 return false;
760 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
761 if (!MCE)
762 return false;
763 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
764 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000765
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000766 template<int N>
767 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000768 if (!isImm())
769 return false;
770 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
771 if (!MCE)
772 return true;
773 int64_t Val = MCE->getValue();
774 if (Val & 0x3)
775 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000776 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
777 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000778 }
779
780 bool
781 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
782 if (!isImm())
783 return false;
784
785 AArch64MCExpr::VariantKind ELFRefKind;
786 MCSymbolRefExpr::VariantKind DarwinRefKind;
787 int64_t Addend;
788 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
789 DarwinRefKind, Addend)) {
790 return false;
791 }
792 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
793 return false;
794
795 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
796 if (ELFRefKind == AllowedModifiers[i])
797 return Addend == 0;
798 }
799
800 return false;
801 }
802
803 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000804 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000805 }
806
807 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000808 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
809 AArch64MCExpr::VK_TPREL_G2,
810 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000811 }
812
813 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000814 return isMovWSymbol({
815 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000816 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
817 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000818 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000819 }
820
821 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000822 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
823 AArch64MCExpr::VK_TPREL_G0,
824 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000825 }
826
827 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000828 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000829 }
830
831 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000832 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000833 }
834
835 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000836 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
837 AArch64MCExpr::VK_TPREL_G1_NC,
838 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000839 }
840
841 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000842 return isMovWSymbol(
843 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
844 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000845 }
846
847 template<int RegWidth, int Shift>
848 bool isMOVZMovAlias() const {
849 if (!isImm()) return false;
850
851 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
852 if (!CE) return false;
853 uint64_t Value = CE->getValue();
854
Tim Northoverdaa1c012016-06-16 01:42:25 +0000855 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000856 }
857
858 template<int RegWidth, int Shift>
859 bool isMOVNMovAlias() const {
860 if (!isImm()) return false;
861
862 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
863 if (!CE) return false;
864 uint64_t Value = CE->getValue();
865
Tim Northoverdaa1c012016-06-16 01:42:25 +0000866 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000867 }
868
869 bool isFPImm() const { return Kind == k_FPImm; }
870 bool isBarrier() const { return Kind == k_Barrier; }
871 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000872
Tim Northover3b0846e2014-05-24 12:50:23 +0000873 bool isMRSSystemRegister() const {
874 if (!isSysReg()) return false;
875
Tim Northover7cd58932015-01-22 17:23:04 +0000876 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000877 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000878
Tim Northover3b0846e2014-05-24 12:50:23 +0000879 bool isMSRSystemRegister() const {
880 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000881 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000882 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000883
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000884 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000885 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000886 return (SysReg.PStateField == AArch64PState::PAN ||
887 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000888 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000889
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000890 bool isSystemPStateFieldWithImm0_15() const {
891 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000892 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000893 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000894
Florian Hahnc4422242017-11-07 13:07:50 +0000895 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000896 return Kind == k_Register;
897 }
898
899 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000900 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
901 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000902
Florian Hahnc4422242017-11-07 13:07:50 +0000903 bool isNeonVectorReg() const {
904 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
905 }
906
907 bool isNeonVectorRegLo() const {
908 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000909 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
910 Reg.RegNum);
911 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000912
Sander de Smalencd6be962017-12-20 11:02:42 +0000913 template <unsigned Class> bool isSVEVectorReg() const {
914 RegKind RK;
915 switch (Class) {
916 case AArch64::ZPRRegClassID:
917 RK = RegKind::SVEDataVector;
918 break;
919 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000920 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000921 RK = RegKind::SVEPredicateVector;
922 break;
923 default:
924 llvm_unreachable("Unsupport register class");
925 }
926
927 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000928 AArch64MCRegisterClasses[Class].contains(getReg());
929 }
930
Sander de Smalencd6be962017-12-20 11:02:42 +0000931 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +0000932 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
933 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
934 return DiagnosticPredicateTy::NoMatch;
935
936 if (isSVEVectorReg<Class>() &&
937 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
938 return DiagnosticPredicateTy::Match;
939
940 return DiagnosticPredicateTy::NearMatch;
941 }
942
943 template <int ElementWidth, unsigned Class>
944 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
945 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
946 return DiagnosticPredicateTy::NoMatch;
947
948 if (isSVEVectorReg<Class>() &&
949 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
950 return DiagnosticPredicateTy::Match;
951
952 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +0000953 }
954
Sander de Smaleneb896b12018-04-25 09:26:47 +0000955 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +0000956 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
957 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +0000958 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
959 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
960 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000961 return DiagnosticPredicateTy::NoMatch;
962
Sander de Smalen5861c262018-04-30 07:24:38 +0000963 // Give a more specific diagnostic when the user has explicitly typed in
964 // a shift-amount that does not match what is expected, but for which
965 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
966 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
967 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
968 ShiftExtendTy == AArch64_AM::SXTW) &&
969 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
970 return DiagnosticPredicateTy::NoMatch;
971
972 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000973 return DiagnosticPredicateTy::Match;
974
975 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +0000976 }
977
Tim Northover3b0846e2014-05-24 12:50:23 +0000978 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000979 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000980 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
981 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000982
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000983 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000984 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000985 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
986 Reg.RegNum);
987 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000988
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000989 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000990 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000991 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
992 Reg.RegNum);
993 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000994
Sam Parker5f934642017-08-31 09:27:04 +0000995 template<int64_t Angle, int64_t Remainder>
996 bool isComplexRotation() const {
997 if (!isImm()) return false;
998
999 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1000 if (!CE) return false;
1001 uint64_t Value = CE->getValue();
1002
1003 return (Value % Angle == Remainder && Value <= 270);
1004 }
1005
Sander de Smalen149916d2018-04-20 07:24:20 +00001006 template <unsigned RegClassID> bool isGPR64() const {
1007 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1008 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1009 }
1010
1011 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001012 DiagnosticPredicate isGPR64WithShiftExtend() const {
1013 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1014 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001015
Sander de Smalenfe17a782018-04-26 12:54:42 +00001016 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1017 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1018 return DiagnosticPredicateTy::Match;
1019 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001020 }
1021
Tim Northover3b0846e2014-05-24 12:50:23 +00001022 /// Is this a vector list with the type implicit (presumably attached to the
1023 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001024 template <RegKind VectorKind, unsigned NumRegs>
1025 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001026 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001027 VectorList.NumElements == 0 &&
1028 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001029 }
1030
Sander de Smalen650234b2018-04-12 11:40:52 +00001031 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1032 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001033 bool isTypedVectorList() const {
1034 if (Kind != k_VectorList)
1035 return false;
1036 if (VectorList.Count != NumRegs)
1037 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001038 if (VectorList.RegisterKind != VectorKind)
1039 return false;
1040 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001041 return false;
1042 return VectorList.NumElements == NumElements;
1043 }
1044
1045 bool isVectorIndex1() const {
1046 return Kind == k_VectorIndex && VectorIndex.Val == 1;
1047 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001048
Tim Northover3b0846e2014-05-24 12:50:23 +00001049 bool isVectorIndexB() const {
1050 return Kind == k_VectorIndex && VectorIndex.Val < 16;
1051 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001052
Tim Northover3b0846e2014-05-24 12:50:23 +00001053 bool isVectorIndexH() const {
1054 return Kind == k_VectorIndex && VectorIndex.Val < 8;
1055 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001056
Tim Northover3b0846e2014-05-24 12:50:23 +00001057 bool isVectorIndexS() const {
1058 return Kind == k_VectorIndex && VectorIndex.Val < 4;
1059 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001060
Tim Northover3b0846e2014-05-24 12:50:23 +00001061 bool isVectorIndexD() const {
1062 return Kind == k_VectorIndex && VectorIndex.Val < 2;
1063 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001064
Tim Northover3b0846e2014-05-24 12:50:23 +00001065 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001066
Tim Northover3b0846e2014-05-24 12:50:23 +00001067 bool isTokenEqual(StringRef Str) const {
1068 return Kind == k_Token && getToken() == Str;
1069 }
1070 bool isSysCR() const { return Kind == k_SysCR; }
1071 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001072 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001073 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1074 bool isShifter() const {
1075 if (!isShiftExtend())
1076 return false;
1077
1078 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1079 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1080 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1081 ST == AArch64_AM::MSL);
1082 }
1083 bool isExtend() const {
1084 if (!isShiftExtend())
1085 return false;
1086
1087 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1088 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1089 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1090 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1091 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1092 ET == AArch64_AM::LSL) &&
1093 getShiftExtendAmount() <= 4;
1094 }
1095
1096 bool isExtend64() const {
1097 if (!isExtend())
1098 return false;
1099 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1100 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1101 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1102 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001103
Tim Northover3b0846e2014-05-24 12:50:23 +00001104 bool isExtendLSL64() const {
1105 if (!isExtend())
1106 return false;
1107 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1108 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1109 ET == AArch64_AM::LSL) &&
1110 getShiftExtendAmount() <= 4;
1111 }
1112
1113 template<int Width> bool isMemXExtend() const {
1114 if (!isExtend())
1115 return false;
1116 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1117 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1118 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1119 getShiftExtendAmount() == 0);
1120 }
1121
1122 template<int Width> bool isMemWExtend() const {
1123 if (!isExtend())
1124 return false;
1125 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1126 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1127 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1128 getShiftExtendAmount() == 0);
1129 }
1130
1131 template <unsigned width>
1132 bool isArithmeticShifter() const {
1133 if (!isShifter())
1134 return false;
1135
1136 // An arithmetic shifter is LSL, LSR, or ASR.
1137 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1138 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1139 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1140 }
1141
1142 template <unsigned width>
1143 bool isLogicalShifter() const {
1144 if (!isShifter())
1145 return false;
1146
1147 // A logical shifter is LSL, LSR, ASR or ROR.
1148 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1149 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1150 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1151 getShiftExtendAmount() < width;
1152 }
1153
1154 bool isMovImm32Shifter() const {
1155 if (!isShifter())
1156 return false;
1157
1158 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1159 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1160 if (ST != AArch64_AM::LSL)
1161 return false;
1162 uint64_t Val = getShiftExtendAmount();
1163 return (Val == 0 || Val == 16);
1164 }
1165
1166 bool isMovImm64Shifter() const {
1167 if (!isShifter())
1168 return false;
1169
1170 // A MOVi shifter is LSL of 0 or 16.
1171 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1172 if (ST != AArch64_AM::LSL)
1173 return false;
1174 uint64_t Val = getShiftExtendAmount();
1175 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1176 }
1177
1178 bool isLogicalVecShifter() const {
1179 if (!isShifter())
1180 return false;
1181
1182 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1183 unsigned Shift = getShiftExtendAmount();
1184 return getShiftExtendType() == AArch64_AM::LSL &&
1185 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1186 }
1187
1188 bool isLogicalVecHalfWordShifter() const {
1189 if (!isLogicalVecShifter())
1190 return false;
1191
1192 // A logical vector shifter is a left shift by 0 or 8.
1193 unsigned Shift = getShiftExtendAmount();
1194 return getShiftExtendType() == AArch64_AM::LSL &&
1195 (Shift == 0 || Shift == 8);
1196 }
1197
1198 bool isMoveVecShifter() const {
1199 if (!isShiftExtend())
1200 return false;
1201
1202 // A logical vector shifter is a left shift by 8 or 16.
1203 unsigned Shift = getShiftExtendAmount();
1204 return getShiftExtendType() == AArch64_AM::MSL &&
1205 (Shift == 8 || Shift == 16);
1206 }
1207
1208 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1209 // to LDUR/STUR when the offset is not legal for the former but is for
1210 // the latter. As such, in addition to checking for being a legal unscaled
1211 // address, also check that it is not a legal scaled address. This avoids
1212 // ambiguity in the matcher.
1213 template<int Width>
1214 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001215 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001216 }
1217
1218 bool isAdrpLabel() const {
1219 // Validation was handled during parsing, so we just sanity check that
1220 // something didn't go haywire.
1221 if (!isImm())
1222 return false;
1223
1224 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1225 int64_t Val = CE->getValue();
1226 int64_t Min = - (4096 * (1LL << (21 - 1)));
1227 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1228 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1229 }
1230
1231 return true;
1232 }
1233
1234 bool isAdrLabel() const {
1235 // Validation was handled during parsing, so we just sanity check that
1236 // something didn't go haywire.
1237 if (!isImm())
1238 return false;
1239
1240 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1241 int64_t Val = CE->getValue();
1242 int64_t Min = - (1LL << (21 - 1));
1243 int64_t Max = ((1LL << (21 - 1)) - 1);
1244 return Val >= Min && Val <= Max;
1245 }
1246
1247 return true;
1248 }
1249
1250 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1251 // Add as immediates when possible. Null MCExpr = 0.
1252 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001253 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001254 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001255 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001256 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001257 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001258 }
1259
1260 void addRegOperands(MCInst &Inst, unsigned N) const {
1261 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001262 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001263 }
1264
1265 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1266 assert(N == 1 && "Invalid number of operands!");
1267 assert(
1268 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1269
1270 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1271 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1272 RI->getEncodingValue(getReg()));
1273
Jim Grosbache9119e42015-05-13 18:37:00 +00001274 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001275 }
1276
1277 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1278 assert(N == 1 && "Invalid number of operands!");
1279 assert(
1280 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001281 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001282 }
1283
1284 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1285 assert(N == 1 && "Invalid number of operands!");
1286 assert(
1287 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001288 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001289 }
1290
1291 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1292 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001293 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001294 }
1295
Sander de Smalen525e3222018-04-12 13:19:32 +00001296 enum VecListIndexType {
1297 VecListIdx_DReg = 0,
1298 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001299 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001300 };
1301
1302 template <VecListIndexType RegTy, unsigned NumRegs>
1303 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001304 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001305 static const unsigned FirstRegs[][5] = {
1306 /* DReg */ { AArch64::Q0,
1307 AArch64::D0, AArch64::D0_D1,
1308 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1309 /* QReg */ { AArch64::Q0,
1310 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001311 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1312 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001313 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001314 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001315 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001316
Sander de Smalen7a210db2018-04-16 10:46:18 +00001317 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1318 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001319
Sander de Smalen525e3222018-04-12 13:19:32 +00001320 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1321 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1322 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001323 }
1324
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001325 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001326 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001327 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001328 }
1329
1330 void addImmOperands(MCInst &Inst, unsigned N) const {
1331 assert(N == 1 && "Invalid number of operands!");
1332 // If this is a pageoff symrefexpr with an addend, adjust the addend
1333 // to be only the page-offset portion. Otherwise, just add the expr
1334 // as-is.
1335 addExpr(Inst, getImm());
1336 }
1337
Sander de Smalen62770792018-05-25 09:47:52 +00001338 template <int Shift>
1339 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001340 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001341 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1342 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1343 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1344 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001345 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001346 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001347 } else {
1348 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001349 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001350 }
1351 }
1352
Sander de Smalen62770792018-05-25 09:47:52 +00001353 template <int Shift>
1354 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001355 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001356 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1357 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1358 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1359 } else
1360 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001361 }
1362
Tim Northover3b0846e2014-05-24 12:50:23 +00001363 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1364 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001365 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001366 }
1367
1368 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1369 assert(N == 1 && "Invalid number of operands!");
1370 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1371 if (!MCE)
1372 addExpr(Inst, getImm());
1373 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001374 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001375 }
1376
1377 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1378 addImmOperands(Inst, N);
1379 }
1380
1381 template<int Scale>
1382 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1383 assert(N == 1 && "Invalid number of operands!");
1384 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1385
1386 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001387 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001388 return;
1389 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001390 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001391 }
1392
Sander de Smalen5c625982018-04-13 12:56:14 +00001393 template <int Scale>
1394 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1395 assert(N == 1 && "Invalid number of operands!");
1396 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1397 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1398 }
1399
Sander de Smalena1c259c2018-01-29 13:05:38 +00001400 template <typename T>
1401 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001402 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001403 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001404 typename std::make_unsigned<T>::type Val = MCE->getValue();
1405 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001406 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001407 }
1408
Sander de Smalena1c259c2018-01-29 13:05:38 +00001409 template <typename T>
1410 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001411 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001412 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001413 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1414 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001415 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001416 }
1417
Tim Northover3b0846e2014-05-24 12:50:23 +00001418 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1419 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001420 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001421 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001422 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001423 }
1424
1425 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1426 // Branch operands don't encode the low bits, so shift them off
1427 // here. If it's a label, however, just put it on directly as there's
1428 // not enough information now to do anything.
1429 assert(N == 1 && "Invalid number of operands!");
1430 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1431 if (!MCE) {
1432 addExpr(Inst, getImm());
1433 return;
1434 }
1435 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001436 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001437 }
1438
1439 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1440 // Branch operands don't encode the low bits, so shift them off
1441 // here. If it's a label, however, just put it on directly as there's
1442 // not enough information now to do anything.
1443 assert(N == 1 && "Invalid number of operands!");
1444 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1445 if (!MCE) {
1446 addExpr(Inst, getImm());
1447 return;
1448 }
1449 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001450 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001451 }
1452
1453 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1454 // Branch operands don't encode the low bits, so shift them off
1455 // here. If it's a label, however, just put it on directly as there's
1456 // not enough information now to do anything.
1457 assert(N == 1 && "Invalid number of operands!");
1458 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1459 if (!MCE) {
1460 addExpr(Inst, getImm());
1461 return;
1462 }
1463 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001464 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001465 }
1466
1467 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1468 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001469 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001470 }
1471
1472 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1473 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001474 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001475 }
1476
1477 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1478 assert(N == 1 && "Invalid number of operands!");
1479
Jim Grosbache9119e42015-05-13 18:37:00 +00001480 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001481 }
1482
1483 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1484 assert(N == 1 && "Invalid number of operands!");
1485
Jim Grosbache9119e42015-05-13 18:37:00 +00001486 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001487 }
1488
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001489 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1490 assert(N == 1 && "Invalid number of operands!");
1491
1492 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1493 }
1494
1495 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001496 assert(N == 1 && "Invalid number of operands!");
1497
Jim Grosbache9119e42015-05-13 18:37:00 +00001498 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001499 }
1500
1501 void addSysCROperands(MCInst &Inst, unsigned N) const {
1502 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001503 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001504 }
1505
1506 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1507 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001508 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001509 }
1510
Oliver Stannarda34e4702015-12-01 10:48:51 +00001511 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1512 assert(N == 1 && "Invalid number of operands!");
1513 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1514 }
1515
Tim Northover3b0846e2014-05-24 12:50:23 +00001516 void addShifterOperands(MCInst &Inst, unsigned N) const {
1517 assert(N == 1 && "Invalid number of operands!");
1518 unsigned Imm =
1519 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001520 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001521 }
1522
1523 void addExtendOperands(MCInst &Inst, unsigned N) const {
1524 assert(N == 1 && "Invalid number of operands!");
1525 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1526 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1527 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001528 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001529 }
1530
1531 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1532 assert(N == 1 && "Invalid number of operands!");
1533 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1534 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1535 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001536 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001537 }
1538
1539 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1540 assert(N == 2 && "Invalid number of operands!");
1541 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1542 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001543 Inst.addOperand(MCOperand::createImm(IsSigned));
1544 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001545 }
1546
1547 // For 8-bit load/store instructions with a register offset, both the
1548 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1549 // they're disambiguated by whether the shift was explicit or implicit rather
1550 // than its size.
1551 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1552 assert(N == 2 && "Invalid number of operands!");
1553 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1554 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001555 Inst.addOperand(MCOperand::createImm(IsSigned));
1556 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001557 }
1558
1559 template<int Shift>
1560 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1561 assert(N == 1 && "Invalid number of operands!");
1562
1563 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1564 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001565 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001566 }
1567
1568 template<int Shift>
1569 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1570 assert(N == 1 && "Invalid number of operands!");
1571
1572 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1573 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001574 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001575 }
1576
Sam Parker5f934642017-08-31 09:27:04 +00001577 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1578 assert(N == 1 && "Invalid number of operands!");
1579 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1580 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1581 }
1582
1583 void addComplexRotationOddOperands(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() - 90) / 180));
1587 }
1588
Tim Northover3b0846e2014-05-24 12:50:23 +00001589 void print(raw_ostream &OS) const override;
1590
David Blaikie960ea3f2014-06-08 16:18:35 +00001591 static std::unique_ptr<AArch64Operand>
1592 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1593 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001594 Op->Tok.Data = Str.data();
1595 Op->Tok.Length = Str.size();
1596 Op->Tok.IsSuffix = IsSuffix;
1597 Op->StartLoc = S;
1598 Op->EndLoc = S;
1599 return Op;
1600 }
1601
David Blaikie960ea3f2014-06-08 16:18:35 +00001602 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001603 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
1604 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1605 unsigned ShiftAmount = 0,
1606 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001607 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001608 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001609 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001610 Op->Reg.ElementWidth = 0;
1611 Op->Reg.ShiftExtend.Type = ExtTy;
1612 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1613 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001614 Op->StartLoc = S;
1615 Op->EndLoc = E;
1616 return Op;
1617 }
1618
David Blaikie960ea3f2014-06-08 16:18:35 +00001619 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001620 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001621 SMLoc S, SMLoc E, MCContext &Ctx,
1622 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1623 unsigned ShiftAmount = 0,
1624 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001625 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1626 Kind == RegKind::SVEPredicateVector) &&
1627 "Invalid vector kind");
Sander de Smalen149916d2018-04-20 07:24:20 +00001628 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, ExtTy, ShiftAmount,
1629 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001630 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001631 return Op;
1632 }
1633
1634 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001635 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001636 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1637 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001638 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001639 Op->VectorList.RegNum = RegNum;
1640 Op->VectorList.Count = Count;
1641 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001642 Op->VectorList.ElementWidth = ElementWidth;
1643 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001644 Op->StartLoc = S;
1645 Op->EndLoc = E;
1646 return Op;
1647 }
1648
David Blaikie960ea3f2014-06-08 16:18:35 +00001649 static std::unique_ptr<AArch64Operand>
1650 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1651 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001652 Op->VectorIndex.Val = Idx;
1653 Op->StartLoc = S;
1654 Op->EndLoc = E;
1655 return Op;
1656 }
1657
David Blaikie960ea3f2014-06-08 16:18:35 +00001658 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1659 SMLoc E, MCContext &Ctx) {
1660 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001661 Op->Imm.Val = Val;
1662 Op->StartLoc = S;
1663 Op->EndLoc = E;
1664 return Op;
1665 }
1666
David Blaikie960ea3f2014-06-08 16:18:35 +00001667 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1668 unsigned ShiftAmount,
1669 SMLoc S, SMLoc E,
1670 MCContext &Ctx) {
1671 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001672 Op->ShiftedImm .Val = Val;
1673 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1674 Op->StartLoc = S;
1675 Op->EndLoc = E;
1676 return Op;
1677 }
1678
David Blaikie960ea3f2014-06-08 16:18:35 +00001679 static std::unique_ptr<AArch64Operand>
1680 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1681 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001682 Op->CondCode.Code = Code;
1683 Op->StartLoc = S;
1684 Op->EndLoc = E;
1685 return Op;
1686 }
1687
David Blaikie960ea3f2014-06-08 16:18:35 +00001688 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1689 MCContext &Ctx) {
1690 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001691 Op->FPImm.Val = Val;
1692 Op->StartLoc = S;
1693 Op->EndLoc = S;
1694 return Op;
1695 }
1696
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001697 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1698 StringRef Str,
1699 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001700 MCContext &Ctx) {
1701 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001702 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001703 Op->Barrier.Data = Str.data();
1704 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001705 Op->StartLoc = S;
1706 Op->EndLoc = S;
1707 return Op;
1708 }
1709
Tim Northover7cd58932015-01-22 17:23:04 +00001710 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1711 uint32_t MRSReg,
1712 uint32_t MSRReg,
1713 uint32_t PStateField,
1714 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001715 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001716 Op->SysReg.Data = Str.data();
1717 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001718 Op->SysReg.MRSReg = MRSReg;
1719 Op->SysReg.MSRReg = MSRReg;
1720 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001721 Op->StartLoc = S;
1722 Op->EndLoc = S;
1723 return Op;
1724 }
1725
David Blaikie960ea3f2014-06-08 16:18:35 +00001726 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1727 SMLoc E, MCContext &Ctx) {
1728 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001729 Op->SysCRImm.Val = Val;
1730 Op->StartLoc = S;
1731 Op->EndLoc = E;
1732 return Op;
1733 }
1734
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001735 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1736 StringRef Str,
1737 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001738 MCContext &Ctx) {
1739 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001740 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001741 Op->Barrier.Data = Str.data();
1742 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001743 Op->StartLoc = S;
1744 Op->EndLoc = S;
1745 return Op;
1746 }
1747
Oliver Stannarda34e4702015-12-01 10:48:51 +00001748 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1749 StringRef Str,
1750 SMLoc S,
1751 MCContext &Ctx) {
1752 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1753 Op->PSBHint.Val = Val;
1754 Op->PSBHint.Data = Str.data();
1755 Op->PSBHint.Length = Str.size();
1756 Op->StartLoc = S;
1757 Op->EndLoc = S;
1758 return Op;
1759 }
1760
David Blaikie960ea3f2014-06-08 16:18:35 +00001761 static std::unique_ptr<AArch64Operand>
1762 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1763 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1764 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001765 Op->ShiftExtend.Type = ShOp;
1766 Op->ShiftExtend.Amount = Val;
1767 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1768 Op->StartLoc = S;
1769 Op->EndLoc = E;
1770 return Op;
1771 }
1772};
1773
1774} // end anonymous namespace.
1775
1776void AArch64Operand::print(raw_ostream &OS) const {
1777 switch (Kind) {
1778 case k_FPImm:
1779 OS << "<fpimm " << getFPImm() << "("
1780 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1781 break;
1782 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001783 StringRef Name = getBarrierName();
1784 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001785 OS << "<barrier " << Name << ">";
1786 else
1787 OS << "<barrier invalid #" << getBarrier() << ">";
1788 break;
1789 }
1790 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001791 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001792 break;
1793 case k_ShiftedImm: {
1794 unsigned Shift = getShiftedImmShift();
1795 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001796 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001797 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1798 break;
1799 }
1800 case k_CondCode:
1801 OS << "<condcode " << getCondCode() << ">";
1802 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001803 case k_VectorList: {
1804 OS << "<vectorlist ";
1805 unsigned Reg = getVectorListStart();
1806 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1807 OS << Reg + i << " ";
1808 OS << ">";
1809 break;
1810 }
1811 case k_VectorIndex:
1812 OS << "<vectorindex " << getVectorIndex() << ">";
1813 break;
1814 case k_SysReg:
1815 OS << "<sysreg: " << getSysReg() << '>';
1816 break;
1817 case k_Token:
1818 OS << "'" << getToken() << "'";
1819 break;
1820 case k_SysCR:
1821 OS << "c" << getSysCR();
1822 break;
1823 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001824 StringRef Name = getPrefetchName();
1825 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001826 OS << "<prfop " << Name << ">";
1827 else
1828 OS << "<prfop invalid #" << getPrefetch() << ">";
1829 break;
1830 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001831 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001832 OS << getPSBHintName();
1833 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00001834 case k_Register:
1835 OS << "<register " << getReg() << ">";
1836 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
1837 break;
1838 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001839 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001840 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1841 << getShiftExtendAmount();
1842 if (!hasShiftExtendAmount())
1843 OS << "<imp>";
1844 OS << '>';
1845 break;
1846 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001847}
1848
1849/// @name Auto-generated Match Functions
1850/// {
1851
1852static unsigned MatchRegisterName(StringRef Name);
1853
1854/// }
1855
Florian Hahnc4422242017-11-07 13:07:50 +00001856static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001857 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001858 .Case("v0", AArch64::Q0)
1859 .Case("v1", AArch64::Q1)
1860 .Case("v2", AArch64::Q2)
1861 .Case("v3", AArch64::Q3)
1862 .Case("v4", AArch64::Q4)
1863 .Case("v5", AArch64::Q5)
1864 .Case("v6", AArch64::Q6)
1865 .Case("v7", AArch64::Q7)
1866 .Case("v8", AArch64::Q8)
1867 .Case("v9", AArch64::Q9)
1868 .Case("v10", AArch64::Q10)
1869 .Case("v11", AArch64::Q11)
1870 .Case("v12", AArch64::Q12)
1871 .Case("v13", AArch64::Q13)
1872 .Case("v14", AArch64::Q14)
1873 .Case("v15", AArch64::Q15)
1874 .Case("v16", AArch64::Q16)
1875 .Case("v17", AArch64::Q17)
1876 .Case("v18", AArch64::Q18)
1877 .Case("v19", AArch64::Q19)
1878 .Case("v20", AArch64::Q20)
1879 .Case("v21", AArch64::Q21)
1880 .Case("v22", AArch64::Q22)
1881 .Case("v23", AArch64::Q23)
1882 .Case("v24", AArch64::Q24)
1883 .Case("v25", AArch64::Q25)
1884 .Case("v26", AArch64::Q26)
1885 .Case("v27", AArch64::Q27)
1886 .Case("v28", AArch64::Q28)
1887 .Case("v29", AArch64::Q29)
1888 .Case("v30", AArch64::Q30)
1889 .Case("v31", AArch64::Q31)
1890 .Default(0);
1891}
1892
Sander de Smalen73937b72018-04-11 07:36:10 +00001893/// Returns an optional pair of (#elements, element-width) if Suffix
1894/// is a valid vector kind. Where the number of elements in a vector
1895/// or the vector width is implicit or explicitly unknown (but still a
1896/// valid suffix kind), 0 is used.
1897static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1898 RegKind VectorKind) {
1899 std::pair<int, int> Res = {-1, -1};
1900
1901 switch (VectorKind) {
1902 case RegKind::NeonVector:
1903 Res =
1904 StringSwitch<std::pair<int, int>>(Suffix.lower())
1905 .Case("", {0, 0})
1906 .Case(".1d", {1, 64})
1907 .Case(".1q", {1, 128})
1908 // '.2h' needed for fp16 scalar pairwise reductions
1909 .Case(".2h", {2, 16})
1910 .Case(".2s", {2, 32})
1911 .Case(".2d", {2, 64})
1912 // '.4b' is another special case for the ARMv8.2a dot product
1913 // operand
1914 .Case(".4b", {4, 8})
1915 .Case(".4h", {4, 16})
1916 .Case(".4s", {4, 32})
1917 .Case(".8b", {8, 8})
1918 .Case(".8h", {8, 16})
1919 .Case(".16b", {16, 8})
1920 // Accept the width neutral ones, too, for verbose syntax. If those
1921 // aren't used in the right places, the token operand won't match so
1922 // all will work out.
1923 .Case(".b", {0, 8})
1924 .Case(".h", {0, 16})
1925 .Case(".s", {0, 32})
1926 .Case(".d", {0, 64})
1927 .Default({-1, -1});
1928 break;
1929 case RegKind::SVEPredicateVector:
1930 case RegKind::SVEDataVector:
1931 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1932 .Case("", {0, 0})
1933 .Case(".b", {0, 8})
1934 .Case(".h", {0, 16})
1935 .Case(".s", {0, 32})
1936 .Case(".d", {0, 64})
1937 .Case(".q", {0, 128})
1938 .Default({-1, -1});
1939 break;
1940 default:
1941 llvm_unreachable("Unsupported RegKind");
1942 }
1943
1944 if (Res == std::make_pair(-1, -1))
1945 return Optional<std::pair<int, int>>();
1946
1947 return Optional<std::pair<int, int>>(Res);
1948}
1949
1950static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1951 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001952}
1953
Florian Hahn91f11e52017-11-07 16:45:48 +00001954static unsigned matchSVEDataVectorRegName(StringRef Name) {
1955 return StringSwitch<unsigned>(Name.lower())
1956 .Case("z0", AArch64::Z0)
1957 .Case("z1", AArch64::Z1)
1958 .Case("z2", AArch64::Z2)
1959 .Case("z3", AArch64::Z3)
1960 .Case("z4", AArch64::Z4)
1961 .Case("z5", AArch64::Z5)
1962 .Case("z6", AArch64::Z6)
1963 .Case("z7", AArch64::Z7)
1964 .Case("z8", AArch64::Z8)
1965 .Case("z9", AArch64::Z9)
1966 .Case("z10", AArch64::Z10)
1967 .Case("z11", AArch64::Z11)
1968 .Case("z12", AArch64::Z12)
1969 .Case("z13", AArch64::Z13)
1970 .Case("z14", AArch64::Z14)
1971 .Case("z15", AArch64::Z15)
1972 .Case("z16", AArch64::Z16)
1973 .Case("z17", AArch64::Z17)
1974 .Case("z18", AArch64::Z18)
1975 .Case("z19", AArch64::Z19)
1976 .Case("z20", AArch64::Z20)
1977 .Case("z21", AArch64::Z21)
1978 .Case("z22", AArch64::Z22)
1979 .Case("z23", AArch64::Z23)
1980 .Case("z24", AArch64::Z24)
1981 .Case("z25", AArch64::Z25)
1982 .Case("z26", AArch64::Z26)
1983 .Case("z27", AArch64::Z27)
1984 .Case("z28", AArch64::Z28)
1985 .Case("z29", AArch64::Z29)
1986 .Case("z30", AArch64::Z30)
1987 .Case("z31", AArch64::Z31)
1988 .Default(0);
1989}
1990
Sander de Smalencd6be962017-12-20 11:02:42 +00001991static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1992 return StringSwitch<unsigned>(Name.lower())
1993 .Case("p0", AArch64::P0)
1994 .Case("p1", AArch64::P1)
1995 .Case("p2", AArch64::P2)
1996 .Case("p3", AArch64::P3)
1997 .Case("p4", AArch64::P4)
1998 .Case("p5", AArch64::P5)
1999 .Case("p6", AArch64::P6)
2000 .Case("p7", AArch64::P7)
2001 .Case("p8", AArch64::P8)
2002 .Case("p9", AArch64::P9)
2003 .Case("p10", AArch64::P10)
2004 .Case("p11", AArch64::P11)
2005 .Case("p12", AArch64::P12)
2006 .Case("p13", AArch64::P13)
2007 .Case("p14", AArch64::P14)
2008 .Case("p15", AArch64::P15)
2009 .Default(0);
2010}
2011
Tim Northover3b0846e2014-05-24 12:50:23 +00002012bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2013 SMLoc &EndLoc) {
2014 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002015 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002016 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002017 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002018}
2019
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002020// Matches a register name or register alias previously defined by '.req'
2021unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002022 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002023 unsigned RegNum = 0;
2024 if ((RegNum = matchSVEDataVectorRegName(Name)))
2025 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2026
Sander de Smalencd6be962017-12-20 11:02:42 +00002027 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2028 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2029
Sander de Smalenc067c302017-12-20 09:45:45 +00002030 if ((RegNum = MatchNeonVectorRegName(Name)))
2031 return Kind == RegKind::NeonVector ? RegNum : 0;
2032
2033 // The parsed register must be of RegKind Scalar
2034 if ((RegNum = MatchRegisterName(Name)))
2035 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002036
Florian Hahnc4422242017-11-07 13:07:50 +00002037 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002038 // Handle a few common aliases of registers.
2039 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2040 .Case("fp", AArch64::FP)
2041 .Case("lr", AArch64::LR)
2042 .Case("x31", AArch64::XZR)
2043 .Case("w31", AArch64::WZR)
2044 .Default(0))
2045 return Kind == RegKind::Scalar ? RegNum : 0;
2046
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002047 // Check for aliases registered via .req. Canonicalize to lower case.
2048 // That's more consistent since register names are case insensitive, and
2049 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2050 auto Entry = RegisterReqs.find(Name.lower());
2051 if (Entry == RegisterReqs.end())
2052 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002053
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002054 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002055 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002056 RegNum = Entry->getValue().second;
2057 }
2058 return RegNum;
2059}
2060
Sander de Smalen50d87022018-04-19 07:35:08 +00002061/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002062/// Identifier when called, and if it is a register name the token is eaten and
2063/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002064OperandMatchResultTy
2065AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002066 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002067 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002068 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002069 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002070
2071 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002072 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2073 if (Reg == 0)
2074 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002075
Sander de Smalen50d87022018-04-19 07:35:08 +00002076 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002077 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002078 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002079}
2080
Tim Northover3b0846e2014-05-24 12:50:23 +00002081/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002082OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002083AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002084 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002085 SMLoc S = getLoc();
2086
2087 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2088 Error(S, "Expected cN operand where 0 <= N <= 15");
2089 return MatchOperand_ParseFail;
2090 }
2091
2092 StringRef Tok = Parser.getTok().getIdentifier();
2093 if (Tok[0] != 'c' && Tok[0] != 'C') {
2094 Error(S, "Expected cN operand where 0 <= N <= 15");
2095 return MatchOperand_ParseFail;
2096 }
2097
2098 uint32_t CRNum;
2099 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2100 if (BadNum || CRNum > 15) {
2101 Error(S, "Expected cN operand where 0 <= N <= 15");
2102 return MatchOperand_ParseFail;
2103 }
2104
2105 Parser.Lex(); // Eat identifier token.
2106 Operands.push_back(
2107 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2108 return MatchOperand_Success;
2109}
2110
2111/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002112template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002113OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002114AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002115 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002116 SMLoc S = getLoc();
2117 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002118
2119 auto LookupByName = [](StringRef N) {
2120 if (IsSVEPrefetch) {
2121 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2122 return Optional<unsigned>(Res->Encoding);
2123 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2124 return Optional<unsigned>(Res->Encoding);
2125 return Optional<unsigned>();
2126 };
2127
2128 auto LookupByEncoding = [](unsigned E) {
2129 if (IsSVEPrefetch) {
2130 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2131 return Optional<StringRef>(Res->Name);
2132 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2133 return Optional<StringRef>(Res->Name);
2134 return Optional<StringRef>();
2135 };
2136 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2137
Tim Northover3b0846e2014-05-24 12:50:23 +00002138 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002139 // Eat optional hash.
2140 if (parseOptionalToken(AsmToken::Hash) ||
2141 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002142 const MCExpr *ImmVal;
2143 if (getParser().parseExpression(ImmVal))
2144 return MatchOperand_ParseFail;
2145
2146 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2147 if (!MCE) {
2148 TokError("immediate value expected for prefetch operand");
2149 return MatchOperand_ParseFail;
2150 }
2151 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002152 if (prfop > MaxVal) {
2153 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2154 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002155 return MatchOperand_ParseFail;
2156 }
2157
Sander de Smalen93380372018-05-14 11:54:41 +00002158 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002159 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002160 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002161 return MatchOperand_Success;
2162 }
2163
2164 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002165 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002166 return MatchOperand_ParseFail;
2167 }
2168
Sander de Smalen93380372018-05-14 11:54:41 +00002169 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002170 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002171 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002172 return MatchOperand_ParseFail;
2173 }
2174
2175 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002176 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002177 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002178 return MatchOperand_Success;
2179}
2180
Oliver Stannarda34e4702015-12-01 10:48:51 +00002181/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002182OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002183AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2184 MCAsmParser &Parser = getParser();
2185 SMLoc S = getLoc();
2186 const AsmToken &Tok = Parser.getTok();
2187 if (Tok.isNot(AsmToken::Identifier)) {
2188 TokError("invalid operand for instruction");
2189 return MatchOperand_ParseFail;
2190 }
2191
Tim Northovere6ae6762016-07-05 21:23:04 +00002192 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2193 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002194 TokError("invalid operand for instruction");
2195 return MatchOperand_ParseFail;
2196 }
2197
2198 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002199 Operands.push_back(AArch64Operand::CreatePSBHint(
2200 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002201 return MatchOperand_Success;
2202}
2203
Tim Northover3b0846e2014-05-24 12:50:23 +00002204/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2205/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002206OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002207AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002208 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002209 SMLoc S = getLoc();
2210 const MCExpr *Expr;
2211
2212 if (Parser.getTok().is(AsmToken::Hash)) {
2213 Parser.Lex(); // Eat hash token.
2214 }
2215
2216 if (parseSymbolicImmVal(Expr))
2217 return MatchOperand_ParseFail;
2218
2219 AArch64MCExpr::VariantKind ELFRefKind;
2220 MCSymbolRefExpr::VariantKind DarwinRefKind;
2221 int64_t Addend;
2222 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2223 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2224 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2225 // No modifier was specified at all; this is the syntax for an ELF basic
2226 // ADRP relocation (unfortunately).
2227 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002228 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002229 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2230 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2231 Addend != 0) {
2232 Error(S, "gotpage label reference not allowed an addend");
2233 return MatchOperand_ParseFail;
2234 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2235 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2236 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2237 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2238 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2239 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2240 // The operand must be an @page or @gotpage qualified symbolref.
2241 Error(S, "page or gotpage label reference expected");
2242 return MatchOperand_ParseFail;
2243 }
2244 }
2245
2246 // We have either a label reference possibly with addend or an immediate. The
2247 // addend is a raw value here. The linker will adjust it to only reference the
2248 // page.
2249 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2250 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2251
2252 return MatchOperand_Success;
2253}
2254
2255/// tryParseAdrLabel - Parse and validate a source label for the ADR
2256/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002257OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002258AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2259 SMLoc S = getLoc();
2260 const MCExpr *Expr;
2261
Nirav Davee833c6c2016-11-08 18:31:04 +00002262 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002263 if (getParser().parseExpression(Expr))
2264 return MatchOperand_ParseFail;
2265
2266 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2267 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2268
2269 return MatchOperand_Success;
2270}
2271
2272/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002273OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002274AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002275 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002276 SMLoc S = getLoc();
2277
Nirav Davee833c6c2016-11-08 18:31:04 +00002278 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002279
2280 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002281 bool isNegative = parseOptionalToken(AsmToken::Minus);
2282
Tim Northover3b0846e2014-05-24 12:50:23 +00002283 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002284 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002285 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002286 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002287 Val = Tok.getIntVal();
2288 if (Val > 255 || Val < 0) {
2289 TokError("encoded floating point value out of range");
2290 return MatchOperand_ParseFail;
2291 }
2292 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002293 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002294 if (isNegative)
2295 RealVal.changeSign();
2296
Tim Northover3b0846e2014-05-24 12:50:23 +00002297 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002298 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002299
John Brawn5ca5daa2017-04-20 10:13:54 +00002300 // Check for out of range values. As an exception we let Zero through,
2301 // but as tokens instead of an FPImm so that it can be matched by the
2302 // appropriate alias if one exists.
2303 if (RealVal.isPosZero()) {
2304 Parser.Lex(); // Eat the token.
2305 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2306 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2307 return MatchOperand_Success;
2308 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002309 TokError("expected compatible register or floating-point constant");
2310 return MatchOperand_ParseFail;
2311 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002312 }
2313 Parser.Lex(); // Eat the token.
2314 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2315 return MatchOperand_Success;
2316 }
2317
2318 if (!Hash)
2319 return MatchOperand_NoMatch;
2320
2321 TokError("invalid floating point immediate");
2322 return MatchOperand_ParseFail;
2323}
2324
Sander de Smalen62770792018-05-25 09:47:52 +00002325/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2326/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002327OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002328AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002329 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002330 SMLoc S = getLoc();
2331
2332 if (Parser.getTok().is(AsmToken::Hash))
2333 Parser.Lex(); // Eat '#'
2334 else if (Parser.getTok().isNot(AsmToken::Integer))
2335 // Operand should start from # or should be integer, emit error otherwise.
2336 return MatchOperand_NoMatch;
2337
2338 const MCExpr *Imm;
2339 if (parseSymbolicImmVal(Imm))
2340 return MatchOperand_ParseFail;
2341 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002342 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002343 Operands.push_back(
2344 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002345 return MatchOperand_Success;
2346 }
2347
2348 // Eat ','
2349 Parser.Lex();
2350
2351 // The optional operand must be "lsl #N" where N is non-negative.
2352 if (!Parser.getTok().is(AsmToken::Identifier) ||
2353 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2354 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2355 return MatchOperand_ParseFail;
2356 }
2357
2358 // Eat 'lsl'
2359 Parser.Lex();
2360
Nirav Davee833c6c2016-11-08 18:31:04 +00002361 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002362
2363 if (Parser.getTok().isNot(AsmToken::Integer)) {
2364 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2365 return MatchOperand_ParseFail;
2366 }
2367
2368 int64_t ShiftAmount = Parser.getTok().getIntVal();
2369
2370 if (ShiftAmount < 0) {
2371 Error(Parser.getTok().getLoc(), "positive shift amount required");
2372 return MatchOperand_ParseFail;
2373 }
2374 Parser.Lex(); // Eat the number
2375
Sander de Smalen62770792018-05-25 09:47:52 +00002376 // Just in case the optional lsl #0 is used for immediates other than zero.
2377 if (ShiftAmount == 0 && Imm != 0) {
2378 SMLoc E = Parser.getTok().getLoc();
2379 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2380 return MatchOperand_Success;
2381 }
2382
Tim Northover3b0846e2014-05-24 12:50:23 +00002383 SMLoc E = Parser.getTok().getLoc();
2384 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2385 S, E, getContext()));
2386 return MatchOperand_Success;
2387}
2388
2389/// parseCondCodeString - Parse a Condition Code string.
2390AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2391 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2392 .Case("eq", AArch64CC::EQ)
2393 .Case("ne", AArch64CC::NE)
2394 .Case("cs", AArch64CC::HS)
2395 .Case("hs", AArch64CC::HS)
2396 .Case("cc", AArch64CC::LO)
2397 .Case("lo", AArch64CC::LO)
2398 .Case("mi", AArch64CC::MI)
2399 .Case("pl", AArch64CC::PL)
2400 .Case("vs", AArch64CC::VS)
2401 .Case("vc", AArch64CC::VC)
2402 .Case("hi", AArch64CC::HI)
2403 .Case("ls", AArch64CC::LS)
2404 .Case("ge", AArch64CC::GE)
2405 .Case("lt", AArch64CC::LT)
2406 .Case("gt", AArch64CC::GT)
2407 .Case("le", AArch64CC::LE)
2408 .Case("al", AArch64CC::AL)
2409 .Case("nv", AArch64CC::NV)
2410 .Default(AArch64CC::Invalid);
2411 return CC;
2412}
2413
2414/// parseCondCode - Parse a Condition Code operand.
2415bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2416 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002417 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002418 SMLoc S = getLoc();
2419 const AsmToken &Tok = Parser.getTok();
2420 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2421
2422 StringRef Cond = Tok.getString();
2423 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2424 if (CC == AArch64CC::Invalid)
2425 return TokError("invalid condition code");
2426 Parser.Lex(); // Eat identifier token.
2427
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002428 if (invertCondCode) {
2429 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2430 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002431 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002432 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002433
2434 Operands.push_back(
2435 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2436 return false;
2437}
2438
2439/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2440/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002441OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002442AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002443 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002444 const AsmToken &Tok = Parser.getTok();
2445 std::string LowerID = Tok.getString().lower();
2446 AArch64_AM::ShiftExtendType ShOp =
2447 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2448 .Case("lsl", AArch64_AM::LSL)
2449 .Case("lsr", AArch64_AM::LSR)
2450 .Case("asr", AArch64_AM::ASR)
2451 .Case("ror", AArch64_AM::ROR)
2452 .Case("msl", AArch64_AM::MSL)
2453 .Case("uxtb", AArch64_AM::UXTB)
2454 .Case("uxth", AArch64_AM::UXTH)
2455 .Case("uxtw", AArch64_AM::UXTW)
2456 .Case("uxtx", AArch64_AM::UXTX)
2457 .Case("sxtb", AArch64_AM::SXTB)
2458 .Case("sxth", AArch64_AM::SXTH)
2459 .Case("sxtw", AArch64_AM::SXTW)
2460 .Case("sxtx", AArch64_AM::SXTX)
2461 .Default(AArch64_AM::InvalidShiftExtend);
2462
2463 if (ShOp == AArch64_AM::InvalidShiftExtend)
2464 return MatchOperand_NoMatch;
2465
2466 SMLoc S = Tok.getLoc();
2467 Parser.Lex();
2468
Nirav Davee833c6c2016-11-08 18:31:04 +00002469 bool Hash = parseOptionalToken(AsmToken::Hash);
2470
Tim Northover3b0846e2014-05-24 12:50:23 +00002471 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2472 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2473 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2474 ShOp == AArch64_AM::MSL) {
2475 // We expect a number here.
2476 TokError("expected #imm after shift specifier");
2477 return MatchOperand_ParseFail;
2478 }
2479
Chad Rosier2ff37b82016-12-27 16:58:09 +00002480 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002481 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2482 Operands.push_back(
2483 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2484 return MatchOperand_Success;
2485 }
2486
Chad Rosier2ff37b82016-12-27 16:58:09 +00002487 // Make sure we do actually have a number, identifier or a parenthesized
2488 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002489 SMLoc E = Parser.getTok().getLoc();
2490 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002491 !Parser.getTok().is(AsmToken::LParen) &&
2492 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002493 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002494 return MatchOperand_ParseFail;
2495 }
2496
2497 const MCExpr *ImmVal;
2498 if (getParser().parseExpression(ImmVal))
2499 return MatchOperand_ParseFail;
2500
2501 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2502 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002503 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002504 return MatchOperand_ParseFail;
2505 }
2506
Jim Grosbach57fd2622014-09-23 22:16:02 +00002507 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002508 Operands.push_back(AArch64Operand::CreateShiftExtend(
2509 ShOp, MCE->getValue(), true, S, E, getContext()));
2510 return MatchOperand_Success;
2511}
2512
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002513static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2514 if (FBS[AArch64::HasV8_1aOps])
2515 Str += "ARMv8.1a";
2516 else if (FBS[AArch64::HasV8_2aOps])
2517 Str += "ARMv8.2a";
2518 else
2519 Str += "(unknown)";
2520}
2521
2522void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2523 SMLoc S) {
2524 const uint16_t Op2 = Encoding & 7;
2525 const uint16_t Cm = (Encoding & 0x78) >> 3;
2526 const uint16_t Cn = (Encoding & 0x780) >> 7;
2527 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2528
2529 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2530
2531 Operands.push_back(
2532 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2533 Operands.push_back(
2534 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2535 Operands.push_back(
2536 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2537 Expr = MCConstantExpr::create(Op2, getContext());
2538 Operands.push_back(
2539 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2540}
2541
Tim Northover3b0846e2014-05-24 12:50:23 +00002542/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2543/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2544bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2545 OperandVector &Operands) {
2546 if (Name.find('.') != StringRef::npos)
2547 return TokError("invalid operand");
2548
2549 Mnemonic = Name;
2550 Operands.push_back(
2551 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2552
Rafael Espindola961d4692014-11-11 05:18:41 +00002553 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002554 const AsmToken &Tok = Parser.getTok();
2555 StringRef Op = Tok.getString();
2556 SMLoc S = Tok.getLoc();
2557
Tim Northover3b0846e2014-05-24 12:50:23 +00002558 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002559 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2560 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002561 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002562 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2563 std::string Str("IC " + std::string(IC->Name) + " requires ");
2564 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2565 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002566 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002567 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002568 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002569 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2570 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002571 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002572 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2573 std::string Str("DC " + std::string(DC->Name) + " requires ");
2574 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2575 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002576 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002577 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002578 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002579 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2580 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002581 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002582 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2583 std::string Str("AT " + std::string(AT->Name) + " requires ");
2584 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2585 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002586 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002587 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002588 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002589 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2590 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002591 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002592 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2593 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2594 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2595 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002596 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002597 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002598 }
2599
Tim Northover3b0846e2014-05-24 12:50:23 +00002600 Parser.Lex(); // Eat operand.
2601
2602 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2603 bool HasRegister = false;
2604
2605 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002606 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002607 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2608 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002609 HasRegister = true;
2610 }
2611
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002612 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002613 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002614 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002615 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002616
Nirav Davee833c6c2016-11-08 18:31:04 +00002617 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2618 return true;
2619
Tim Northover3b0846e2014-05-24 12:50:23 +00002620 return false;
2621}
2622
Alex Bradbury58eba092016-11-01 16:32:05 +00002623OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002624AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002625 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002626 const AsmToken &Tok = Parser.getTok();
2627
2628 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002629 if (parseOptionalToken(AsmToken::Hash) ||
2630 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002631 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002632 const MCExpr *ImmVal;
2633 SMLoc ExprLoc = getLoc();
2634 if (getParser().parseExpression(ImmVal))
2635 return MatchOperand_ParseFail;
2636 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2637 if (!MCE) {
2638 Error(ExprLoc, "immediate value expected for barrier operand");
2639 return MatchOperand_ParseFail;
2640 }
2641 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2642 Error(ExprLoc, "barrier operand out of range");
2643 return MatchOperand_ParseFail;
2644 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002645 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2646 Operands.push_back(AArch64Operand::CreateBarrier(
2647 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002648 return MatchOperand_Success;
2649 }
2650
2651 if (Tok.isNot(AsmToken::Identifier)) {
2652 TokError("invalid operand for instruction");
2653 return MatchOperand_ParseFail;
2654 }
2655
Tim Northover3b0846e2014-05-24 12:50:23 +00002656 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002657 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2658 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002659 TokError("'sy' or #imm operand expected");
2660 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002661 } else if (!DB) {
2662 TokError("invalid barrier option name");
2663 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002664 }
2665
Tim Northovere6ae6762016-07-05 21:23:04 +00002666 Operands.push_back(AArch64Operand::CreateBarrier(
2667 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002668 Parser.Lex(); // Consume the option
2669
2670 return MatchOperand_Success;
2671}
2672
Alex Bradbury58eba092016-11-01 16:32:05 +00002673OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002674AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002675 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002676 const AsmToken &Tok = Parser.getTok();
2677
2678 if (Tok.isNot(AsmToken::Identifier))
2679 return MatchOperand_NoMatch;
2680
Tim Northovere6ae6762016-07-05 21:23:04 +00002681 int MRSReg, MSRReg;
2682 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2683 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2684 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2685 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2686 } else
2687 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002688
Tim Northovere6ae6762016-07-05 21:23:04 +00002689 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2690 unsigned PStateImm = -1;
2691 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2692 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002693
Tim Northovere6ae6762016-07-05 21:23:04 +00002694 Operands.push_back(
2695 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2696 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002697 Parser.Lex(); // Eat identifier
2698
2699 return MatchOperand_Success;
2700}
2701
Florian Hahnc4422242017-11-07 13:07:50 +00002702/// tryParseNeonVectorRegister - Parse a vector register operand.
2703bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002704 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002705 if (Parser.getTok().isNot(AsmToken::Identifier))
2706 return true;
2707
2708 SMLoc S = getLoc();
2709 // Check for a vector register specifier first.
2710 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002711 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002712 OperandMatchResultTy Res =
2713 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2714 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002715 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002716
2717 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2718 if (!KindRes)
2719 return true;
2720
2721 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002722 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002723 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2724 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002725
Tim Northover3b0846e2014-05-24 12:50:23 +00002726 // If there was an explicit qualifier, that goes on as a literal text
2727 // operand.
2728 if (!Kind.empty())
2729 Operands.push_back(
2730 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2731
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002732 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2733}
2734
2735OperandMatchResultTy
2736AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002737 SMLoc SIdx = getLoc();
2738 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002739 const MCExpr *ImmVal;
2740 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002741 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002742 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2743 if (!MCE) {
2744 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002745 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002746 }
2747
2748 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002749
Nirav Davee833c6c2016-11-08 18:31:04 +00002750 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002751 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002752
2753 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2754 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002755 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002756 }
2757
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002758 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002759}
2760
Sander de Smalen73937b72018-04-11 07:36:10 +00002761// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002762// optional kind specifier. If it is a register specifier, eat the token
2763// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002764OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002765AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002766 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002767 MCAsmParser &Parser = getParser();
2768 const AsmToken &Tok = Parser.getTok();
2769
Florian Hahn91f11e52017-11-07 16:45:48 +00002770 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002771 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002772
2773 StringRef Name = Tok.getString();
2774 // If there is a kind specifier, it's separated from the register name by
2775 // a '.'.
2776 size_t Start = 0, Next = Name.find('.');
2777 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002778 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002779
2780 if (RegNum) {
2781 if (Next != StringRef::npos) {
2782 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002783 if (!isValidVectorKind(Kind, MatchKind)) {
2784 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002785 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002786 }
2787 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002788 Parser.Lex(); // Eat the register token.
2789
2790 Reg = RegNum;
2791 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002792 }
2793
Sander de Smalen8e607342017-11-15 15:44:43 +00002794 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002795}
2796
Sander de Smalencd6be962017-12-20 11:02:42 +00002797/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2798OperandMatchResultTy
2799AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2800 // Check for a SVE predicate register specifier first.
2801 const SMLoc S = getLoc();
2802 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002803 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002804 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002805 if (Res != MatchOperand_Success)
2806 return Res;
2807
Sander de Smalen73937b72018-04-11 07:36:10 +00002808 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2809 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002810 return MatchOperand_NoMatch;
2811
Sander de Smalen73937b72018-04-11 07:36:10 +00002812 unsigned ElementWidth = KindRes->second;
2813 Operands.push_back(AArch64Operand::CreateVectorReg(
2814 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2815 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002816
Sander de Smalen7868e742018-01-09 11:17:06 +00002817 // Not all predicates are followed by a '/m' or '/z'.
2818 MCAsmParser &Parser = getParser();
2819 if (Parser.getTok().isNot(AsmToken::Slash))
2820 return MatchOperand_Success;
2821
2822 // But when they do they shouldn't have an element type suffix.
2823 if (!Kind.empty()) {
2824 Error(S, "not expecting size suffix");
2825 return MatchOperand_ParseFail;
2826 }
2827
2828 // Add a literal slash as operand
2829 Operands.push_back(
2830 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2831
2832 Parser.Lex(); // Eat the slash.
2833
2834 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002835 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002836 if (Pred != "z" && Pred != "m") {
2837 Error(getLoc(), "expecting 'm' or 'z' predication");
2838 return MatchOperand_ParseFail;
2839 }
2840
2841 // Add zero/merge token.
2842 const char *ZM = Pred == "z" ? "z" : "m";
2843 Operands.push_back(
2844 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2845
2846 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002847 return MatchOperand_Success;
2848}
2849
Sander de Smalen50d87022018-04-19 07:35:08 +00002850/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002851bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002852 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002853 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002854 return false;
2855
Sander de Smalen149916d2018-04-20 07:24:20 +00002856 // Otherwise try for a scalar register.
2857 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
2858 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002859
Sander de Smalen149916d2018-04-20 07:24:20 +00002860 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002861}
2862
2863bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002864 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002865 bool HasELFModifier = false;
2866 AArch64MCExpr::VariantKind RefKind;
2867
Nirav Davee833c6c2016-11-08 18:31:04 +00002868 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002869 HasELFModifier = true;
2870
Nirav Davee833c6c2016-11-08 18:31:04 +00002871 if (Parser.getTok().isNot(AsmToken::Identifier))
2872 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002873
2874 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2875 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2876 .Case("lo12", AArch64MCExpr::VK_LO12)
2877 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2878 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2879 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2880 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2881 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2882 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2883 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2884 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2885 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2886 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2887 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2888 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2889 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2890 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2891 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2892 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2893 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2894 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2895 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2896 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2897 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2898 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2899 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2900 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2901 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2902 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2903 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2904 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2905 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2906 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2907 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2908 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2909 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2910 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002911 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2912 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002913 .Default(AArch64MCExpr::VK_INVALID);
2914
Nirav Davee833c6c2016-11-08 18:31:04 +00002915 if (RefKind == AArch64MCExpr::VK_INVALID)
2916 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002917
2918 Parser.Lex(); // Eat identifier
2919
Nirav Davee833c6c2016-11-08 18:31:04 +00002920 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002921 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002922 }
2923
2924 if (getParser().parseExpression(ImmVal))
2925 return true;
2926
2927 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002928 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002929
2930 return false;
2931}
2932
Sander de Smalen650234b2018-04-12 11:40:52 +00002933template <RegKind VectorKind>
2934OperandMatchResultTy
2935AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
2936 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002937 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00002938 if (!Parser.getTok().is(AsmToken::LCurly))
2939 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002940
2941 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00002942 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00002943 bool NoMatchIsError) {
2944 auto RegTok = Parser.getTok();
2945 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
2946 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002947 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00002948 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002949 llvm_unreachable("Expected a valid vector kind");
2950 }
2951
Sander de Smalen650234b2018-04-12 11:40:52 +00002952 if (RegTok.isNot(AsmToken::Identifier) ||
2953 ParseRes == MatchOperand_ParseFail ||
2954 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
2955 Error(Loc, "vector register expected");
2956 return MatchOperand_ParseFail;
2957 }
2958
2959 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002960 };
2961
Tim Northover3b0846e2014-05-24 12:50:23 +00002962 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00002963 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00002964 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00002965
Tim Northover3b0846e2014-05-24 12:50:23 +00002966 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002967 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002968 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
2969
2970 // Put back the original left bracket if there was no match, so that
2971 // different types of list-operands can be matched (e.g. SVE, Neon).
2972 if (ParseRes == MatchOperand_NoMatch)
2973 Parser.getLexer().UnLex(LCurly);
2974
2975 if (ParseRes != MatchOperand_Success)
2976 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002977
Tim Northover3b0846e2014-05-24 12:50:23 +00002978 int64_t PrevReg = FirstReg;
2979 unsigned Count = 1;
2980
Nirav Davee833c6c2016-11-08 18:31:04 +00002981 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002982 SMLoc Loc = getLoc();
2983 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002984
Sander de Smalen50d87022018-04-19 07:35:08 +00002985 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002986 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2987 if (ParseRes != MatchOperand_Success)
2988 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002989
Tim Northover3b0846e2014-05-24 12:50:23 +00002990 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002991 if (Kind != NextKind) {
2992 Error(Loc, "mismatched register size suffix");
2993 return MatchOperand_ParseFail;
2994 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002995
2996 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2997
2998 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002999 Error(Loc, "invalid number of vectors");
3000 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003001 }
3002
3003 Count += Space;
3004 }
3005 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003006 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003007 SMLoc Loc = getLoc();
3008 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003009 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003010 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3011 if (ParseRes != MatchOperand_Success)
3012 return ParseRes;
3013
Tim Northover3b0846e2014-05-24 12:50:23 +00003014 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003015 if (Kind != NextKind) {
3016 Error(Loc, "mismatched register size suffix");
3017 return MatchOperand_ParseFail;
3018 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003019
3020 // Registers must be incremental (with wraparound at 31)
3021 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003022 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3023 Error(Loc, "registers must be sequential");
3024 return MatchOperand_ParseFail;
3025 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003026
3027 PrevReg = Reg;
3028 ++Count;
3029 }
3030 }
3031
Nirav Davee833c6c2016-11-08 18:31:04 +00003032 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003033 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003034
Sander de Smalen650234b2018-04-12 11:40:52 +00003035 if (Count > 4) {
3036 Error(S, "invalid number of vectors");
3037 return MatchOperand_ParseFail;
3038 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003039
3040 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003041 unsigned ElementWidth = 0;
3042 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003043 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003044 std::tie(NumElements, ElementWidth) = *VK;
3045 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003046
3047 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003048 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3049 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003050
Sander de Smalen650234b2018-04-12 11:40:52 +00003051 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003052}
3053
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003054/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3055bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003056 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3057 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003058 return true;
3059
3060 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3061}
3062
Alex Bradbury58eba092016-11-01 16:32:05 +00003063OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003064AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003065 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003066
Sander de Smalen50d87022018-04-19 07:35:08 +00003067 unsigned RegNum;
3068 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3069 if (Res != MatchOperand_Success)
3070 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003071
Nirav Davee833c6c2016-11-08 18:31:04 +00003072 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003073 Operands.push_back(AArch64Operand::CreateReg(
3074 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003075 return MatchOperand_Success;
3076 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003077
Nirav Davee833c6c2016-11-08 18:31:04 +00003078 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003079
Sander de Smalen50d87022018-04-19 07:35:08 +00003080 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003081 Error(getLoc(), "index must be absent or #0");
3082 return MatchOperand_ParseFail;
3083 }
3084
3085 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003086 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003087 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3088 Error(getLoc(), "index must be absent or #0");
3089 return MatchOperand_ParseFail;
3090 }
3091
Sander de Smalen50d87022018-04-19 07:35:08 +00003092 Operands.push_back(AArch64Operand::CreateReg(
3093 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003094 return MatchOperand_Success;
3095}
3096
Sander de Smalen149916d2018-04-20 07:24:20 +00003097template <bool ParseShiftExtend>
3098OperandMatchResultTy
3099AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3100 SMLoc StartLoc = getLoc();
3101
3102 unsigned RegNum;
3103 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3104 if (Res != MatchOperand_Success)
3105 return Res;
3106
3107 // No shift/extend is the default.
3108 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3109 Operands.push_back(AArch64Operand::CreateReg(
3110 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
3111 return MatchOperand_Success;
3112 }
3113
3114 // Eat the comma
3115 getParser().Lex();
3116
3117 // Match the shift
3118 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3119 Res = tryParseOptionalShiftExtend(ExtOpnd);
3120 if (Res != MatchOperand_Success)
3121 return Res;
3122
3123 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
3124 Operands.push_back(AArch64Operand::CreateReg(RegNum, RegKind::Scalar,
3125 StartLoc, Ext->getEndLoc(), getContext(),
3126 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3127 Ext->hasShiftExtendAmount()));
3128
3129 return MatchOperand_Success;
3130}
3131
Sander de Smalen5c625982018-04-13 12:56:14 +00003132bool AArch64AsmParser::parseOptionalMulVl(OperandVector &Operands) {
3133 MCAsmParser &Parser = getParser();
3134
3135 // Some SVE instructions have a decoration after the immediate, i.e.
3136 // "mul vl". We parse them here and add tokens, which must be present in the
3137 // asm string in the tablegen instruction.
3138 if (!Parser.getTok().getString().equals_lower("mul") ||
3139 !Parser.getLexer().peekTok().getString().equals_lower("vl"))
3140 return true;
3141
3142 SMLoc S = getLoc();
3143 Operands.push_back(
3144 AArch64Operand::CreateToken("mul", false, S, getContext()));
3145 Parser.Lex(); // Eat the "mul"
3146
3147 S = getLoc();
3148 Operands.push_back(
3149 AArch64Operand::CreateToken("vl", false, S, getContext()));
3150 Parser.Lex(); // Eat the "vl"
3151
3152 return false;
3153}
3154
Tim Northover3b0846e2014-05-24 12:50:23 +00003155/// parseOperand - Parse a arm instruction operand. For now this parses the
3156/// operand regardless of the mnemonic.
3157bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3158 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003159 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003160
3161 OperandMatchResultTy ResTy =
3162 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3163
Tim Northover3b0846e2014-05-24 12:50:23 +00003164 // Check if the current operand has a custom associated parser, if so, try to
3165 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003166 if (ResTy == MatchOperand_Success)
3167 return false;
3168 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3169 // there was a match, but an error occurred, in which case, just return that
3170 // the operand parsing failed.
3171 if (ResTy == MatchOperand_ParseFail)
3172 return true;
3173
3174 // Nothing custom, so do general case parsing.
3175 SMLoc S, E;
3176 switch (getLexer().getKind()) {
3177 default: {
3178 SMLoc S = getLoc();
3179 const MCExpr *Expr;
3180 if (parseSymbolicImmVal(Expr))
3181 return Error(S, "invalid operand");
3182
3183 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3184 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3185 return false;
3186 }
3187 case AsmToken::LBrac: {
3188 SMLoc Loc = Parser.getTok().getLoc();
3189 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3190 getContext()));
3191 Parser.Lex(); // Eat '['
3192
3193 // There's no comma after a '[', so we can parse the next operand
3194 // immediately.
3195 return parseOperand(Operands, false, false);
3196 }
3197 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003198 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003199 case AsmToken::Identifier: {
3200 // If we're expecting a Condition Code operand, then just parse that.
3201 if (isCondCode)
3202 return parseCondCode(Operands, invertCondCode);
3203
3204 // If it's a register name, parse it.
3205 if (!parseRegister(Operands))
3206 return false;
3207
Sander de Smalen5c625982018-04-13 12:56:14 +00003208 // See if this is a "mul vl" decoration used by SVE instructions.
3209 if (!parseOptionalMulVl(Operands))
3210 return false;
3211
Tim Northover3b0846e2014-05-24 12:50:23 +00003212 // This could be an optional "shift" or "extend" operand.
3213 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3214 // We can only continue if no tokens were eaten.
3215 if (GotShift != MatchOperand_NoMatch)
3216 return GotShift;
3217
3218 // This was not a register so parse other operands that start with an
3219 // identifier (like labels) as expressions and create them as immediates.
3220 const MCExpr *IdVal;
3221 S = getLoc();
3222 if (getParser().parseExpression(IdVal))
3223 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003224 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3225 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3226 return false;
3227 }
3228 case AsmToken::Integer:
3229 case AsmToken::Real:
3230 case AsmToken::Hash: {
3231 // #42 -> immediate.
3232 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003233
3234 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003235
3236 // Parse a negative sign
3237 bool isNegative = false;
3238 if (Parser.getTok().is(AsmToken::Minus)) {
3239 isNegative = true;
3240 // We need to consume this token only when we have a Real, otherwise
3241 // we let parseSymbolicImmVal take care of it
3242 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3243 Parser.Lex();
3244 }
3245
3246 // The only Real that should come through here is a literal #0.0 for
3247 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3248 // so convert the value.
3249 const AsmToken &Tok = Parser.getTok();
3250 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003251 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003252 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3253 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3254 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3255 Mnemonic != "fcmlt")
3256 return TokError("unexpected floating point literal");
3257 else if (IntVal != 0 || isNegative)
3258 return TokError("expected floating-point constant #0.0");
3259 Parser.Lex(); // Eat the token.
3260
3261 Operands.push_back(
3262 AArch64Operand::CreateToken("#0", false, S, getContext()));
3263 Operands.push_back(
3264 AArch64Operand::CreateToken(".0", false, S, getContext()));
3265 return false;
3266 }
3267
3268 const MCExpr *ImmVal;
3269 if (parseSymbolicImmVal(ImmVal))
3270 return true;
3271
3272 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3273 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3274 return false;
3275 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003276 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003277 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003278 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003279 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003280 Parser.Lex(); // Eat '='
3281 const MCExpr *SubExprVal;
3282 if (getParser().parseExpression(SubExprVal))
3283 return true;
3284
David Peixottoae5ba762014-07-18 16:05:14 +00003285 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003286 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003287 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003288
3289 bool IsXReg =
3290 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3291 Operands[1]->getReg());
3292
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003293 MCContext& Ctx = getContext();
3294 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3295 // 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 +00003296 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003297 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3298 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3299 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3300 ShiftAmt += 16;
3301 Imm >>= 16;
3302 }
3303 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3304 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3305 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003306 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003307 if (ShiftAmt)
3308 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3309 ShiftAmt, true, S, E, Ctx));
3310 return false;
3311 }
David Peixottoae5ba762014-07-18 16:05:14 +00003312 APInt Simm = APInt(64, Imm << ShiftAmt);
3313 // check if the immediate is an unsigned or signed 32-bit int for W regs
3314 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3315 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003316 }
3317 // 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 +00003318 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003319 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003320 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3321 return false;
3322 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003323 }
3324}
3325
3326/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3327/// operands.
3328bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3329 StringRef Name, SMLoc NameLoc,
3330 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003331 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003332 Name = StringSwitch<StringRef>(Name.lower())
3333 .Case("beq", "b.eq")
3334 .Case("bne", "b.ne")
3335 .Case("bhs", "b.hs")
3336 .Case("bcs", "b.cs")
3337 .Case("blo", "b.lo")
3338 .Case("bcc", "b.cc")
3339 .Case("bmi", "b.mi")
3340 .Case("bpl", "b.pl")
3341 .Case("bvs", "b.vs")
3342 .Case("bvc", "b.vc")
3343 .Case("bhi", "b.hi")
3344 .Case("bls", "b.ls")
3345 .Case("bge", "b.ge")
3346 .Case("blt", "b.lt")
3347 .Case("bgt", "b.gt")
3348 .Case("ble", "b.le")
3349 .Case("bal", "b.al")
3350 .Case("bnv", "b.nv")
3351 .Default(Name);
3352
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003353 // First check for the AArch64-specific .req directive.
3354 if (Parser.getTok().is(AsmToken::Identifier) &&
3355 Parser.getTok().getIdentifier() == ".req") {
3356 parseDirectiveReq(Name, NameLoc);
3357 // We always return 'error' for this, as we're done with this
3358 // statement and don't need to match the 'instruction."
3359 return true;
3360 }
3361
Tim Northover3b0846e2014-05-24 12:50:23 +00003362 // Create the leading tokens for the mnemonic, split by '.' characters.
3363 size_t Start = 0, Next = Name.find('.');
3364 StringRef Head = Name.slice(Start, Next);
3365
3366 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003367 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3368 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003369
3370 Operands.push_back(
3371 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3372 Mnemonic = Head;
3373
3374 // Handle condition codes for a branch mnemonic
3375 if (Head == "b" && Next != StringRef::npos) {
3376 Start = Next;
3377 Next = Name.find('.', Start + 1);
3378 Head = Name.slice(Start + 1, Next);
3379
3380 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3381 (Head.data() - Name.data()));
3382 AArch64CC::CondCode CC = parseCondCodeString(Head);
3383 if (CC == AArch64CC::Invalid)
3384 return Error(SuffixLoc, "invalid condition code");
3385 Operands.push_back(
3386 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3387 Operands.push_back(
3388 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3389 }
3390
3391 // Add the remaining tokens in the mnemonic.
3392 while (Next != StringRef::npos) {
3393 Start = Next;
3394 Next = Name.find('.', Start + 1);
3395 Head = Name.slice(Start, Next);
3396 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3397 (Head.data() - Name.data()) + 1);
3398 Operands.push_back(
3399 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3400 }
3401
3402 // Conditional compare instructions have a Condition Code operand, which needs
3403 // to be parsed and an immediate operand created.
3404 bool condCodeFourthOperand =
3405 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3406 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3407 Head == "csinc" || Head == "csinv" || Head == "csneg");
3408
3409 // These instructions are aliases to some of the conditional select
3410 // instructions. However, the condition code is inverted in the aliased
3411 // instruction.
3412 //
3413 // FIXME: Is this the correct way to handle these? Or should the parser
3414 // generate the aliased instructions directly?
3415 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3416 bool condCodeThirdOperand =
3417 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3418
3419 // Read the remaining operands.
3420 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3421 // Read the first operand.
3422 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003423 return true;
3424 }
3425
3426 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003427 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003428 // Parse and remember the operand.
3429 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3430 (N == 3 && condCodeThirdOperand) ||
3431 (N == 2 && condCodeSecondOperand),
3432 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003433 return true;
3434 }
3435
3436 // After successfully parsing some operands there are two special cases to
3437 // consider (i.e. notional operands not separated by commas). Both are due
3438 // to memory specifiers:
3439 // + An RBrac will end an address for load/store/prefetch
3440 // + An '!' will indicate a pre-indexed operation.
3441 //
3442 // It's someone else's responsibility to make sure these tokens are sane
3443 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003444
Nirav Davee833c6c2016-11-08 18:31:04 +00003445 SMLoc RLoc = Parser.getTok().getLoc();
3446 if (parseOptionalToken(AsmToken::RBrac))
3447 Operands.push_back(
3448 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3449 SMLoc ELoc = Parser.getTok().getLoc();
3450 if (parseOptionalToken(AsmToken::Exclaim))
3451 Operands.push_back(
3452 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003453
3454 ++N;
3455 }
3456 }
3457
Nirav Davee833c6c2016-11-08 18:31:04 +00003458 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3459 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003460
Tim Northover3b0846e2014-05-24 12:50:23 +00003461 return false;
3462}
3463
3464// FIXME: This entire function is a giant hack to provide us with decent
3465// operand range validation/diagnostics until TableGen/MC can be extended
3466// to support autogeneration of this kind of validation.
3467bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3468 SmallVectorImpl<SMLoc> &Loc) {
3469 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3470 // Check for indexed addressing modes w/ the base register being the
3471 // same as a destination/source register or pair load where
3472 // the Rt == Rt2. All of those are undefined behaviour.
3473 switch (Inst.getOpcode()) {
3474 case AArch64::LDPSWpre:
3475 case AArch64::LDPWpost:
3476 case AArch64::LDPWpre:
3477 case AArch64::LDPXpost:
3478 case AArch64::LDPXpre: {
3479 unsigned Rt = Inst.getOperand(1).getReg();
3480 unsigned Rt2 = Inst.getOperand(2).getReg();
3481 unsigned Rn = Inst.getOperand(3).getReg();
3482 if (RI->isSubRegisterEq(Rn, Rt))
3483 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3484 "is also a destination");
3485 if (RI->isSubRegisterEq(Rn, Rt2))
3486 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3487 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003488 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003489 }
3490 case AArch64::LDPDi:
3491 case AArch64::LDPQi:
3492 case AArch64::LDPSi:
3493 case AArch64::LDPSWi:
3494 case AArch64::LDPWi:
3495 case AArch64::LDPXi: {
3496 unsigned Rt = Inst.getOperand(0).getReg();
3497 unsigned Rt2 = Inst.getOperand(1).getReg();
3498 if (Rt == Rt2)
3499 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3500 break;
3501 }
3502 case AArch64::LDPDpost:
3503 case AArch64::LDPDpre:
3504 case AArch64::LDPQpost:
3505 case AArch64::LDPQpre:
3506 case AArch64::LDPSpost:
3507 case AArch64::LDPSpre:
3508 case AArch64::LDPSWpost: {
3509 unsigned Rt = Inst.getOperand(1).getReg();
3510 unsigned Rt2 = Inst.getOperand(2).getReg();
3511 if (Rt == Rt2)
3512 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3513 break;
3514 }
3515 case AArch64::STPDpost:
3516 case AArch64::STPDpre:
3517 case AArch64::STPQpost:
3518 case AArch64::STPQpre:
3519 case AArch64::STPSpost:
3520 case AArch64::STPSpre:
3521 case AArch64::STPWpost:
3522 case AArch64::STPWpre:
3523 case AArch64::STPXpost:
3524 case AArch64::STPXpre: {
3525 unsigned Rt = Inst.getOperand(1).getReg();
3526 unsigned Rt2 = Inst.getOperand(2).getReg();
3527 unsigned Rn = Inst.getOperand(3).getReg();
3528 if (RI->isSubRegisterEq(Rn, Rt))
3529 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3530 "is also a source");
3531 if (RI->isSubRegisterEq(Rn, Rt2))
3532 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3533 "is also a source");
3534 break;
3535 }
3536 case AArch64::LDRBBpre:
3537 case AArch64::LDRBpre:
3538 case AArch64::LDRHHpre:
3539 case AArch64::LDRHpre:
3540 case AArch64::LDRSBWpre:
3541 case AArch64::LDRSBXpre:
3542 case AArch64::LDRSHWpre:
3543 case AArch64::LDRSHXpre:
3544 case AArch64::LDRSWpre:
3545 case AArch64::LDRWpre:
3546 case AArch64::LDRXpre:
3547 case AArch64::LDRBBpost:
3548 case AArch64::LDRBpost:
3549 case AArch64::LDRHHpost:
3550 case AArch64::LDRHpost:
3551 case AArch64::LDRSBWpost:
3552 case AArch64::LDRSBXpost:
3553 case AArch64::LDRSHWpost:
3554 case AArch64::LDRSHXpost:
3555 case AArch64::LDRSWpost:
3556 case AArch64::LDRWpost:
3557 case AArch64::LDRXpost: {
3558 unsigned Rt = Inst.getOperand(1).getReg();
3559 unsigned Rn = Inst.getOperand(2).getReg();
3560 if (RI->isSubRegisterEq(Rn, Rt))
3561 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3562 "is also a source");
3563 break;
3564 }
3565 case AArch64::STRBBpost:
3566 case AArch64::STRBpost:
3567 case AArch64::STRHHpost:
3568 case AArch64::STRHpost:
3569 case AArch64::STRWpost:
3570 case AArch64::STRXpost:
3571 case AArch64::STRBBpre:
3572 case AArch64::STRBpre:
3573 case AArch64::STRHHpre:
3574 case AArch64::STRHpre:
3575 case AArch64::STRWpre:
3576 case AArch64::STRXpre: {
3577 unsigned Rt = Inst.getOperand(1).getReg();
3578 unsigned Rn = Inst.getOperand(2).getReg();
3579 if (RI->isSubRegisterEq(Rn, Rt))
3580 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3581 "is also a source");
3582 break;
3583 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003584 case AArch64::STXRB:
3585 case AArch64::STXRH:
3586 case AArch64::STXRW:
3587 case AArch64::STXRX:
3588 case AArch64::STLXRB:
3589 case AArch64::STLXRH:
3590 case AArch64::STLXRW:
3591 case AArch64::STLXRX: {
3592 unsigned Rs = Inst.getOperand(0).getReg();
3593 unsigned Rt = Inst.getOperand(1).getReg();
3594 unsigned Rn = Inst.getOperand(2).getReg();
3595 if (RI->isSubRegisterEq(Rt, Rs) ||
3596 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3597 return Error(Loc[0],
3598 "unpredictable STXR instruction, status is also a source");
3599 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003600 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003601 case AArch64::STXPW:
3602 case AArch64::STXPX:
3603 case AArch64::STLXPW:
3604 case AArch64::STLXPX: {
3605 unsigned Rs = Inst.getOperand(0).getReg();
3606 unsigned Rt1 = Inst.getOperand(1).getReg();
3607 unsigned Rt2 = Inst.getOperand(2).getReg();
3608 unsigned Rn = Inst.getOperand(3).getReg();
3609 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3610 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3611 return Error(Loc[0],
3612 "unpredictable STXP instruction, status is also a source");
3613 break;
3614 }
3615 }
3616
Tim Northover3b0846e2014-05-24 12:50:23 +00003617
3618 // Now check immediate ranges. Separate from the above as there is overlap
3619 // in the instructions being checked and this keeps the nested conditionals
3620 // to a minimum.
3621 switch (Inst.getOpcode()) {
3622 case AArch64::ADDSWri:
3623 case AArch64::ADDSXri:
3624 case AArch64::ADDWri:
3625 case AArch64::ADDXri:
3626 case AArch64::SUBSWri:
3627 case AArch64::SUBSXri:
3628 case AArch64::SUBWri:
3629 case AArch64::SUBXri: {
3630 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3631 // some slight duplication here.
3632 if (Inst.getOperand(2).isExpr()) {
3633 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3634 AArch64MCExpr::VariantKind ELFRefKind;
3635 MCSymbolRefExpr::VariantKind DarwinRefKind;
3636 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003637 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3638
3639 // Only allow these with ADDXri.
3640 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3641 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3642 Inst.getOpcode() == AArch64::ADDXri)
3643 return false;
3644
3645 // Only allow these with ADDXri/ADDWri
3646 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3647 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3648 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3649 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3650 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3651 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3652 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003653 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3654 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3655 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003656 (Inst.getOpcode() == AArch64::ADDXri ||
3657 Inst.getOpcode() == AArch64::ADDWri))
3658 return false;
3659
3660 // Don't allow symbol refs in the immediate field otherwise
3661 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3662 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3663 // 'cmp w0, 'borked')
3664 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003665 }
Diana Picusc93518d2016-10-11 09:17:47 +00003666 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003667 }
3668 return false;
3669 }
3670 default:
3671 return false;
3672 }
3673}
3674
Craig Topper05515562017-10-26 06:46:41 +00003675static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3676 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003677
3678bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3679 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003680 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003681 case Match_InvalidTiedOperand:
3682 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003683 case Match_MissingFeature:
3684 return Error(Loc,
3685 "instruction requires a CPU feature not currently enabled");
3686 case Match_InvalidOperand:
3687 return Error(Loc, "invalid operand for instruction");
3688 case Match_InvalidSuffix:
3689 return Error(Loc, "invalid type suffix for instruction");
3690 case Match_InvalidCondCode:
3691 return Error(Loc, "expected AArch64 condition code");
3692 case Match_AddSubRegExtendSmall:
3693 return Error(Loc,
3694 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3695 case Match_AddSubRegExtendLarge:
3696 return Error(Loc,
3697 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3698 case Match_AddSubSecondSource:
3699 return Error(Loc,
3700 "expected compatible register, symbol or integer in range [0, 4095]");
3701 case Match_LogicalSecondSource:
3702 return Error(Loc, "expected compatible register or logical immediate");
3703 case Match_InvalidMovImm32Shift:
3704 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3705 case Match_InvalidMovImm64Shift:
3706 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3707 case Match_AddSubRegShift32:
3708 return Error(Loc,
3709 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3710 case Match_AddSubRegShift64:
3711 return Error(Loc,
3712 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3713 case Match_InvalidFPImm:
3714 return Error(Loc,
3715 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003716 case Match_InvalidMemoryIndexedSImm6:
3717 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003718 case Match_InvalidMemoryIndexedSImm5:
3719 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003720 case Match_InvalidMemoryIndexed1SImm4:
3721 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003722 case Match_InvalidMemoryIndexed2SImm4:
3723 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003724 case Match_InvalidMemoryIndexed3SImm4:
3725 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003726 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00003727 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00003728 case Match_InvalidMemoryIndexed16SImm4:
3729 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00003730 case Match_InvalidMemoryIndexed1SImm6:
3731 return Error(Loc, "index must be an integer in range [-32, 31].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003732 case Match_InvalidMemoryIndexedSImm9:
3733 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00003734 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00003735 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003736 case Match_InvalidMemoryIndexed4SImm7:
3737 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3738 case Match_InvalidMemoryIndexed8SImm7:
3739 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3740 case Match_InvalidMemoryIndexed16SImm7:
3741 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00003742 case Match_InvalidMemoryIndexed8UImm5:
3743 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
3744 case Match_InvalidMemoryIndexed4UImm5:
3745 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
3746 case Match_InvalidMemoryIndexed2UImm5:
3747 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00003748 case Match_InvalidMemoryIndexed8UImm6:
3749 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
3750 case Match_InvalidMemoryIndexed4UImm6:
3751 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
3752 case Match_InvalidMemoryIndexed2UImm6:
3753 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
3754 case Match_InvalidMemoryIndexed1UImm6:
3755 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003756 case Match_InvalidMemoryWExtend8:
3757 return Error(Loc,
3758 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3759 case Match_InvalidMemoryWExtend16:
3760 return Error(Loc,
3761 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3762 case Match_InvalidMemoryWExtend32:
3763 return Error(Loc,
3764 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3765 case Match_InvalidMemoryWExtend64:
3766 return Error(Loc,
3767 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3768 case Match_InvalidMemoryWExtend128:
3769 return Error(Loc,
3770 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3771 case Match_InvalidMemoryXExtend8:
3772 return Error(Loc,
3773 "expected 'lsl' or 'sxtx' with optional shift of #0");
3774 case Match_InvalidMemoryXExtend16:
3775 return Error(Loc,
3776 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3777 case Match_InvalidMemoryXExtend32:
3778 return Error(Loc,
3779 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3780 case Match_InvalidMemoryXExtend64:
3781 return Error(Loc,
3782 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3783 case Match_InvalidMemoryXExtend128:
3784 return Error(Loc,
3785 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3786 case Match_InvalidMemoryIndexed1:
3787 return Error(Loc, "index must be an integer in range [0, 4095].");
3788 case Match_InvalidMemoryIndexed2:
3789 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3790 case Match_InvalidMemoryIndexed4:
3791 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3792 case Match_InvalidMemoryIndexed8:
3793 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3794 case Match_InvalidMemoryIndexed16:
3795 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003796 case Match_InvalidImm0_1:
3797 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003798 case Match_InvalidImm0_7:
3799 return Error(Loc, "immediate must be an integer in range [0, 7].");
3800 case Match_InvalidImm0_15:
3801 return Error(Loc, "immediate must be an integer in range [0, 15].");
3802 case Match_InvalidImm0_31:
3803 return Error(Loc, "immediate must be an integer in range [0, 31].");
3804 case Match_InvalidImm0_63:
3805 return Error(Loc, "immediate must be an integer in range [0, 63].");
3806 case Match_InvalidImm0_127:
3807 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003808 case Match_InvalidImm0_255:
3809 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003810 case Match_InvalidImm0_65535:
3811 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3812 case Match_InvalidImm1_8:
3813 return Error(Loc, "immediate must be an integer in range [1, 8].");
3814 case Match_InvalidImm1_16:
3815 return Error(Loc, "immediate must be an integer in range [1, 16].");
3816 case Match_InvalidImm1_32:
3817 return Error(Loc, "immediate must be an integer in range [1, 32].");
3818 case Match_InvalidImm1_64:
3819 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00003820 case Match_InvalidSVEAddSubImm8:
3821 return Error(Loc, "immediate must be an integer in range [0, 255]"
3822 " with a shift amount of 0");
3823 case Match_InvalidSVEAddSubImm16:
3824 case Match_InvalidSVEAddSubImm32:
3825 case Match_InvalidSVEAddSubImm64:
3826 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
3827 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00003828 case Match_InvalidSVECpyImm8:
3829 return Error(Loc, "immediate must be an integer in range [-128, 255]"
3830 " with a shift amount of 0");
3831 case Match_InvalidSVECpyImm16:
3832 case Match_InvalidSVECpyImm32:
3833 case Match_InvalidSVECpyImm64:
3834 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
3835 "multiple of 256 in range [-32768, 32512]");
Tim Northover3b0846e2014-05-24 12:50:23 +00003836 case Match_InvalidIndex1:
3837 return Error(Loc, "expected lane specifier '[1]'");
3838 case Match_InvalidIndexB:
3839 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3840 case Match_InvalidIndexH:
3841 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3842 case Match_InvalidIndexS:
3843 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3844 case Match_InvalidIndexD:
3845 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3846 case Match_InvalidLabel:
3847 return Error(Loc, "expected label or encodable integer pc offset");
3848 case Match_MRS:
3849 return Error(Loc, "expected readable system register");
3850 case Match_MSR:
3851 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003852 case Match_InvalidComplexRotationEven:
3853 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3854 case Match_InvalidComplexRotationOdd:
3855 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003856 case Match_MnemonicFail: {
3857 std::string Suggestion = AArch64MnemonicSpellCheck(
3858 ((AArch64Operand &)*Operands[0]).getToken(),
3859 ComputeAvailableFeatures(STI->getFeatureBits()));
3860 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3861 }
Sander de Smalen367694b2018-04-20 08:54:49 +00003862 case Match_InvalidGPR64shifted8:
3863 return Error(Loc, "register must be x0..x30 or xzr, without shift");
3864 case Match_InvalidGPR64shifted16:
3865 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
3866 case Match_InvalidGPR64shifted32:
3867 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
3868 case Match_InvalidGPR64shifted64:
3869 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
3870 case Match_InvalidGPR64NoXZRshifted8:
3871 return Error(Loc, "register must be x0..x30 without shift");
3872 case Match_InvalidGPR64NoXZRshifted16:
3873 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
3874 case Match_InvalidGPR64NoXZRshifted32:
3875 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
3876 case Match_InvalidGPR64NoXZRshifted64:
3877 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00003878 case Match_InvalidZPR32UXTW8:
3879 case Match_InvalidZPR32SXTW8:
3880 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
3881 case Match_InvalidZPR32UXTW16:
3882 case Match_InvalidZPR32SXTW16:
3883 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
3884 case Match_InvalidZPR32UXTW32:
3885 case Match_InvalidZPR32SXTW32:
3886 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
3887 case Match_InvalidZPR32UXTW64:
3888 case Match_InvalidZPR32SXTW64:
3889 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
3890 case Match_InvalidZPR64UXTW8:
3891 case Match_InvalidZPR64SXTW8:
3892 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
3893 case Match_InvalidZPR64UXTW16:
3894 case Match_InvalidZPR64SXTW16:
3895 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
3896 case Match_InvalidZPR64UXTW32:
3897 case Match_InvalidZPR64SXTW32:
3898 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
3899 case Match_InvalidZPR64UXTW64:
3900 case Match_InvalidZPR64SXTW64:
3901 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
3902 case Match_InvalidZPR64LSL8:
3903 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
3904 case Match_InvalidZPR64LSL16:
3905 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
3906 case Match_InvalidZPR64LSL32:
3907 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
3908 case Match_InvalidZPR64LSL64:
3909 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00003910 case Match_InvalidZPR0:
3911 return Error(Loc, "expected register without element width sufix");
3912 case Match_InvalidZPR8:
3913 case Match_InvalidZPR16:
3914 case Match_InvalidZPR32:
3915 case Match_InvalidZPR64:
3916 case Match_InvalidZPR128:
3917 return Error(Loc, "invalid element width");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003918 case Match_InvalidSVEPattern:
3919 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003920 case Match_InvalidSVEPredicateAnyReg:
3921 case Match_InvalidSVEPredicateBReg:
3922 case Match_InvalidSVEPredicateHReg:
3923 case Match_InvalidSVEPredicateSReg:
3924 case Match_InvalidSVEPredicateDReg:
3925 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003926 case Match_InvalidSVEPredicate3bAnyReg:
3927 case Match_InvalidSVEPredicate3bBReg:
3928 case Match_InvalidSVEPredicate3bHReg:
3929 case Match_InvalidSVEPredicate3bSReg:
3930 case Match_InvalidSVEPredicate3bDReg:
3931 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003932 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003933 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003934 }
3935}
3936
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003937static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003938
3939bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3940 OperandVector &Operands,
3941 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003942 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003943 bool MatchingInlineAsm) {
3944 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003945 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3946 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003947
David Blaikie960ea3f2014-06-08 16:18:35 +00003948 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003949 unsigned NumOperands = Operands.size();
3950
3951 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003952 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3953 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003954 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003955 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003956 if (Op3CE) {
3957 uint64_t Op3Val = Op3CE->getValue();
3958 uint64_t NewOp3Val = 0;
3959 uint64_t NewOp4Val = 0;
3960 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003961 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003962 NewOp3Val = (32 - Op3Val) & 0x1f;
3963 NewOp4Val = 31 - Op3Val;
3964 } else {
3965 NewOp3Val = (64 - Op3Val) & 0x3f;
3966 NewOp4Val = 63 - Op3Val;
3967 }
3968
Jim Grosbach13760bd2015-05-30 01:25:56 +00003969 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3970 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003971
3972 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003973 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003974 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003975 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3976 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3977 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003978 }
3979 }
Tim Northover03b99f62015-04-30 18:28:58 +00003980 } else if (NumOperands == 4 && Tok == "bfc") {
3981 // FIXME: Horrible hack to handle BFC->BFM alias.
3982 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3983 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3984 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3985
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003986 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003987 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3988 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3989
3990 if (LSBCE && WidthCE) {
3991 uint64_t LSB = LSBCE->getValue();
3992 uint64_t Width = WidthCE->getValue();
3993
3994 uint64_t RegWidth = 0;
3995 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3996 Op1.getReg()))
3997 RegWidth = 64;
3998 else
3999 RegWidth = 32;
4000
4001 if (LSB >= RegWidth)
4002 return Error(LSBOp.getStartLoc(),
4003 "expected integer in range [0, 31]");
4004 if (Width < 1 || Width > RegWidth)
4005 return Error(WidthOp.getStartLoc(),
4006 "expected integer in range [1, 32]");
4007
4008 uint64_t ImmR = 0;
4009 if (RegWidth == 32)
4010 ImmR = (32 - LSB) & 0x1f;
4011 else
4012 ImmR = (64 - LSB) & 0x3f;
4013
4014 uint64_t ImmS = Width - 1;
4015
4016 if (ImmR != 0 && ImmS >= ImmR)
4017 return Error(WidthOp.getStartLoc(),
4018 "requested insert overflows register");
4019
Jim Grosbach13760bd2015-05-30 01:25:56 +00004020 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4021 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004022 Operands[0] = AArch64Operand::CreateToken(
4023 "bfm", false, Op.getStartLoc(), getContext());
4024 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004025 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4026 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004027 Operands[3] = AArch64Operand::CreateImm(
4028 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4029 Operands.emplace_back(
4030 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4031 WidthOp.getEndLoc(), getContext()));
4032 }
4033 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004034 } else if (NumOperands == 5) {
4035 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4036 // UBFIZ -> UBFM aliases.
4037 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004038 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4039 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4040 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004041
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004042 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004043 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4044 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004045
4046 if (Op3CE && Op4CE) {
4047 uint64_t Op3Val = Op3CE->getValue();
4048 uint64_t Op4Val = Op4CE->getValue();
4049
4050 uint64_t RegWidth = 0;
4051 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004052 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004053 RegWidth = 64;
4054 else
4055 RegWidth = 32;
4056
4057 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004058 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004059 "expected integer in range [0, 31]");
4060 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004061 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004062 "expected integer in range [1, 32]");
4063
4064 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004065 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004066 NewOp3Val = (32 - Op3Val) & 0x1f;
4067 else
4068 NewOp3Val = (64 - Op3Val) & 0x3f;
4069
4070 uint64_t NewOp4Val = Op4Val - 1;
4071
4072 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004073 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004074 "requested insert overflows register");
4075
4076 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004077 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004078 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004079 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004080 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004081 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004082 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004083 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004084 if (Tok == "bfi")
4085 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004086 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004087 else if (Tok == "sbfiz")
4088 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004089 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004090 else if (Tok == "ubfiz")
4091 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004092 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004093 else
4094 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004095 }
4096 }
4097
4098 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4099 // UBFX -> UBFM aliases.
4100 } else if (NumOperands == 5 &&
4101 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004102 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4103 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4104 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004105
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004106 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004107 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4108 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004109
4110 if (Op3CE && Op4CE) {
4111 uint64_t Op3Val = Op3CE->getValue();
4112 uint64_t Op4Val = Op4CE->getValue();
4113
4114 uint64_t RegWidth = 0;
4115 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004116 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004117 RegWidth = 64;
4118 else
4119 RegWidth = 32;
4120
4121 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004122 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004123 "expected integer in range [0, 31]");
4124 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004125 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004126 "expected integer in range [1, 32]");
4127
4128 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4129
4130 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004131 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004132 "requested extract overflows register");
4133
4134 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004135 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004136 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004137 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004138 if (Tok == "bfxil")
4139 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004140 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004141 else if (Tok == "sbfx")
4142 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004143 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004144 else if (Tok == "ubfx")
4145 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004146 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004147 else
4148 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004149 }
4150 }
4151 }
4152 }
Tim Northover9097a072017-12-18 10:36:00 +00004153
4154 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4155 // instruction for FP registers correctly in some rare circumstances. Convert
4156 // it to a safe instruction and warn (because silently changing someone's
4157 // assembly is rude).
4158 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4159 NumOperands == 4 && Tok == "movi") {
4160 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4161 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4162 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4163 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4164 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4165 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4166 if (Suffix.lower() == ".2d" &&
4167 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4168 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4169 " correctly on this CPU, converting to equivalent movi.16b");
4170 // Switch the suffix to .16b.
4171 unsigned Idx = Op1.isToken() ? 1 : 2;
4172 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4173 getContext());
4174 }
4175 }
4176 }
4177
Tim Northover3b0846e2014-05-24 12:50:23 +00004178 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4179 // InstAlias can't quite handle this since the reg classes aren't
4180 // subclasses.
4181 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4182 // The source register can be Wn here, but the matcher expects a
4183 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004184 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004185 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004186 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004187 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4188 Op.getStartLoc(), Op.getEndLoc(),
4189 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004190 }
4191 }
4192 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4193 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004194 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004195 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004196 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004197 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004198 // The source register can be Wn here, but the matcher expects a
4199 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004200 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004201 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004202 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004203 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4204 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004205 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004206 }
4207 }
4208 }
4209 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4210 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004211 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004212 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004213 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004214 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004215 // The source register can be Wn here, but the matcher expects a
4216 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004217 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004218 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004219 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004220 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4221 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004222 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004223 }
4224 }
4225 }
4226
Tim Northover3b0846e2014-05-24 12:50:23 +00004227 MCInst Inst;
4228 // First try to match against the secondary set of tables containing the
4229 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4230 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004231 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004232
4233 // If that fails, try against the alternate table containing long-form NEON:
4234 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004235 if (MatchResult != Match_Success) {
4236 // But first, save the short-form match result: we can use it in case the
4237 // long-form match also fails.
4238 auto ShortFormNEONErrorInfo = ErrorInfo;
4239 auto ShortFormNEONMatchResult = MatchResult;
4240
Tim Northover3b0846e2014-05-24 12:50:23 +00004241 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004242 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004243
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004244 // Now, both matches failed, and the long-form match failed on the mnemonic
4245 // suffix token operand. The short-form match failure is probably more
4246 // relevant: use it instead.
4247 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004248 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004249 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4250 MatchResult = ShortFormNEONMatchResult;
4251 ErrorInfo = ShortFormNEONErrorInfo;
4252 }
4253 }
4254
Tim Northover3b0846e2014-05-24 12:50:23 +00004255 switch (MatchResult) {
4256 case Match_Success: {
4257 // Perform range checking and other semantic validations
4258 SmallVector<SMLoc, 8> OperandLocs;
4259 NumOperands = Operands.size();
4260 for (unsigned i = 1; i < NumOperands; ++i)
4261 OperandLocs.push_back(Operands[i]->getStartLoc());
4262 if (validateInstruction(Inst, OperandLocs))
4263 return true;
4264
4265 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004266 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004267 return false;
4268 }
4269 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004270 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004271 // Special case the error message for the very common case where only
4272 // a single subtarget feature is missing (neon, e.g.).
4273 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004274 uint64_t Mask = 1;
4275 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4276 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004277 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004278 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004279 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004280 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004281 }
4282 return Error(IDLoc, Msg);
4283 }
4284 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004285 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004286 case Match_InvalidOperand: {
4287 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004288
Tim Northover26bb14e2014-08-18 11:49:42 +00004289 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004290 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004291 return Error(IDLoc, "too few operands for instruction",
4292 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004293
David Blaikie960ea3f2014-06-08 16:18:35 +00004294 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004295 if (ErrorLoc == SMLoc())
4296 ErrorLoc = IDLoc;
4297 }
4298 // If the match failed on a suffix token operand, tweak the diagnostic
4299 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004300 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4301 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004302 MatchResult = Match_InvalidSuffix;
4303
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004304 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004305 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004306 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004307 case Match_InvalidMemoryIndexed1:
4308 case Match_InvalidMemoryIndexed2:
4309 case Match_InvalidMemoryIndexed4:
4310 case Match_InvalidMemoryIndexed8:
4311 case Match_InvalidMemoryIndexed16:
4312 case Match_InvalidCondCode:
4313 case Match_AddSubRegExtendSmall:
4314 case Match_AddSubRegExtendLarge:
4315 case Match_AddSubSecondSource:
4316 case Match_LogicalSecondSource:
4317 case Match_AddSubRegShift32:
4318 case Match_AddSubRegShift64:
4319 case Match_InvalidMovImm32Shift:
4320 case Match_InvalidMovImm64Shift:
4321 case Match_InvalidFPImm:
4322 case Match_InvalidMemoryWExtend8:
4323 case Match_InvalidMemoryWExtend16:
4324 case Match_InvalidMemoryWExtend32:
4325 case Match_InvalidMemoryWExtend64:
4326 case Match_InvalidMemoryWExtend128:
4327 case Match_InvalidMemoryXExtend8:
4328 case Match_InvalidMemoryXExtend16:
4329 case Match_InvalidMemoryXExtend32:
4330 case Match_InvalidMemoryXExtend64:
4331 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004332 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004333 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004334 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004335 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004336 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004337 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004338 case Match_InvalidMemoryIndexed4SImm7:
4339 case Match_InvalidMemoryIndexed8SImm7:
4340 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004341 case Match_InvalidMemoryIndexed8UImm5:
4342 case Match_InvalidMemoryIndexed4UImm5:
4343 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004344 case Match_InvalidMemoryIndexed1UImm6:
4345 case Match_InvalidMemoryIndexed2UImm6:
4346 case Match_InvalidMemoryIndexed4UImm6:
4347 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004348 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004349 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004350 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004351 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004352 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004353 case Match_InvalidImm0_7:
4354 case Match_InvalidImm0_15:
4355 case Match_InvalidImm0_31:
4356 case Match_InvalidImm0_63:
4357 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004358 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004359 case Match_InvalidImm0_65535:
4360 case Match_InvalidImm1_8:
4361 case Match_InvalidImm1_16:
4362 case Match_InvalidImm1_32:
4363 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004364 case Match_InvalidSVEAddSubImm8:
4365 case Match_InvalidSVEAddSubImm16:
4366 case Match_InvalidSVEAddSubImm32:
4367 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004368 case Match_InvalidSVECpyImm8:
4369 case Match_InvalidSVECpyImm16:
4370 case Match_InvalidSVECpyImm32:
4371 case Match_InvalidSVECpyImm64:
Tim Northover3b0846e2014-05-24 12:50:23 +00004372 case Match_InvalidIndex1:
4373 case Match_InvalidIndexB:
4374 case Match_InvalidIndexH:
4375 case Match_InvalidIndexS:
4376 case Match_InvalidIndexD:
4377 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004378 case Match_InvalidComplexRotationEven:
4379 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004380 case Match_InvalidGPR64shifted8:
4381 case Match_InvalidGPR64shifted16:
4382 case Match_InvalidGPR64shifted32:
4383 case Match_InvalidGPR64shifted64:
4384 case Match_InvalidGPR64NoXZRshifted8:
4385 case Match_InvalidGPR64NoXZRshifted16:
4386 case Match_InvalidGPR64NoXZRshifted32:
4387 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004388 case Match_InvalidZPR32UXTW8:
4389 case Match_InvalidZPR32UXTW16:
4390 case Match_InvalidZPR32UXTW32:
4391 case Match_InvalidZPR32UXTW64:
4392 case Match_InvalidZPR32SXTW8:
4393 case Match_InvalidZPR32SXTW16:
4394 case Match_InvalidZPR32SXTW32:
4395 case Match_InvalidZPR32SXTW64:
4396 case Match_InvalidZPR64UXTW8:
4397 case Match_InvalidZPR64SXTW8:
4398 case Match_InvalidZPR64UXTW16:
4399 case Match_InvalidZPR64SXTW16:
4400 case Match_InvalidZPR64UXTW32:
4401 case Match_InvalidZPR64SXTW32:
4402 case Match_InvalidZPR64UXTW64:
4403 case Match_InvalidZPR64SXTW64:
4404 case Match_InvalidZPR64LSL8:
4405 case Match_InvalidZPR64LSL16:
4406 case Match_InvalidZPR64LSL32:
4407 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004408 case Match_InvalidZPR0:
4409 case Match_InvalidZPR8:
4410 case Match_InvalidZPR16:
4411 case Match_InvalidZPR32:
4412 case Match_InvalidZPR64:
4413 case Match_InvalidZPR128:
Sander de Smalencd6be962017-12-20 11:02:42 +00004414 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004415 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004416 case Match_InvalidSVEPredicateBReg:
4417 case Match_InvalidSVEPredicateHReg:
4418 case Match_InvalidSVEPredicateSReg:
4419 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004420 case Match_InvalidSVEPredicate3bAnyReg:
4421 case Match_InvalidSVEPredicate3bBReg:
4422 case Match_InvalidSVEPredicate3bHReg:
4423 case Match_InvalidSVEPredicate3bSReg:
4424 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004425 case Match_MSR:
4426 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004427 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004428 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004429 // Any time we get here, there's nothing fancy to do. Just get the
4430 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004431 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004432 if (ErrorLoc == SMLoc())
4433 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004434 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004435 }
4436 }
4437
4438 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004439}
4440
4441/// ParseDirective parses the arm specific directives
4442bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004443 const MCObjectFileInfo::Environment Format =
4444 getContext().getObjectFileInfo()->getObjectFileType();
4445 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4446 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004447
Tim Northover3b0846e2014-05-24 12:50:23 +00004448 StringRef IDVal = DirectiveID.getIdentifier();
4449 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004450 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004451 parseDirectiveArch(Loc);
4452 else if (IDVal == ".cpu")
4453 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00004454 else if (IDVal == ".tlsdesccall")
4455 parseDirectiveTLSDescCall(Loc);
4456 else if (IDVal == ".ltorg" || IDVal == ".pool")
4457 parseDirectiveLtorg(Loc);
4458 else if (IDVal == ".unreq")
4459 parseDirectiveUnreq(Loc);
4460 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004461 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004462 parseDirectiveInst(Loc);
4463 else
4464 return true;
4465 } else if (IDVal == MCLOHDirectiveName())
4466 parseDirectiveLOH(IDVal, Loc);
4467 else
4468 return true;
4469 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004470}
4471
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004472static const struct {
4473 const char *Name;
4474 const FeatureBitset Features;
4475} ExtensionMap[] = {
4476 { "crc", {AArch64::FeatureCRC} },
4477 { "crypto", {AArch64::FeatureCrypto} },
4478 { "fp", {AArch64::FeatureFPARMv8} },
4479 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004480 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004481 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004482
4483 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004484 { "pan", {} },
4485 { "lor", {} },
4486 { "rdma", {} },
4487 { "profile", {} },
4488};
4489
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004490/// parseDirectiveArch
4491/// ::= .arch token
4492bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4493 SMLoc ArchLoc = getLoc();
4494
4495 StringRef Arch, ExtensionString;
4496 std::tie(Arch, ExtensionString) =
4497 getParser().parseStringToEndOfStatement().trim().split('+');
4498
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004499 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4500 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004501 return Error(ArchLoc, "unknown arch name");
4502
4503 if (parseToken(AsmToken::EndOfStatement))
4504 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004505
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004506 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004507 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004508 AArch64::getArchFeatures(ID, AArch64Features);
4509 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4510 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004511
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004512 MCSubtargetInfo &STI = copySTI();
4513 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4514 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4515
4516 SmallVector<StringRef, 4> RequestedExtensions;
4517 if (!ExtensionString.empty())
4518 ExtensionString.split(RequestedExtensions, '+');
4519
4520 FeatureBitset Features = STI.getFeatureBits();
4521 for (auto Name : RequestedExtensions) {
4522 bool EnableFeature = true;
4523
4524 if (Name.startswith_lower("no")) {
4525 EnableFeature = false;
4526 Name = Name.substr(2);
4527 }
4528
4529 for (const auto &Extension : ExtensionMap) {
4530 if (Extension.Name != Name)
4531 continue;
4532
4533 if (Extension.Features.none())
4534 report_fatal_error("unsupported architectural extension: " + Name);
4535
4536 FeatureBitset ToggleFeatures = EnableFeature
4537 ? (~Features & Extension.Features)
4538 : ( Features & Extension.Features);
4539 uint64_t Features =
4540 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4541 setAvailableFeatures(Features);
4542 break;
4543 }
4544 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004545 return false;
4546}
4547
Tim Northover8b96c7e2017-05-15 19:42:15 +00004548static SMLoc incrementLoc(SMLoc L, int Offset) {
4549 return SMLoc::getFromPointer(L.getPointer() + Offset);
4550}
4551
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004552/// parseDirectiveCPU
4553/// ::= .cpu id
4554bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004555 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004556
4557 StringRef CPU, ExtensionString;
4558 std::tie(CPU, ExtensionString) =
4559 getParser().parseStringToEndOfStatement().trim().split('+');
4560
Nirav Davee833c6c2016-11-08 18:31:04 +00004561 if (parseToken(AsmToken::EndOfStatement))
4562 return true;
4563
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004564 SmallVector<StringRef, 4> RequestedExtensions;
4565 if (!ExtensionString.empty())
4566 ExtensionString.split(RequestedExtensions, '+');
4567
4568 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4569 // once that is tablegen'ed
4570 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004571 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004572 return false;
4573 }
4574
4575 MCSubtargetInfo &STI = copySTI();
4576 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004577 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004578
4579 FeatureBitset Features = STI.getFeatureBits();
4580 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004581 // Advance source location past '+'.
4582 CurLoc = incrementLoc(CurLoc, 1);
4583
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004584 bool EnableFeature = true;
4585
4586 if (Name.startswith_lower("no")) {
4587 EnableFeature = false;
4588 Name = Name.substr(2);
4589 }
4590
Tim Northover8b96c7e2017-05-15 19:42:15 +00004591 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004592 for (const auto &Extension : ExtensionMap) {
4593 if (Extension.Name != Name)
4594 continue;
4595
4596 if (Extension.Features.none())
4597 report_fatal_error("unsupported architectural extension: " + Name);
4598
4599 FeatureBitset ToggleFeatures = EnableFeature
4600 ? (~Features & Extension.Features)
4601 : ( Features & Extension.Features);
4602 uint64_t Features =
4603 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4604 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004605 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004606
4607 break;
4608 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004609
4610 if (!FoundExtension)
4611 Error(CurLoc, "unsupported architectural extension");
4612
4613 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004614 }
4615 return false;
4616}
4617
Chad Rosierdcd2a302014-10-22 20:35:57 +00004618/// parseDirectiveInst
4619/// ::= .inst opcode [, ...]
4620bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004621 if (getLexer().is(AsmToken::EndOfStatement))
4622 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004623
Nirav Davee833c6c2016-11-08 18:31:04 +00004624 auto parseOp = [&]() -> bool {
4625 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004626 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004627 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4628 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004629 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004630 if (check(!Value, L, "expected constant expression"))
4631 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004632 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004633 return false;
4634 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004635
Nirav Davee833c6c2016-11-08 18:31:04 +00004636 if (parseMany(parseOp))
4637 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004638 return false;
4639}
4640
Tim Northover3b0846e2014-05-24 12:50:23 +00004641// parseDirectiveTLSDescCall:
4642// ::= .tlsdesccall symbol
4643bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4644 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004645 if (check(getParser().parseIdentifier(Name), L,
4646 "expected symbol after directive") ||
4647 parseToken(AsmToken::EndOfStatement))
4648 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004649
Jim Grosbach6f482002015-05-18 18:43:14 +00004650 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004651 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4652 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004653
4654 MCInst Inst;
4655 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004656 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004657
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004658 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004659 return false;
4660}
4661
4662/// ::= .loh <lohName | lohId> label1, ..., labelN
4663/// The number of arguments depends on the loh identifier.
4664bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004665 MCLOHType Kind;
4666 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4667 if (getParser().getTok().isNot(AsmToken::Integer))
4668 return TokError("expected an identifier or a number in directive");
4669 // We successfully get a numeric value for the identifier.
4670 // Check if it is valid.
4671 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004672 if (Id <= -1U && !isValidMCLOHType(Id))
4673 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004674 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004675 } else {
4676 StringRef Name = getTok().getIdentifier();
4677 // We successfully parse an identifier.
4678 // Check if it is a recognized one.
4679 int Id = MCLOHNameToId(Name);
4680
4681 if (Id == -1)
4682 return TokError("invalid identifier in directive");
4683 Kind = (MCLOHType)Id;
4684 }
4685 // Consume the identifier.
4686 Lex();
4687 // Get the number of arguments of this LOH.
4688 int NbArgs = MCLOHIdToNbArgs(Kind);
4689
4690 assert(NbArgs != -1 && "Invalid number of arguments");
4691
4692 SmallVector<MCSymbol *, 3> Args;
4693 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4694 StringRef Name;
4695 if (getParser().parseIdentifier(Name))
4696 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004697 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004698
4699 if (Idx + 1 == NbArgs)
4700 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004701 if (parseToken(AsmToken::Comma,
4702 "unexpected token in '" + Twine(IDVal) + "' directive"))
4703 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004704 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004705 if (parseToken(AsmToken::EndOfStatement,
4706 "unexpected token in '" + Twine(IDVal) + "' directive"))
4707 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004708
4709 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4710 return false;
4711}
4712
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004713/// parseDirectiveLtorg
4714/// ::= .ltorg | .pool
4715bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004716 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4717 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004718 getTargetStreamer().emitCurrentConstantPool();
4719 return false;
4720}
4721
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004722/// parseDirectiveReq
4723/// ::= name .req registername
4724bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004725 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004726 Parser.Lex(); // Eat the '.req' token.
4727 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004728 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004729 unsigned RegNum;
4730 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004731
Sander de Smalen50d87022018-04-19 07:35:08 +00004732 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004733 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004734 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004735 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004736
Sander de Smalen50d87022018-04-19 07:35:08 +00004737 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004738 return true;
4739
Sander de Smalen50d87022018-04-19 07:35:08 +00004740 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004741 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004742 }
4743
Sander de Smalen50d87022018-04-19 07:35:08 +00004744 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004745 StringRef Kind;
4746 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004747 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004748 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004749
Sander de Smalen50d87022018-04-19 07:35:08 +00004750 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004751 return true;
4752
Sander de Smalen50d87022018-04-19 07:35:08 +00004753 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004754 return Error(SRegLoc,
4755 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004756 }
4757
Sander de Smalen50d87022018-04-19 07:35:08 +00004758 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00004759 StringRef Kind;
4760 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004761 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004762
Sander de Smalen50d87022018-04-19 07:35:08 +00004763 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00004764 return true;
4765
Sander de Smalen50d87022018-04-19 07:35:08 +00004766 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00004767 return Error(SRegLoc,
4768 "sve predicate register without type specifier expected");
4769 }
4770
Sander de Smalen50d87022018-04-19 07:35:08 +00004771 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00004772 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004773
4774 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004775 if (parseToken(AsmToken::EndOfStatement,
4776 "unexpected input in .req directive"))
4777 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004778
Sander de Smalen8e607342017-11-15 15:44:43 +00004779 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004780 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004781 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4782
Nirav Dave2364748a2016-09-16 18:30:20 +00004783 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004784}
4785
4786/// parseDirectiveUneq
4787/// ::= .unreq registername
4788bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004789 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004790 if (getTok().isNot(AsmToken::Identifier))
4791 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004792 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4793 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004794 if (parseToken(AsmToken::EndOfStatement))
4795 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004796 return false;
4797}
4798
Tim Northover3b0846e2014-05-24 12:50:23 +00004799bool
4800AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4801 AArch64MCExpr::VariantKind &ELFRefKind,
4802 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4803 int64_t &Addend) {
4804 ELFRefKind = AArch64MCExpr::VK_INVALID;
4805 DarwinRefKind = MCSymbolRefExpr::VK_None;
4806 Addend = 0;
4807
4808 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4809 ELFRefKind = AE->getKind();
4810 Expr = AE->getSubExpr();
4811 }
4812
4813 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4814 if (SE) {
4815 // It's a simple symbol reference with no addend.
4816 DarwinRefKind = SE->getKind();
4817 return true;
4818 }
4819
4820 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4821 if (!BE)
4822 return false;
4823
4824 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4825 if (!SE)
4826 return false;
4827 DarwinRefKind = SE->getKind();
4828
4829 if (BE->getOpcode() != MCBinaryExpr::Add &&
4830 BE->getOpcode() != MCBinaryExpr::Sub)
4831 return false;
4832
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004833 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004834 // on here than we can deal with.
4835 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4836 if (!AddendExpr)
4837 return false;
4838
4839 Addend = AddendExpr->getValue();
4840 if (BE->getOpcode() == MCBinaryExpr::Sub)
4841 Addend = -Addend;
4842
4843 // It's some symbol reference + a constant addend, but really
4844 // shouldn't use both Darwin and ELF syntax.
4845 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4846 DarwinRefKind == MCSymbolRefExpr::VK_None;
4847}
4848
4849/// Force static initialization.
4850extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004851 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4852 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4853 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004854}
4855
4856#define GET_REGISTER_MATCHER
4857#define GET_SUBTARGET_FEATURE_NAME
4858#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004859#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004860#include "AArch64GenAsmMatcher.inc"
4861
4862// Define this matcher function after the auto-generated include so we
4863// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004864unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004865 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004866 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004867 // If the kind is a token for a literal immediate, check if our asm
4868 // operand matches. This is for InstAliases which have a fixed-value
4869 // immediate in the syntax.
4870 int64_t ExpectedVal;
4871 switch (Kind) {
4872 default:
4873 return Match_InvalidOperand;
4874 case MCK__35_0:
4875 ExpectedVal = 0;
4876 break;
4877 case MCK__35_1:
4878 ExpectedVal = 1;
4879 break;
4880 case MCK__35_12:
4881 ExpectedVal = 12;
4882 break;
4883 case MCK__35_16:
4884 ExpectedVal = 16;
4885 break;
4886 case MCK__35_2:
4887 ExpectedVal = 2;
4888 break;
4889 case MCK__35_24:
4890 ExpectedVal = 24;
4891 break;
4892 case MCK__35_3:
4893 ExpectedVal = 3;
4894 break;
4895 case MCK__35_32:
4896 ExpectedVal = 32;
4897 break;
4898 case MCK__35_4:
4899 ExpectedVal = 4;
4900 break;
4901 case MCK__35_48:
4902 ExpectedVal = 48;
4903 break;
4904 case MCK__35_6:
4905 ExpectedVal = 6;
4906 break;
4907 case MCK__35_64:
4908 ExpectedVal = 64;
4909 break;
4910 case MCK__35_8:
4911 ExpectedVal = 8;
4912 break;
4913 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004914 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004915 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004916 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004917 if (!CE)
4918 return Match_InvalidOperand;
4919 if (CE->getValue() == ExpectedVal)
4920 return Match_Success;
4921 return Match_InvalidOperand;
4922}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004923
Alex Bradbury58eba092016-11-01 16:32:05 +00004924OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004925AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4926
4927 SMLoc S = getLoc();
4928
4929 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4930 Error(S, "expected register");
4931 return MatchOperand_ParseFail;
4932 }
4933
Sander de Smalen50d87022018-04-19 07:35:08 +00004934 unsigned FirstReg;
4935 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
4936 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004937 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00004938
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004939 const MCRegisterClass &WRegClass =
4940 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4941 const MCRegisterClass &XRegClass =
4942 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4943
4944 bool isXReg = XRegClass.contains(FirstReg),
4945 isWReg = WRegClass.contains(FirstReg);
4946 if (!isXReg && !isWReg) {
4947 Error(S, "expected first even register of a "
4948 "consecutive same-size even/odd register pair");
4949 return MatchOperand_ParseFail;
4950 }
4951
4952 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4953 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4954
4955 if (FirstEncoding & 0x1) {
4956 Error(S, "expected first even register of a "
4957 "consecutive same-size even/odd register pair");
4958 return MatchOperand_ParseFail;
4959 }
4960
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004961 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00004962 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004963 return MatchOperand_ParseFail;
4964 }
4965 // Eat the comma
4966 getParser().Lex();
4967
4968 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00004969 unsigned SecondReg;
4970 Res = tryParseScalarRegister(SecondReg);
4971 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004972 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004973
Eugene Zelenko049b0172017-01-06 00:30:53 +00004974 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004975 (isXReg && !XRegClass.contains(SecondReg)) ||
4976 (isWReg && !WRegClass.contains(SecondReg))) {
4977 Error(E,"expected second odd register of a "
4978 "consecutive same-size even/odd register pair");
4979 return MatchOperand_ParseFail;
4980 }
Joel Jones504bf332016-10-24 13:37:13 +00004981
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004982 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004983 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004984 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4985 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4986 } else {
4987 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4988 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4989 }
4990
Florian Hahnc4422242017-11-07 13:07:50 +00004991 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4992 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004993
4994 return MatchOperand_Success;
4995}
Florian Hahn91f11e52017-11-07 16:45:48 +00004996
Sander de Smaleneb896b12018-04-25 09:26:47 +00004997template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00004998OperandMatchResultTy
4999AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005000 const SMLoc S = getLoc();
5001 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005002 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005003 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005004
Sander de Smalen8e607342017-11-15 15:44:43 +00005005 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005006 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005007
5008 if (Res != MatchOperand_Success)
5009 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005010
5011 if (ParseSuffix && Kind.empty())
5012 return MatchOperand_NoMatch;
5013
Sander de Smalen73937b72018-04-11 07:36:10 +00005014 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5015 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005016 return MatchOperand_NoMatch;
5017
Sander de Smalen73937b72018-04-11 07:36:10 +00005018 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005019
5020 // No shift/extend is the default.
5021 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5022 Operands.push_back(AArch64Operand::CreateVectorReg(
5023 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5024
5025 return MatchOperand_Success;
5026 }
5027
5028 // Eat the comma
5029 getParser().Lex();
5030
5031 // Match the shift
5032 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5033 Res = tryParseOptionalShiftExtend(ExtOpnd);
5034 if (Res != MatchOperand_Success)
5035 return Res;
5036
5037 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005038 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005039 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5040 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5041 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005042
5043 return MatchOperand_Success;
5044}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005045
5046OperandMatchResultTy
5047AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5048 MCAsmParser &Parser = getParser();
5049
5050 SMLoc SS = getLoc();
5051 const AsmToken &TokE = Parser.getTok();
5052 bool IsHash = TokE.is(AsmToken::Hash);
5053
5054 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5055 return MatchOperand_NoMatch;
5056
5057 int64_t Pattern;
5058 if (IsHash) {
5059 Parser.Lex(); // Eat hash
5060
5061 // Parse the immediate operand.
5062 const MCExpr *ImmVal;
5063 SS = getLoc();
5064 if (Parser.parseExpression(ImmVal))
5065 return MatchOperand_ParseFail;
5066
5067 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5068 if (!MCE)
5069 return MatchOperand_ParseFail;
5070
5071 Pattern = MCE->getValue();
5072 } else {
5073 // Parse the pattern
5074 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5075 if (!Pat)
5076 return MatchOperand_NoMatch;
5077
5078 Parser.Lex();
5079 Pattern = Pat->Encoding;
5080 assert(Pattern >= 0 && Pattern < 32);
5081 }
5082
5083 Operands.push_back(
5084 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5085 SS, getLoc(), getContext()));
5086
5087 return MatchOperand_Success;
5088}