blob: cf22a1cbadc58418838468fefab07e11b5ec3137 [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
Sander de Smalen97ca6b92018-06-01 07:25:46 +0000755 template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
756 if (isLogicalImm<T>() && !isSVECpyImm<T>())
757 return DiagnosticPredicateTy::Match;
758 return DiagnosticPredicateTy::NoMatch;
759 }
760
Tim Northover3b0846e2014-05-24 12:50:23 +0000761 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000762
Tim Northover3b0846e2014-05-24 12:50:23 +0000763 bool isSIMDImmType10() const {
764 if (!isImm())
765 return false;
766 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
767 if (!MCE)
768 return false;
769 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
770 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000771
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000772 template<int N>
773 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000774 if (!isImm())
775 return false;
776 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
777 if (!MCE)
778 return true;
779 int64_t Val = MCE->getValue();
780 if (Val & 0x3)
781 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000782 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
783 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000784 }
785
786 bool
787 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
788 if (!isImm())
789 return false;
790
791 AArch64MCExpr::VariantKind ELFRefKind;
792 MCSymbolRefExpr::VariantKind DarwinRefKind;
793 int64_t Addend;
794 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
795 DarwinRefKind, Addend)) {
796 return false;
797 }
798 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
799 return false;
800
801 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
802 if (ELFRefKind == AllowedModifiers[i])
803 return Addend == 0;
804 }
805
806 return false;
807 }
808
809 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000810 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000811 }
812
813 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000814 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
815 AArch64MCExpr::VK_TPREL_G2,
816 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000817 }
818
819 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000820 return isMovWSymbol({
821 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000822 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
823 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000824 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000825 }
826
827 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000828 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
829 AArch64MCExpr::VK_TPREL_G0,
830 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000831 }
832
833 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000834 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000835 }
836
837 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000838 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000839 }
840
841 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000842 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
843 AArch64MCExpr::VK_TPREL_G1_NC,
844 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000845 }
846
847 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000848 return isMovWSymbol(
849 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
850 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000851 }
852
853 template<int RegWidth, int Shift>
854 bool isMOVZMovAlias() const {
855 if (!isImm()) return false;
856
857 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
858 if (!CE) return false;
859 uint64_t Value = CE->getValue();
860
Tim Northoverdaa1c012016-06-16 01:42:25 +0000861 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000862 }
863
864 template<int RegWidth, int Shift>
865 bool isMOVNMovAlias() const {
866 if (!isImm()) return false;
867
868 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
869 if (!CE) return false;
870 uint64_t Value = CE->getValue();
871
Tim Northoverdaa1c012016-06-16 01:42:25 +0000872 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000873 }
874
875 bool isFPImm() const { return Kind == k_FPImm; }
876 bool isBarrier() const { return Kind == k_Barrier; }
877 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000878
Tim Northover3b0846e2014-05-24 12:50:23 +0000879 bool isMRSSystemRegister() const {
880 if (!isSysReg()) return false;
881
Tim Northover7cd58932015-01-22 17:23:04 +0000882 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000883 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000884
Tim Northover3b0846e2014-05-24 12:50:23 +0000885 bool isMSRSystemRegister() const {
886 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000887 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000888 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000889
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000890 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000891 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000892 return (SysReg.PStateField == AArch64PState::PAN ||
893 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000894 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000895
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000896 bool isSystemPStateFieldWithImm0_15() const {
897 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000898 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000899 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000900
Florian Hahnc4422242017-11-07 13:07:50 +0000901 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000902 return Kind == k_Register;
903 }
904
905 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000906 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
907 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000908
Florian Hahnc4422242017-11-07 13:07:50 +0000909 bool isNeonVectorReg() const {
910 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
911 }
912
913 bool isNeonVectorRegLo() const {
914 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000915 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
916 Reg.RegNum);
917 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000918
Sander de Smalencd6be962017-12-20 11:02:42 +0000919 template <unsigned Class> bool isSVEVectorReg() const {
920 RegKind RK;
921 switch (Class) {
922 case AArch64::ZPRRegClassID:
923 RK = RegKind::SVEDataVector;
924 break;
925 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000926 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000927 RK = RegKind::SVEPredicateVector;
928 break;
929 default:
930 llvm_unreachable("Unsupport register class");
931 }
932
933 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000934 AArch64MCRegisterClasses[Class].contains(getReg());
935 }
936
Sander de Smalencd6be962017-12-20 11:02:42 +0000937 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +0000938 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
939 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
940 return DiagnosticPredicateTy::NoMatch;
941
942 if (isSVEVectorReg<Class>() &&
943 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
944 return DiagnosticPredicateTy::Match;
945
946 return DiagnosticPredicateTy::NearMatch;
947 }
948
949 template <int ElementWidth, unsigned Class>
950 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
951 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
952 return DiagnosticPredicateTy::NoMatch;
953
954 if (isSVEVectorReg<Class>() &&
955 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
956 return DiagnosticPredicateTy::Match;
957
958 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +0000959 }
960
Sander de Smaleneb896b12018-04-25 09:26:47 +0000961 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +0000962 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
963 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +0000964 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
965 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
966 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000967 return DiagnosticPredicateTy::NoMatch;
968
Sander de Smalen5861c262018-04-30 07:24:38 +0000969 // Give a more specific diagnostic when the user has explicitly typed in
970 // a shift-amount that does not match what is expected, but for which
971 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
972 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
973 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
974 ShiftExtendTy == AArch64_AM::SXTW) &&
975 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
976 return DiagnosticPredicateTy::NoMatch;
977
978 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000979 return DiagnosticPredicateTy::Match;
980
981 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +0000982 }
983
Tim Northover3b0846e2014-05-24 12:50:23 +0000984 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000985 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000986 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
987 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000988
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000989 bool isWSeqPair() 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::WSeqPairsClassRegClassID].contains(
992 Reg.RegNum);
993 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000994
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000995 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000996 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000997 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
998 Reg.RegNum);
999 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001000
Sam Parker5f934642017-08-31 09:27:04 +00001001 template<int64_t Angle, int64_t Remainder>
1002 bool isComplexRotation() const {
1003 if (!isImm()) return false;
1004
1005 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1006 if (!CE) return false;
1007 uint64_t Value = CE->getValue();
1008
1009 return (Value % Angle == Remainder && Value <= 270);
1010 }
1011
Sander de Smalen149916d2018-04-20 07:24:20 +00001012 template <unsigned RegClassID> bool isGPR64() const {
1013 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1014 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1015 }
1016
1017 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001018 DiagnosticPredicate isGPR64WithShiftExtend() const {
1019 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1020 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001021
Sander de Smalenfe17a782018-04-26 12:54:42 +00001022 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1023 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1024 return DiagnosticPredicateTy::Match;
1025 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001026 }
1027
Tim Northover3b0846e2014-05-24 12:50:23 +00001028 /// Is this a vector list with the type implicit (presumably attached to the
1029 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001030 template <RegKind VectorKind, unsigned NumRegs>
1031 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001032 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001033 VectorList.NumElements == 0 &&
1034 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001035 }
1036
Sander de Smalen650234b2018-04-12 11:40:52 +00001037 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1038 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001039 bool isTypedVectorList() const {
1040 if (Kind != k_VectorList)
1041 return false;
1042 if (VectorList.Count != NumRegs)
1043 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001044 if (VectorList.RegisterKind != VectorKind)
1045 return false;
1046 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001047 return false;
1048 return VectorList.NumElements == NumElements;
1049 }
1050
Sander de Smalenc33d6682018-06-04 06:40:55 +00001051 template <int Min, int Max>
1052 DiagnosticPredicate isVectorIndex() const {
1053 if (Kind != k_VectorIndex)
1054 return DiagnosticPredicateTy::NoMatch;
1055 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1056 return DiagnosticPredicateTy::Match;
1057 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001058 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001059
Tim Northover3b0846e2014-05-24 12:50:23 +00001060 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001061
Tim Northover3b0846e2014-05-24 12:50:23 +00001062 bool isTokenEqual(StringRef Str) const {
1063 return Kind == k_Token && getToken() == Str;
1064 }
1065 bool isSysCR() const { return Kind == k_SysCR; }
1066 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001067 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001068 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1069 bool isShifter() const {
1070 if (!isShiftExtend())
1071 return false;
1072
1073 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1074 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1075 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1076 ST == AArch64_AM::MSL);
1077 }
1078 bool isExtend() const {
1079 if (!isShiftExtend())
1080 return false;
1081
1082 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1083 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1084 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1085 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1086 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1087 ET == AArch64_AM::LSL) &&
1088 getShiftExtendAmount() <= 4;
1089 }
1090
1091 bool isExtend64() const {
1092 if (!isExtend())
1093 return false;
1094 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1095 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1096 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1097 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001098
Tim Northover3b0846e2014-05-24 12:50:23 +00001099 bool isExtendLSL64() const {
1100 if (!isExtend())
1101 return false;
1102 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1103 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1104 ET == AArch64_AM::LSL) &&
1105 getShiftExtendAmount() <= 4;
1106 }
1107
1108 template<int Width> bool isMemXExtend() const {
1109 if (!isExtend())
1110 return false;
1111 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1112 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1113 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1114 getShiftExtendAmount() == 0);
1115 }
1116
1117 template<int Width> bool isMemWExtend() const {
1118 if (!isExtend())
1119 return false;
1120 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1121 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1122 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1123 getShiftExtendAmount() == 0);
1124 }
1125
1126 template <unsigned width>
1127 bool isArithmeticShifter() const {
1128 if (!isShifter())
1129 return false;
1130
1131 // An arithmetic shifter is LSL, LSR, or ASR.
1132 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1133 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1134 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1135 }
1136
1137 template <unsigned width>
1138 bool isLogicalShifter() const {
1139 if (!isShifter())
1140 return false;
1141
1142 // A logical shifter is LSL, LSR, ASR or ROR.
1143 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1144 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1145 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1146 getShiftExtendAmount() < width;
1147 }
1148
1149 bool isMovImm32Shifter() const {
1150 if (!isShifter())
1151 return false;
1152
1153 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1154 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1155 if (ST != AArch64_AM::LSL)
1156 return false;
1157 uint64_t Val = getShiftExtendAmount();
1158 return (Val == 0 || Val == 16);
1159 }
1160
1161 bool isMovImm64Shifter() const {
1162 if (!isShifter())
1163 return false;
1164
1165 // A MOVi shifter is LSL of 0 or 16.
1166 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1167 if (ST != AArch64_AM::LSL)
1168 return false;
1169 uint64_t Val = getShiftExtendAmount();
1170 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1171 }
1172
1173 bool isLogicalVecShifter() const {
1174 if (!isShifter())
1175 return false;
1176
1177 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1178 unsigned Shift = getShiftExtendAmount();
1179 return getShiftExtendType() == AArch64_AM::LSL &&
1180 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1181 }
1182
1183 bool isLogicalVecHalfWordShifter() const {
1184 if (!isLogicalVecShifter())
1185 return false;
1186
1187 // A logical vector shifter is a left shift by 0 or 8.
1188 unsigned Shift = getShiftExtendAmount();
1189 return getShiftExtendType() == AArch64_AM::LSL &&
1190 (Shift == 0 || Shift == 8);
1191 }
1192
1193 bool isMoveVecShifter() const {
1194 if (!isShiftExtend())
1195 return false;
1196
1197 // A logical vector shifter is a left shift by 8 or 16.
1198 unsigned Shift = getShiftExtendAmount();
1199 return getShiftExtendType() == AArch64_AM::MSL &&
1200 (Shift == 8 || Shift == 16);
1201 }
1202
1203 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1204 // to LDUR/STUR when the offset is not legal for the former but is for
1205 // the latter. As such, in addition to checking for being a legal unscaled
1206 // address, also check that it is not a legal scaled address. This avoids
1207 // ambiguity in the matcher.
1208 template<int Width>
1209 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001210 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001211 }
1212
1213 bool isAdrpLabel() const {
1214 // Validation was handled during parsing, so we just sanity check that
1215 // something didn't go haywire.
1216 if (!isImm())
1217 return false;
1218
1219 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1220 int64_t Val = CE->getValue();
1221 int64_t Min = - (4096 * (1LL << (21 - 1)));
1222 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1223 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1224 }
1225
1226 return true;
1227 }
1228
1229 bool isAdrLabel() const {
1230 // Validation was handled during parsing, so we just sanity check that
1231 // something didn't go haywire.
1232 if (!isImm())
1233 return false;
1234
1235 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1236 int64_t Val = CE->getValue();
1237 int64_t Min = - (1LL << (21 - 1));
1238 int64_t Max = ((1LL << (21 - 1)) - 1);
1239 return Val >= Min && Val <= Max;
1240 }
1241
1242 return true;
1243 }
1244
1245 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1246 // Add as immediates when possible. Null MCExpr = 0.
1247 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001248 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001249 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001250 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001251 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001252 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001253 }
1254
1255 void addRegOperands(MCInst &Inst, unsigned N) const {
1256 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001257 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001258 }
1259
1260 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1261 assert(N == 1 && "Invalid number of operands!");
1262 assert(
1263 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1264
1265 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1266 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1267 RI->getEncodingValue(getReg()));
1268
Jim Grosbache9119e42015-05-13 18:37:00 +00001269 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001270 }
1271
1272 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1273 assert(N == 1 && "Invalid number of operands!");
1274 assert(
1275 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001276 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001277 }
1278
1279 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1280 assert(N == 1 && "Invalid number of operands!");
1281 assert(
1282 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001283 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001284 }
1285
1286 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1287 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001288 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001289 }
1290
Sander de Smalen525e3222018-04-12 13:19:32 +00001291 enum VecListIndexType {
1292 VecListIdx_DReg = 0,
1293 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001294 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001295 };
1296
1297 template <VecListIndexType RegTy, unsigned NumRegs>
1298 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001299 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001300 static const unsigned FirstRegs[][5] = {
1301 /* DReg */ { AArch64::Q0,
1302 AArch64::D0, AArch64::D0_D1,
1303 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1304 /* QReg */ { AArch64::Q0,
1305 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001306 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1307 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001308 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001309 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001310 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001311
Sander de Smalen7a210db2018-04-16 10:46:18 +00001312 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1313 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001314
Sander de Smalen525e3222018-04-12 13:19:32 +00001315 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1316 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1317 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001318 }
1319
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001320 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001321 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001322 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001323 }
1324
1325 void addImmOperands(MCInst &Inst, unsigned N) const {
1326 assert(N == 1 && "Invalid number of operands!");
1327 // If this is a pageoff symrefexpr with an addend, adjust the addend
1328 // to be only the page-offset portion. Otherwise, just add the expr
1329 // as-is.
1330 addExpr(Inst, getImm());
1331 }
1332
Sander de Smalen62770792018-05-25 09:47:52 +00001333 template <int Shift>
1334 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001335 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001336 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1337 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1338 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1339 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001340 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001341 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001342 } else {
1343 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001344 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001345 }
1346 }
1347
Sander de Smalen62770792018-05-25 09:47:52 +00001348 template <int Shift>
1349 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001350 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001351 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1352 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1353 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1354 } else
1355 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001356 }
1357
Tim Northover3b0846e2014-05-24 12:50:23 +00001358 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1359 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001360 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001361 }
1362
1363 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1364 assert(N == 1 && "Invalid number of operands!");
1365 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1366 if (!MCE)
1367 addExpr(Inst, getImm());
1368 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001369 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001370 }
1371
1372 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1373 addImmOperands(Inst, N);
1374 }
1375
1376 template<int Scale>
1377 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1378 assert(N == 1 && "Invalid number of operands!");
1379 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1380
1381 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001382 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001383 return;
1384 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001385 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001386 }
1387
Sander de Smalen5c625982018-04-13 12:56:14 +00001388 template <int Scale>
1389 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1390 assert(N == 1 && "Invalid number of operands!");
1391 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1392 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1393 }
1394
Sander de Smalena1c259c2018-01-29 13:05:38 +00001395 template <typename T>
1396 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001397 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001398 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001399 typename std::make_unsigned<T>::type Val = MCE->getValue();
1400 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001401 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001402 }
1403
Sander de Smalena1c259c2018-01-29 13:05:38 +00001404 template <typename T>
1405 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001406 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001407 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001408 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1409 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001410 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001411 }
1412
Tim Northover3b0846e2014-05-24 12:50:23 +00001413 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1414 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001415 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001416 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001417 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001418 }
1419
1420 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1421 // Branch operands don't encode the low bits, so shift them off
1422 // here. If it's a label, however, just put it on directly as there's
1423 // not enough information now to do anything.
1424 assert(N == 1 && "Invalid number of operands!");
1425 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1426 if (!MCE) {
1427 addExpr(Inst, getImm());
1428 return;
1429 }
1430 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001431 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001432 }
1433
1434 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1435 // Branch operands don't encode the low bits, so shift them off
1436 // here. If it's a label, however, just put it on directly as there's
1437 // not enough information now to do anything.
1438 assert(N == 1 && "Invalid number of operands!");
1439 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1440 if (!MCE) {
1441 addExpr(Inst, getImm());
1442 return;
1443 }
1444 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001445 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001446 }
1447
1448 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1449 // Branch operands don't encode the low bits, so shift them off
1450 // here. If it's a label, however, just put it on directly as there's
1451 // not enough information now to do anything.
1452 assert(N == 1 && "Invalid number of operands!");
1453 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1454 if (!MCE) {
1455 addExpr(Inst, getImm());
1456 return;
1457 }
1458 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001459 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001460 }
1461
1462 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1463 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001464 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001465 }
1466
1467 void addBarrierOperands(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(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001470 }
1471
1472 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1473 assert(N == 1 && "Invalid number of operands!");
1474
Jim Grosbache9119e42015-05-13 18:37:00 +00001475 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001476 }
1477
1478 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1479 assert(N == 1 && "Invalid number of operands!");
1480
Jim Grosbache9119e42015-05-13 18:37:00 +00001481 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001482 }
1483
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001484 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1485 assert(N == 1 && "Invalid number of operands!");
1486
1487 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1488 }
1489
1490 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001491 assert(N == 1 && "Invalid number of operands!");
1492
Jim Grosbache9119e42015-05-13 18:37:00 +00001493 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001494 }
1495
1496 void addSysCROperands(MCInst &Inst, unsigned N) const {
1497 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001498 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001499 }
1500
1501 void addPrefetchOperands(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(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001504 }
1505
Oliver Stannarda34e4702015-12-01 10:48:51 +00001506 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1507 assert(N == 1 && "Invalid number of operands!");
1508 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1509 }
1510
Tim Northover3b0846e2014-05-24 12:50:23 +00001511 void addShifterOperands(MCInst &Inst, unsigned N) const {
1512 assert(N == 1 && "Invalid number of operands!");
1513 unsigned Imm =
1514 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001515 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001516 }
1517
1518 void addExtendOperands(MCInst &Inst, unsigned N) const {
1519 assert(N == 1 && "Invalid number of operands!");
1520 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1521 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1522 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001523 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001524 }
1525
1526 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1527 assert(N == 1 && "Invalid number of operands!");
1528 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1529 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1530 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001531 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001532 }
1533
1534 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1535 assert(N == 2 && "Invalid number of operands!");
1536 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1537 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001538 Inst.addOperand(MCOperand::createImm(IsSigned));
1539 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001540 }
1541
1542 // For 8-bit load/store instructions with a register offset, both the
1543 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1544 // they're disambiguated by whether the shift was explicit or implicit rather
1545 // than its size.
1546 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1547 assert(N == 2 && "Invalid number of operands!");
1548 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1549 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001550 Inst.addOperand(MCOperand::createImm(IsSigned));
1551 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001552 }
1553
1554 template<int Shift>
1555 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1556 assert(N == 1 && "Invalid number of operands!");
1557
1558 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1559 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001560 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001561 }
1562
1563 template<int Shift>
1564 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1565 assert(N == 1 && "Invalid number of operands!");
1566
1567 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1568 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001569 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001570 }
1571
Sam Parker5f934642017-08-31 09:27:04 +00001572 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1573 assert(N == 1 && "Invalid number of operands!");
1574 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1575 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1576 }
1577
1578 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1579 assert(N == 1 && "Invalid number of operands!");
1580 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1581 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1582 }
1583
Tim Northover3b0846e2014-05-24 12:50:23 +00001584 void print(raw_ostream &OS) const override;
1585
David Blaikie960ea3f2014-06-08 16:18:35 +00001586 static std::unique_ptr<AArch64Operand>
1587 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1588 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001589 Op->Tok.Data = Str.data();
1590 Op->Tok.Length = Str.size();
1591 Op->Tok.IsSuffix = IsSuffix;
1592 Op->StartLoc = S;
1593 Op->EndLoc = S;
1594 return Op;
1595 }
1596
David Blaikie960ea3f2014-06-08 16:18:35 +00001597 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001598 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
1599 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1600 unsigned ShiftAmount = 0,
1601 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001602 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001603 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001604 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001605 Op->Reg.ElementWidth = 0;
1606 Op->Reg.ShiftExtend.Type = ExtTy;
1607 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1608 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001609 Op->StartLoc = S;
1610 Op->EndLoc = E;
1611 return Op;
1612 }
1613
David Blaikie960ea3f2014-06-08 16:18:35 +00001614 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001615 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001616 SMLoc S, SMLoc E, MCContext &Ctx,
1617 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1618 unsigned ShiftAmount = 0,
1619 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001620 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1621 Kind == RegKind::SVEPredicateVector) &&
1622 "Invalid vector kind");
Sander de Smalen149916d2018-04-20 07:24:20 +00001623 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, ExtTy, ShiftAmount,
1624 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001625 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001626 return Op;
1627 }
1628
1629 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001630 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001631 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1632 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001633 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001634 Op->VectorList.RegNum = RegNum;
1635 Op->VectorList.Count = Count;
1636 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001637 Op->VectorList.ElementWidth = ElementWidth;
1638 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001639 Op->StartLoc = S;
1640 Op->EndLoc = E;
1641 return Op;
1642 }
1643
David Blaikie960ea3f2014-06-08 16:18:35 +00001644 static std::unique_ptr<AArch64Operand>
1645 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1646 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001647 Op->VectorIndex.Val = Idx;
1648 Op->StartLoc = S;
1649 Op->EndLoc = E;
1650 return Op;
1651 }
1652
David Blaikie960ea3f2014-06-08 16:18:35 +00001653 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1654 SMLoc E, MCContext &Ctx) {
1655 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001656 Op->Imm.Val = Val;
1657 Op->StartLoc = S;
1658 Op->EndLoc = E;
1659 return Op;
1660 }
1661
David Blaikie960ea3f2014-06-08 16:18:35 +00001662 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1663 unsigned ShiftAmount,
1664 SMLoc S, SMLoc E,
1665 MCContext &Ctx) {
1666 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001667 Op->ShiftedImm .Val = Val;
1668 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1669 Op->StartLoc = S;
1670 Op->EndLoc = E;
1671 return Op;
1672 }
1673
David Blaikie960ea3f2014-06-08 16:18:35 +00001674 static std::unique_ptr<AArch64Operand>
1675 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1676 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001677 Op->CondCode.Code = Code;
1678 Op->StartLoc = S;
1679 Op->EndLoc = E;
1680 return Op;
1681 }
1682
David Blaikie960ea3f2014-06-08 16:18:35 +00001683 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1684 MCContext &Ctx) {
1685 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001686 Op->FPImm.Val = Val;
1687 Op->StartLoc = S;
1688 Op->EndLoc = S;
1689 return Op;
1690 }
1691
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001692 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1693 StringRef Str,
1694 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001695 MCContext &Ctx) {
1696 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001697 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001698 Op->Barrier.Data = Str.data();
1699 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001700 Op->StartLoc = S;
1701 Op->EndLoc = S;
1702 return Op;
1703 }
1704
Tim Northover7cd58932015-01-22 17:23:04 +00001705 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1706 uint32_t MRSReg,
1707 uint32_t MSRReg,
1708 uint32_t PStateField,
1709 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001710 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001711 Op->SysReg.Data = Str.data();
1712 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001713 Op->SysReg.MRSReg = MRSReg;
1714 Op->SysReg.MSRReg = MSRReg;
1715 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001716 Op->StartLoc = S;
1717 Op->EndLoc = S;
1718 return Op;
1719 }
1720
David Blaikie960ea3f2014-06-08 16:18:35 +00001721 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1722 SMLoc E, MCContext &Ctx) {
1723 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001724 Op->SysCRImm.Val = Val;
1725 Op->StartLoc = S;
1726 Op->EndLoc = E;
1727 return Op;
1728 }
1729
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001730 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1731 StringRef Str,
1732 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001733 MCContext &Ctx) {
1734 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001735 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001736 Op->Barrier.Data = Str.data();
1737 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001738 Op->StartLoc = S;
1739 Op->EndLoc = S;
1740 return Op;
1741 }
1742
Oliver Stannarda34e4702015-12-01 10:48:51 +00001743 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1744 StringRef Str,
1745 SMLoc S,
1746 MCContext &Ctx) {
1747 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1748 Op->PSBHint.Val = Val;
1749 Op->PSBHint.Data = Str.data();
1750 Op->PSBHint.Length = Str.size();
1751 Op->StartLoc = S;
1752 Op->EndLoc = S;
1753 return Op;
1754 }
1755
David Blaikie960ea3f2014-06-08 16:18:35 +00001756 static std::unique_ptr<AArch64Operand>
1757 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1758 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1759 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001760 Op->ShiftExtend.Type = ShOp;
1761 Op->ShiftExtend.Amount = Val;
1762 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1763 Op->StartLoc = S;
1764 Op->EndLoc = E;
1765 return Op;
1766 }
1767};
1768
1769} // end anonymous namespace.
1770
1771void AArch64Operand::print(raw_ostream &OS) const {
1772 switch (Kind) {
1773 case k_FPImm:
1774 OS << "<fpimm " << getFPImm() << "("
1775 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1776 break;
1777 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001778 StringRef Name = getBarrierName();
1779 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001780 OS << "<barrier " << Name << ">";
1781 else
1782 OS << "<barrier invalid #" << getBarrier() << ">";
1783 break;
1784 }
1785 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001786 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001787 break;
1788 case k_ShiftedImm: {
1789 unsigned Shift = getShiftedImmShift();
1790 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001791 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001792 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1793 break;
1794 }
1795 case k_CondCode:
1796 OS << "<condcode " << getCondCode() << ">";
1797 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001798 case k_VectorList: {
1799 OS << "<vectorlist ";
1800 unsigned Reg = getVectorListStart();
1801 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1802 OS << Reg + i << " ";
1803 OS << ">";
1804 break;
1805 }
1806 case k_VectorIndex:
1807 OS << "<vectorindex " << getVectorIndex() << ">";
1808 break;
1809 case k_SysReg:
1810 OS << "<sysreg: " << getSysReg() << '>';
1811 break;
1812 case k_Token:
1813 OS << "'" << getToken() << "'";
1814 break;
1815 case k_SysCR:
1816 OS << "c" << getSysCR();
1817 break;
1818 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001819 StringRef Name = getPrefetchName();
1820 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001821 OS << "<prfop " << Name << ">";
1822 else
1823 OS << "<prfop invalid #" << getPrefetch() << ">";
1824 break;
1825 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001826 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001827 OS << getPSBHintName();
1828 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00001829 case k_Register:
1830 OS << "<register " << getReg() << ">";
1831 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
1832 break;
1833 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001834 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001835 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1836 << getShiftExtendAmount();
1837 if (!hasShiftExtendAmount())
1838 OS << "<imp>";
1839 OS << '>';
1840 break;
1841 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001842}
1843
1844/// @name Auto-generated Match Functions
1845/// {
1846
1847static unsigned MatchRegisterName(StringRef Name);
1848
1849/// }
1850
Florian Hahnc4422242017-11-07 13:07:50 +00001851static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001852 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001853 .Case("v0", AArch64::Q0)
1854 .Case("v1", AArch64::Q1)
1855 .Case("v2", AArch64::Q2)
1856 .Case("v3", AArch64::Q3)
1857 .Case("v4", AArch64::Q4)
1858 .Case("v5", AArch64::Q5)
1859 .Case("v6", AArch64::Q6)
1860 .Case("v7", AArch64::Q7)
1861 .Case("v8", AArch64::Q8)
1862 .Case("v9", AArch64::Q9)
1863 .Case("v10", AArch64::Q10)
1864 .Case("v11", AArch64::Q11)
1865 .Case("v12", AArch64::Q12)
1866 .Case("v13", AArch64::Q13)
1867 .Case("v14", AArch64::Q14)
1868 .Case("v15", AArch64::Q15)
1869 .Case("v16", AArch64::Q16)
1870 .Case("v17", AArch64::Q17)
1871 .Case("v18", AArch64::Q18)
1872 .Case("v19", AArch64::Q19)
1873 .Case("v20", AArch64::Q20)
1874 .Case("v21", AArch64::Q21)
1875 .Case("v22", AArch64::Q22)
1876 .Case("v23", AArch64::Q23)
1877 .Case("v24", AArch64::Q24)
1878 .Case("v25", AArch64::Q25)
1879 .Case("v26", AArch64::Q26)
1880 .Case("v27", AArch64::Q27)
1881 .Case("v28", AArch64::Q28)
1882 .Case("v29", AArch64::Q29)
1883 .Case("v30", AArch64::Q30)
1884 .Case("v31", AArch64::Q31)
1885 .Default(0);
1886}
1887
Sander de Smalen73937b72018-04-11 07:36:10 +00001888/// Returns an optional pair of (#elements, element-width) if Suffix
1889/// is a valid vector kind. Where the number of elements in a vector
1890/// or the vector width is implicit or explicitly unknown (but still a
1891/// valid suffix kind), 0 is used.
1892static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1893 RegKind VectorKind) {
1894 std::pair<int, int> Res = {-1, -1};
1895
1896 switch (VectorKind) {
1897 case RegKind::NeonVector:
1898 Res =
1899 StringSwitch<std::pair<int, int>>(Suffix.lower())
1900 .Case("", {0, 0})
1901 .Case(".1d", {1, 64})
1902 .Case(".1q", {1, 128})
1903 // '.2h' needed for fp16 scalar pairwise reductions
1904 .Case(".2h", {2, 16})
1905 .Case(".2s", {2, 32})
1906 .Case(".2d", {2, 64})
1907 // '.4b' is another special case for the ARMv8.2a dot product
1908 // operand
1909 .Case(".4b", {4, 8})
1910 .Case(".4h", {4, 16})
1911 .Case(".4s", {4, 32})
1912 .Case(".8b", {8, 8})
1913 .Case(".8h", {8, 16})
1914 .Case(".16b", {16, 8})
1915 // Accept the width neutral ones, too, for verbose syntax. If those
1916 // aren't used in the right places, the token operand won't match so
1917 // all will work out.
1918 .Case(".b", {0, 8})
1919 .Case(".h", {0, 16})
1920 .Case(".s", {0, 32})
1921 .Case(".d", {0, 64})
1922 .Default({-1, -1});
1923 break;
1924 case RegKind::SVEPredicateVector:
1925 case RegKind::SVEDataVector:
1926 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1927 .Case("", {0, 0})
1928 .Case(".b", {0, 8})
1929 .Case(".h", {0, 16})
1930 .Case(".s", {0, 32})
1931 .Case(".d", {0, 64})
1932 .Case(".q", {0, 128})
1933 .Default({-1, -1});
1934 break;
1935 default:
1936 llvm_unreachable("Unsupported RegKind");
1937 }
1938
1939 if (Res == std::make_pair(-1, -1))
1940 return Optional<std::pair<int, int>>();
1941
1942 return Optional<std::pair<int, int>>(Res);
1943}
1944
1945static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1946 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001947}
1948
Florian Hahn91f11e52017-11-07 16:45:48 +00001949static unsigned matchSVEDataVectorRegName(StringRef Name) {
1950 return StringSwitch<unsigned>(Name.lower())
1951 .Case("z0", AArch64::Z0)
1952 .Case("z1", AArch64::Z1)
1953 .Case("z2", AArch64::Z2)
1954 .Case("z3", AArch64::Z3)
1955 .Case("z4", AArch64::Z4)
1956 .Case("z5", AArch64::Z5)
1957 .Case("z6", AArch64::Z6)
1958 .Case("z7", AArch64::Z7)
1959 .Case("z8", AArch64::Z8)
1960 .Case("z9", AArch64::Z9)
1961 .Case("z10", AArch64::Z10)
1962 .Case("z11", AArch64::Z11)
1963 .Case("z12", AArch64::Z12)
1964 .Case("z13", AArch64::Z13)
1965 .Case("z14", AArch64::Z14)
1966 .Case("z15", AArch64::Z15)
1967 .Case("z16", AArch64::Z16)
1968 .Case("z17", AArch64::Z17)
1969 .Case("z18", AArch64::Z18)
1970 .Case("z19", AArch64::Z19)
1971 .Case("z20", AArch64::Z20)
1972 .Case("z21", AArch64::Z21)
1973 .Case("z22", AArch64::Z22)
1974 .Case("z23", AArch64::Z23)
1975 .Case("z24", AArch64::Z24)
1976 .Case("z25", AArch64::Z25)
1977 .Case("z26", AArch64::Z26)
1978 .Case("z27", AArch64::Z27)
1979 .Case("z28", AArch64::Z28)
1980 .Case("z29", AArch64::Z29)
1981 .Case("z30", AArch64::Z30)
1982 .Case("z31", AArch64::Z31)
1983 .Default(0);
1984}
1985
Sander de Smalencd6be962017-12-20 11:02:42 +00001986static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1987 return StringSwitch<unsigned>(Name.lower())
1988 .Case("p0", AArch64::P0)
1989 .Case("p1", AArch64::P1)
1990 .Case("p2", AArch64::P2)
1991 .Case("p3", AArch64::P3)
1992 .Case("p4", AArch64::P4)
1993 .Case("p5", AArch64::P5)
1994 .Case("p6", AArch64::P6)
1995 .Case("p7", AArch64::P7)
1996 .Case("p8", AArch64::P8)
1997 .Case("p9", AArch64::P9)
1998 .Case("p10", AArch64::P10)
1999 .Case("p11", AArch64::P11)
2000 .Case("p12", AArch64::P12)
2001 .Case("p13", AArch64::P13)
2002 .Case("p14", AArch64::P14)
2003 .Case("p15", AArch64::P15)
2004 .Default(0);
2005}
2006
Tim Northover3b0846e2014-05-24 12:50:23 +00002007bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2008 SMLoc &EndLoc) {
2009 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002010 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002011 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002012 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002013}
2014
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002015// Matches a register name or register alias previously defined by '.req'
2016unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002017 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002018 unsigned RegNum = 0;
2019 if ((RegNum = matchSVEDataVectorRegName(Name)))
2020 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2021
Sander de Smalencd6be962017-12-20 11:02:42 +00002022 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2023 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2024
Sander de Smalenc067c302017-12-20 09:45:45 +00002025 if ((RegNum = MatchNeonVectorRegName(Name)))
2026 return Kind == RegKind::NeonVector ? RegNum : 0;
2027
2028 // The parsed register must be of RegKind Scalar
2029 if ((RegNum = MatchRegisterName(Name)))
2030 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002031
Florian Hahnc4422242017-11-07 13:07:50 +00002032 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002033 // Handle a few common aliases of registers.
2034 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2035 .Case("fp", AArch64::FP)
2036 .Case("lr", AArch64::LR)
2037 .Case("x31", AArch64::XZR)
2038 .Case("w31", AArch64::WZR)
2039 .Default(0))
2040 return Kind == RegKind::Scalar ? RegNum : 0;
2041
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002042 // Check for aliases registered via .req. Canonicalize to lower case.
2043 // That's more consistent since register names are case insensitive, and
2044 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2045 auto Entry = RegisterReqs.find(Name.lower());
2046 if (Entry == RegisterReqs.end())
2047 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002048
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002049 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002050 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002051 RegNum = Entry->getValue().second;
2052 }
2053 return RegNum;
2054}
2055
Sander de Smalen50d87022018-04-19 07:35:08 +00002056/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002057/// Identifier when called, and if it is a register name the token is eaten and
2058/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002059OperandMatchResultTy
2060AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002061 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002062 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002063 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002064 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002065
2066 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002067 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2068 if (Reg == 0)
2069 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002070
Sander de Smalen50d87022018-04-19 07:35:08 +00002071 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002072 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002073 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002074}
2075
Tim Northover3b0846e2014-05-24 12:50:23 +00002076/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002077OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002078AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002079 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002080 SMLoc S = getLoc();
2081
2082 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2083 Error(S, "Expected cN operand where 0 <= N <= 15");
2084 return MatchOperand_ParseFail;
2085 }
2086
2087 StringRef Tok = Parser.getTok().getIdentifier();
2088 if (Tok[0] != 'c' && Tok[0] != 'C') {
2089 Error(S, "Expected cN operand where 0 <= N <= 15");
2090 return MatchOperand_ParseFail;
2091 }
2092
2093 uint32_t CRNum;
2094 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2095 if (BadNum || CRNum > 15) {
2096 Error(S, "Expected cN operand where 0 <= N <= 15");
2097 return MatchOperand_ParseFail;
2098 }
2099
2100 Parser.Lex(); // Eat identifier token.
2101 Operands.push_back(
2102 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2103 return MatchOperand_Success;
2104}
2105
2106/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002107template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002108OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002109AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002110 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002111 SMLoc S = getLoc();
2112 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002113
2114 auto LookupByName = [](StringRef N) {
2115 if (IsSVEPrefetch) {
2116 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2117 return Optional<unsigned>(Res->Encoding);
2118 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2119 return Optional<unsigned>(Res->Encoding);
2120 return Optional<unsigned>();
2121 };
2122
2123 auto LookupByEncoding = [](unsigned E) {
2124 if (IsSVEPrefetch) {
2125 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2126 return Optional<StringRef>(Res->Name);
2127 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2128 return Optional<StringRef>(Res->Name);
2129 return Optional<StringRef>();
2130 };
2131 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2132
Tim Northover3b0846e2014-05-24 12:50:23 +00002133 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002134 // Eat optional hash.
2135 if (parseOptionalToken(AsmToken::Hash) ||
2136 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002137 const MCExpr *ImmVal;
2138 if (getParser().parseExpression(ImmVal))
2139 return MatchOperand_ParseFail;
2140
2141 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2142 if (!MCE) {
2143 TokError("immediate value expected for prefetch operand");
2144 return MatchOperand_ParseFail;
2145 }
2146 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002147 if (prfop > MaxVal) {
2148 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2149 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002150 return MatchOperand_ParseFail;
2151 }
2152
Sander de Smalen93380372018-05-14 11:54:41 +00002153 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002154 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002155 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002156 return MatchOperand_Success;
2157 }
2158
2159 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002160 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002161 return MatchOperand_ParseFail;
2162 }
2163
Sander de Smalen93380372018-05-14 11:54:41 +00002164 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002165 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002166 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002167 return MatchOperand_ParseFail;
2168 }
2169
2170 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002171 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002172 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002173 return MatchOperand_Success;
2174}
2175
Oliver Stannarda34e4702015-12-01 10:48:51 +00002176/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002177OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002178AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2179 MCAsmParser &Parser = getParser();
2180 SMLoc S = getLoc();
2181 const AsmToken &Tok = Parser.getTok();
2182 if (Tok.isNot(AsmToken::Identifier)) {
2183 TokError("invalid operand for instruction");
2184 return MatchOperand_ParseFail;
2185 }
2186
Tim Northovere6ae6762016-07-05 21:23:04 +00002187 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2188 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002189 TokError("invalid operand for instruction");
2190 return MatchOperand_ParseFail;
2191 }
2192
2193 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002194 Operands.push_back(AArch64Operand::CreatePSBHint(
2195 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002196 return MatchOperand_Success;
2197}
2198
Tim Northover3b0846e2014-05-24 12:50:23 +00002199/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2200/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002201OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002202AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002203 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002204 SMLoc S = getLoc();
2205 const MCExpr *Expr;
2206
2207 if (Parser.getTok().is(AsmToken::Hash)) {
2208 Parser.Lex(); // Eat hash token.
2209 }
2210
2211 if (parseSymbolicImmVal(Expr))
2212 return MatchOperand_ParseFail;
2213
2214 AArch64MCExpr::VariantKind ELFRefKind;
2215 MCSymbolRefExpr::VariantKind DarwinRefKind;
2216 int64_t Addend;
2217 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2218 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2219 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2220 // No modifier was specified at all; this is the syntax for an ELF basic
2221 // ADRP relocation (unfortunately).
2222 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002223 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002224 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2225 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2226 Addend != 0) {
2227 Error(S, "gotpage label reference not allowed an addend");
2228 return MatchOperand_ParseFail;
2229 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2230 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2231 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2232 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2233 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2234 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2235 // The operand must be an @page or @gotpage qualified symbolref.
2236 Error(S, "page or gotpage label reference expected");
2237 return MatchOperand_ParseFail;
2238 }
2239 }
2240
2241 // We have either a label reference possibly with addend or an immediate. The
2242 // addend is a raw value here. The linker will adjust it to only reference the
2243 // page.
2244 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2245 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2246
2247 return MatchOperand_Success;
2248}
2249
2250/// tryParseAdrLabel - Parse and validate a source label for the ADR
2251/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002252OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002253AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2254 SMLoc S = getLoc();
2255 const MCExpr *Expr;
2256
Nirav Davee833c6c2016-11-08 18:31:04 +00002257 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002258 if (getParser().parseExpression(Expr))
2259 return MatchOperand_ParseFail;
2260
2261 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2262 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2263
2264 return MatchOperand_Success;
2265}
2266
2267/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002268OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002269AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002270 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002271 SMLoc S = getLoc();
2272
Nirav Davee833c6c2016-11-08 18:31:04 +00002273 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002274
2275 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002276 bool isNegative = parseOptionalToken(AsmToken::Minus);
2277
Tim Northover3b0846e2014-05-24 12:50:23 +00002278 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002279 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002280 int64_t Val;
Sander de Smalenbdf09fe2018-05-30 09:54:19 +00002281 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002282 Val = Tok.getIntVal();
Sander de Smalenbdf09fe2018-05-30 09:54:19 +00002283 if (Val > 255 || isNegative) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002284 TokError("encoded floating point value out of range");
2285 return MatchOperand_ParseFail;
2286 }
2287 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002288 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002289 if (isNegative)
2290 RealVal.changeSign();
2291
Tim Northover3b0846e2014-05-24 12:50:23 +00002292 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002293 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002294
John Brawn5ca5daa2017-04-20 10:13:54 +00002295 // Check for out of range values. As an exception we let Zero through,
2296 // but as tokens instead of an FPImm so that it can be matched by the
2297 // appropriate alias if one exists.
2298 if (RealVal.isPosZero()) {
2299 Parser.Lex(); // Eat the token.
2300 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2301 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2302 return MatchOperand_Success;
2303 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002304 TokError("expected compatible register or floating-point constant");
2305 return MatchOperand_ParseFail;
2306 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002307 }
2308 Parser.Lex(); // Eat the token.
2309 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2310 return MatchOperand_Success;
2311 }
2312
2313 if (!Hash)
2314 return MatchOperand_NoMatch;
2315
2316 TokError("invalid floating point immediate");
2317 return MatchOperand_ParseFail;
2318}
2319
Sander de Smalen62770792018-05-25 09:47:52 +00002320/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2321/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002322OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002323AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002324 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002325 SMLoc S = getLoc();
2326
2327 if (Parser.getTok().is(AsmToken::Hash))
2328 Parser.Lex(); // Eat '#'
2329 else if (Parser.getTok().isNot(AsmToken::Integer))
2330 // Operand should start from # or should be integer, emit error otherwise.
2331 return MatchOperand_NoMatch;
2332
2333 const MCExpr *Imm;
2334 if (parseSymbolicImmVal(Imm))
2335 return MatchOperand_ParseFail;
2336 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002337 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002338 Operands.push_back(
2339 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002340 return MatchOperand_Success;
2341 }
2342
2343 // Eat ','
2344 Parser.Lex();
2345
2346 // The optional operand must be "lsl #N" where N is non-negative.
2347 if (!Parser.getTok().is(AsmToken::Identifier) ||
2348 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2349 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2350 return MatchOperand_ParseFail;
2351 }
2352
2353 // Eat 'lsl'
2354 Parser.Lex();
2355
Nirav Davee833c6c2016-11-08 18:31:04 +00002356 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002357
2358 if (Parser.getTok().isNot(AsmToken::Integer)) {
2359 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2360 return MatchOperand_ParseFail;
2361 }
2362
2363 int64_t ShiftAmount = Parser.getTok().getIntVal();
2364
2365 if (ShiftAmount < 0) {
2366 Error(Parser.getTok().getLoc(), "positive shift amount required");
2367 return MatchOperand_ParseFail;
2368 }
2369 Parser.Lex(); // Eat the number
2370
Sander de Smalen62770792018-05-25 09:47:52 +00002371 // Just in case the optional lsl #0 is used for immediates other than zero.
2372 if (ShiftAmount == 0 && Imm != 0) {
2373 SMLoc E = Parser.getTok().getLoc();
2374 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2375 return MatchOperand_Success;
2376 }
2377
Tim Northover3b0846e2014-05-24 12:50:23 +00002378 SMLoc E = Parser.getTok().getLoc();
2379 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2380 S, E, getContext()));
2381 return MatchOperand_Success;
2382}
2383
2384/// parseCondCodeString - Parse a Condition Code string.
2385AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2386 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2387 .Case("eq", AArch64CC::EQ)
2388 .Case("ne", AArch64CC::NE)
2389 .Case("cs", AArch64CC::HS)
2390 .Case("hs", AArch64CC::HS)
2391 .Case("cc", AArch64CC::LO)
2392 .Case("lo", AArch64CC::LO)
2393 .Case("mi", AArch64CC::MI)
2394 .Case("pl", AArch64CC::PL)
2395 .Case("vs", AArch64CC::VS)
2396 .Case("vc", AArch64CC::VC)
2397 .Case("hi", AArch64CC::HI)
2398 .Case("ls", AArch64CC::LS)
2399 .Case("ge", AArch64CC::GE)
2400 .Case("lt", AArch64CC::LT)
2401 .Case("gt", AArch64CC::GT)
2402 .Case("le", AArch64CC::LE)
2403 .Case("al", AArch64CC::AL)
2404 .Case("nv", AArch64CC::NV)
2405 .Default(AArch64CC::Invalid);
2406 return CC;
2407}
2408
2409/// parseCondCode - Parse a Condition Code operand.
2410bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2411 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002412 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002413 SMLoc S = getLoc();
2414 const AsmToken &Tok = Parser.getTok();
2415 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2416
2417 StringRef Cond = Tok.getString();
2418 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2419 if (CC == AArch64CC::Invalid)
2420 return TokError("invalid condition code");
2421 Parser.Lex(); // Eat identifier token.
2422
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002423 if (invertCondCode) {
2424 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2425 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002426 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002427 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002428
2429 Operands.push_back(
2430 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2431 return false;
2432}
2433
2434/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2435/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002436OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002437AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002438 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002439 const AsmToken &Tok = Parser.getTok();
2440 std::string LowerID = Tok.getString().lower();
2441 AArch64_AM::ShiftExtendType ShOp =
2442 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2443 .Case("lsl", AArch64_AM::LSL)
2444 .Case("lsr", AArch64_AM::LSR)
2445 .Case("asr", AArch64_AM::ASR)
2446 .Case("ror", AArch64_AM::ROR)
2447 .Case("msl", AArch64_AM::MSL)
2448 .Case("uxtb", AArch64_AM::UXTB)
2449 .Case("uxth", AArch64_AM::UXTH)
2450 .Case("uxtw", AArch64_AM::UXTW)
2451 .Case("uxtx", AArch64_AM::UXTX)
2452 .Case("sxtb", AArch64_AM::SXTB)
2453 .Case("sxth", AArch64_AM::SXTH)
2454 .Case("sxtw", AArch64_AM::SXTW)
2455 .Case("sxtx", AArch64_AM::SXTX)
2456 .Default(AArch64_AM::InvalidShiftExtend);
2457
2458 if (ShOp == AArch64_AM::InvalidShiftExtend)
2459 return MatchOperand_NoMatch;
2460
2461 SMLoc S = Tok.getLoc();
2462 Parser.Lex();
2463
Nirav Davee833c6c2016-11-08 18:31:04 +00002464 bool Hash = parseOptionalToken(AsmToken::Hash);
2465
Tim Northover3b0846e2014-05-24 12:50:23 +00002466 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2467 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2468 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2469 ShOp == AArch64_AM::MSL) {
2470 // We expect a number here.
2471 TokError("expected #imm after shift specifier");
2472 return MatchOperand_ParseFail;
2473 }
2474
Chad Rosier2ff37b82016-12-27 16:58:09 +00002475 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002476 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2477 Operands.push_back(
2478 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2479 return MatchOperand_Success;
2480 }
2481
Chad Rosier2ff37b82016-12-27 16:58:09 +00002482 // Make sure we do actually have a number, identifier or a parenthesized
2483 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002484 SMLoc E = Parser.getTok().getLoc();
2485 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002486 !Parser.getTok().is(AsmToken::LParen) &&
2487 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002488 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002489 return MatchOperand_ParseFail;
2490 }
2491
2492 const MCExpr *ImmVal;
2493 if (getParser().parseExpression(ImmVal))
2494 return MatchOperand_ParseFail;
2495
2496 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2497 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002498 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002499 return MatchOperand_ParseFail;
2500 }
2501
Jim Grosbach57fd2622014-09-23 22:16:02 +00002502 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002503 Operands.push_back(AArch64Operand::CreateShiftExtend(
2504 ShOp, MCE->getValue(), true, S, E, getContext()));
2505 return MatchOperand_Success;
2506}
2507
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002508static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2509 if (FBS[AArch64::HasV8_1aOps])
2510 Str += "ARMv8.1a";
2511 else if (FBS[AArch64::HasV8_2aOps])
2512 Str += "ARMv8.2a";
2513 else
2514 Str += "(unknown)";
2515}
2516
2517void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2518 SMLoc S) {
2519 const uint16_t Op2 = Encoding & 7;
2520 const uint16_t Cm = (Encoding & 0x78) >> 3;
2521 const uint16_t Cn = (Encoding & 0x780) >> 7;
2522 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2523
2524 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2525
2526 Operands.push_back(
2527 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2528 Operands.push_back(
2529 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2530 Operands.push_back(
2531 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2532 Expr = MCConstantExpr::create(Op2, getContext());
2533 Operands.push_back(
2534 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2535}
2536
Tim Northover3b0846e2014-05-24 12:50:23 +00002537/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2538/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2539bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2540 OperandVector &Operands) {
2541 if (Name.find('.') != StringRef::npos)
2542 return TokError("invalid operand");
2543
2544 Mnemonic = Name;
2545 Operands.push_back(
2546 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2547
Rafael Espindola961d4692014-11-11 05:18:41 +00002548 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002549 const AsmToken &Tok = Parser.getTok();
2550 StringRef Op = Tok.getString();
2551 SMLoc S = Tok.getLoc();
2552
Tim Northover3b0846e2014-05-24 12:50:23 +00002553 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002554 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2555 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002556 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002557 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2558 std::string Str("IC " + std::string(IC->Name) + " requires ");
2559 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2560 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002561 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002562 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002563 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002564 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2565 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002566 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002567 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2568 std::string Str("DC " + std::string(DC->Name) + " requires ");
2569 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2570 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002571 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002572 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002573 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002574 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2575 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002576 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002577 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2578 std::string Str("AT " + std::string(AT->Name) + " requires ");
2579 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2580 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002581 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002582 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002583 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002584 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2585 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002586 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002587 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2588 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2589 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2590 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002591 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002592 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002593 }
2594
Tim Northover3b0846e2014-05-24 12:50:23 +00002595 Parser.Lex(); // Eat operand.
2596
2597 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2598 bool HasRegister = false;
2599
2600 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002601 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002602 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2603 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002604 HasRegister = true;
2605 }
2606
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002607 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002608 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002609 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002610 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002611
Nirav Davee833c6c2016-11-08 18:31:04 +00002612 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2613 return true;
2614
Tim Northover3b0846e2014-05-24 12:50:23 +00002615 return false;
2616}
2617
Alex Bradbury58eba092016-11-01 16:32:05 +00002618OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002619AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002620 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002621 const AsmToken &Tok = Parser.getTok();
2622
2623 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002624 if (parseOptionalToken(AsmToken::Hash) ||
2625 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002626 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002627 const MCExpr *ImmVal;
2628 SMLoc ExprLoc = getLoc();
2629 if (getParser().parseExpression(ImmVal))
2630 return MatchOperand_ParseFail;
2631 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2632 if (!MCE) {
2633 Error(ExprLoc, "immediate value expected for barrier operand");
2634 return MatchOperand_ParseFail;
2635 }
2636 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2637 Error(ExprLoc, "barrier operand out of range");
2638 return MatchOperand_ParseFail;
2639 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002640 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2641 Operands.push_back(AArch64Operand::CreateBarrier(
2642 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002643 return MatchOperand_Success;
2644 }
2645
2646 if (Tok.isNot(AsmToken::Identifier)) {
2647 TokError("invalid operand for instruction");
2648 return MatchOperand_ParseFail;
2649 }
2650
Tim Northover3b0846e2014-05-24 12:50:23 +00002651 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002652 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2653 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002654 TokError("'sy' or #imm operand expected");
2655 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002656 } else if (!DB) {
2657 TokError("invalid barrier option name");
2658 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002659 }
2660
Tim Northovere6ae6762016-07-05 21:23:04 +00002661 Operands.push_back(AArch64Operand::CreateBarrier(
2662 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002663 Parser.Lex(); // Consume the option
2664
2665 return MatchOperand_Success;
2666}
2667
Alex Bradbury58eba092016-11-01 16:32:05 +00002668OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002669AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002670 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002671 const AsmToken &Tok = Parser.getTok();
2672
2673 if (Tok.isNot(AsmToken::Identifier))
2674 return MatchOperand_NoMatch;
2675
Tim Northovere6ae6762016-07-05 21:23:04 +00002676 int MRSReg, MSRReg;
2677 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2678 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2679 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2680 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2681 } else
2682 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002683
Tim Northovere6ae6762016-07-05 21:23:04 +00002684 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2685 unsigned PStateImm = -1;
2686 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2687 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002688
Tim Northovere6ae6762016-07-05 21:23:04 +00002689 Operands.push_back(
2690 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2691 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002692 Parser.Lex(); // Eat identifier
2693
2694 return MatchOperand_Success;
2695}
2696
Florian Hahnc4422242017-11-07 13:07:50 +00002697/// tryParseNeonVectorRegister - Parse a vector register operand.
2698bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002699 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002700 if (Parser.getTok().isNot(AsmToken::Identifier))
2701 return true;
2702
2703 SMLoc S = getLoc();
2704 // Check for a vector register specifier first.
2705 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002706 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002707 OperandMatchResultTy Res =
2708 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2709 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002710 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002711
2712 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2713 if (!KindRes)
2714 return true;
2715
2716 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002717 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002718 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2719 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002720
Tim Northover3b0846e2014-05-24 12:50:23 +00002721 // If there was an explicit qualifier, that goes on as a literal text
2722 // operand.
2723 if (!Kind.empty())
2724 Operands.push_back(
2725 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2726
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002727 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2728}
2729
2730OperandMatchResultTy
2731AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002732 SMLoc SIdx = getLoc();
2733 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002734 const MCExpr *ImmVal;
2735 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002736 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002737 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2738 if (!MCE) {
2739 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002740 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002741 }
2742
2743 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002744
Nirav Davee833c6c2016-11-08 18:31:04 +00002745 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002746 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002747
2748 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2749 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002750 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002751 }
2752
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002753 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002754}
2755
Sander de Smalen73937b72018-04-11 07:36:10 +00002756// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002757// optional kind specifier. If it is a register specifier, eat the token
2758// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002759OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002760AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002761 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002762 MCAsmParser &Parser = getParser();
2763 const AsmToken &Tok = Parser.getTok();
2764
Florian Hahn91f11e52017-11-07 16:45:48 +00002765 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002766 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002767
2768 StringRef Name = Tok.getString();
2769 // If there is a kind specifier, it's separated from the register name by
2770 // a '.'.
2771 size_t Start = 0, Next = Name.find('.');
2772 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002773 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002774
2775 if (RegNum) {
2776 if (Next != StringRef::npos) {
2777 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002778 if (!isValidVectorKind(Kind, MatchKind)) {
2779 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002780 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002781 }
2782 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002783 Parser.Lex(); // Eat the register token.
2784
2785 Reg = RegNum;
2786 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002787 }
2788
Sander de Smalen8e607342017-11-15 15:44:43 +00002789 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002790}
2791
Sander de Smalencd6be962017-12-20 11:02:42 +00002792/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2793OperandMatchResultTy
2794AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2795 // Check for a SVE predicate register specifier first.
2796 const SMLoc S = getLoc();
2797 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002798 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002799 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002800 if (Res != MatchOperand_Success)
2801 return Res;
2802
Sander de Smalen73937b72018-04-11 07:36:10 +00002803 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2804 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002805 return MatchOperand_NoMatch;
2806
Sander de Smalen73937b72018-04-11 07:36:10 +00002807 unsigned ElementWidth = KindRes->second;
2808 Operands.push_back(AArch64Operand::CreateVectorReg(
2809 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2810 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002811
Sander de Smalen7868e742018-01-09 11:17:06 +00002812 // Not all predicates are followed by a '/m' or '/z'.
2813 MCAsmParser &Parser = getParser();
2814 if (Parser.getTok().isNot(AsmToken::Slash))
2815 return MatchOperand_Success;
2816
2817 // But when they do they shouldn't have an element type suffix.
2818 if (!Kind.empty()) {
2819 Error(S, "not expecting size suffix");
2820 return MatchOperand_ParseFail;
2821 }
2822
2823 // Add a literal slash as operand
2824 Operands.push_back(
2825 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2826
2827 Parser.Lex(); // Eat the slash.
2828
2829 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002830 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002831 if (Pred != "z" && Pred != "m") {
2832 Error(getLoc(), "expecting 'm' or 'z' predication");
2833 return MatchOperand_ParseFail;
2834 }
2835
2836 // Add zero/merge token.
2837 const char *ZM = Pred == "z" ? "z" : "m";
2838 Operands.push_back(
2839 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2840
2841 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002842 return MatchOperand_Success;
2843}
2844
Sander de Smalen50d87022018-04-19 07:35:08 +00002845/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002846bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002847 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002848 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002849 return false;
2850
Sander de Smalen149916d2018-04-20 07:24:20 +00002851 // Otherwise try for a scalar register.
2852 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
2853 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002854
Sander de Smalen149916d2018-04-20 07:24:20 +00002855 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002856}
2857
2858bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002859 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002860 bool HasELFModifier = false;
2861 AArch64MCExpr::VariantKind RefKind;
2862
Nirav Davee833c6c2016-11-08 18:31:04 +00002863 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002864 HasELFModifier = true;
2865
Nirav Davee833c6c2016-11-08 18:31:04 +00002866 if (Parser.getTok().isNot(AsmToken::Identifier))
2867 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002868
2869 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2870 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2871 .Case("lo12", AArch64MCExpr::VK_LO12)
2872 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2873 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2874 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2875 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2876 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2877 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2878 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2879 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2880 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2881 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2882 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2883 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2884 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2885 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2886 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2887 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2888 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2889 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2890 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2891 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2892 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2893 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2894 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2895 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2896 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2897 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2898 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2899 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2900 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2901 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2902 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2903 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2904 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2905 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002906 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2907 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002908 .Default(AArch64MCExpr::VK_INVALID);
2909
Nirav Davee833c6c2016-11-08 18:31:04 +00002910 if (RefKind == AArch64MCExpr::VK_INVALID)
2911 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002912
2913 Parser.Lex(); // Eat identifier
2914
Nirav Davee833c6c2016-11-08 18:31:04 +00002915 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002916 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002917 }
2918
2919 if (getParser().parseExpression(ImmVal))
2920 return true;
2921
2922 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002923 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002924
2925 return false;
2926}
2927
Sander de Smalen650234b2018-04-12 11:40:52 +00002928template <RegKind VectorKind>
2929OperandMatchResultTy
2930AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
2931 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002932 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00002933 if (!Parser.getTok().is(AsmToken::LCurly))
2934 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002935
2936 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00002937 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00002938 bool NoMatchIsError) {
2939 auto RegTok = Parser.getTok();
2940 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
2941 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002942 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00002943 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002944 llvm_unreachable("Expected a valid vector kind");
2945 }
2946
Sander de Smalen650234b2018-04-12 11:40:52 +00002947 if (RegTok.isNot(AsmToken::Identifier) ||
2948 ParseRes == MatchOperand_ParseFail ||
2949 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
2950 Error(Loc, "vector register expected");
2951 return MatchOperand_ParseFail;
2952 }
2953
2954 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002955 };
2956
Tim Northover3b0846e2014-05-24 12:50:23 +00002957 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00002958 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00002959 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00002960
Tim Northover3b0846e2014-05-24 12:50:23 +00002961 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002962 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002963 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
2964
2965 // Put back the original left bracket if there was no match, so that
2966 // different types of list-operands can be matched (e.g. SVE, Neon).
2967 if (ParseRes == MatchOperand_NoMatch)
2968 Parser.getLexer().UnLex(LCurly);
2969
2970 if (ParseRes != MatchOperand_Success)
2971 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002972
Tim Northover3b0846e2014-05-24 12:50:23 +00002973 int64_t PrevReg = FirstReg;
2974 unsigned Count = 1;
2975
Nirav Davee833c6c2016-11-08 18:31:04 +00002976 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002977 SMLoc Loc = getLoc();
2978 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002979
Sander de Smalen50d87022018-04-19 07:35:08 +00002980 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002981 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2982 if (ParseRes != MatchOperand_Success)
2983 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002984
Tim Northover3b0846e2014-05-24 12:50:23 +00002985 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002986 if (Kind != NextKind) {
2987 Error(Loc, "mismatched register size suffix");
2988 return MatchOperand_ParseFail;
2989 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002990
2991 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2992
2993 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002994 Error(Loc, "invalid number of vectors");
2995 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002996 }
2997
2998 Count += Space;
2999 }
3000 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003001 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003002 SMLoc Loc = getLoc();
3003 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003004 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003005 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3006 if (ParseRes != MatchOperand_Success)
3007 return ParseRes;
3008
Tim Northover3b0846e2014-05-24 12:50:23 +00003009 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003010 if (Kind != NextKind) {
3011 Error(Loc, "mismatched register size suffix");
3012 return MatchOperand_ParseFail;
3013 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003014
3015 // Registers must be incremental (with wraparound at 31)
3016 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003017 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3018 Error(Loc, "registers must be sequential");
3019 return MatchOperand_ParseFail;
3020 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003021
3022 PrevReg = Reg;
3023 ++Count;
3024 }
3025 }
3026
Nirav Davee833c6c2016-11-08 18:31:04 +00003027 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003028 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003029
Sander de Smalen650234b2018-04-12 11:40:52 +00003030 if (Count > 4) {
3031 Error(S, "invalid number of vectors");
3032 return MatchOperand_ParseFail;
3033 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003034
3035 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003036 unsigned ElementWidth = 0;
3037 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003038 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003039 std::tie(NumElements, ElementWidth) = *VK;
3040 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003041
3042 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003043 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3044 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003045
Sander de Smalen650234b2018-04-12 11:40:52 +00003046 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003047}
3048
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003049/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3050bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003051 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3052 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003053 return true;
3054
3055 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3056}
3057
Alex Bradbury58eba092016-11-01 16:32:05 +00003058OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003059AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003060 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003061
Sander de Smalen50d87022018-04-19 07:35:08 +00003062 unsigned RegNum;
3063 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3064 if (Res != MatchOperand_Success)
3065 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003066
Nirav Davee833c6c2016-11-08 18:31:04 +00003067 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003068 Operands.push_back(AArch64Operand::CreateReg(
3069 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003070 return MatchOperand_Success;
3071 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003072
Nirav Davee833c6c2016-11-08 18:31:04 +00003073 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003074
Sander de Smalen50d87022018-04-19 07:35:08 +00003075 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003076 Error(getLoc(), "index must be absent or #0");
3077 return MatchOperand_ParseFail;
3078 }
3079
3080 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003081 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003082 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3083 Error(getLoc(), "index must be absent or #0");
3084 return MatchOperand_ParseFail;
3085 }
3086
Sander de Smalen50d87022018-04-19 07:35:08 +00003087 Operands.push_back(AArch64Operand::CreateReg(
3088 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003089 return MatchOperand_Success;
3090}
3091
Sander de Smalen149916d2018-04-20 07:24:20 +00003092template <bool ParseShiftExtend>
3093OperandMatchResultTy
3094AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3095 SMLoc StartLoc = getLoc();
3096
3097 unsigned RegNum;
3098 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3099 if (Res != MatchOperand_Success)
3100 return Res;
3101
3102 // No shift/extend is the default.
3103 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3104 Operands.push_back(AArch64Operand::CreateReg(
3105 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
3106 return MatchOperand_Success;
3107 }
3108
3109 // Eat the comma
3110 getParser().Lex();
3111
3112 // Match the shift
3113 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3114 Res = tryParseOptionalShiftExtend(ExtOpnd);
3115 if (Res != MatchOperand_Success)
3116 return Res;
3117
3118 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
3119 Operands.push_back(AArch64Operand::CreateReg(RegNum, RegKind::Scalar,
3120 StartLoc, Ext->getEndLoc(), getContext(),
3121 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3122 Ext->hasShiftExtendAmount()));
3123
3124 return MatchOperand_Success;
3125}
3126
Sander de Smalen5c625982018-04-13 12:56:14 +00003127bool AArch64AsmParser::parseOptionalMulVl(OperandVector &Operands) {
3128 MCAsmParser &Parser = getParser();
3129
3130 // Some SVE instructions have a decoration after the immediate, i.e.
3131 // "mul vl". We parse them here and add tokens, which must be present in the
3132 // asm string in the tablegen instruction.
3133 if (!Parser.getTok().getString().equals_lower("mul") ||
3134 !Parser.getLexer().peekTok().getString().equals_lower("vl"))
3135 return true;
3136
3137 SMLoc S = getLoc();
3138 Operands.push_back(
3139 AArch64Operand::CreateToken("mul", false, S, getContext()));
3140 Parser.Lex(); // Eat the "mul"
3141
3142 S = getLoc();
3143 Operands.push_back(
3144 AArch64Operand::CreateToken("vl", false, S, getContext()));
3145 Parser.Lex(); // Eat the "vl"
3146
3147 return false;
3148}
3149
Tim Northover3b0846e2014-05-24 12:50:23 +00003150/// parseOperand - Parse a arm instruction operand. For now this parses the
3151/// operand regardless of the mnemonic.
3152bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3153 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003154 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003155
3156 OperandMatchResultTy ResTy =
3157 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3158
Tim Northover3b0846e2014-05-24 12:50:23 +00003159 // Check if the current operand has a custom associated parser, if so, try to
3160 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003161 if (ResTy == MatchOperand_Success)
3162 return false;
3163 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3164 // there was a match, but an error occurred, in which case, just return that
3165 // the operand parsing failed.
3166 if (ResTy == MatchOperand_ParseFail)
3167 return true;
3168
3169 // Nothing custom, so do general case parsing.
3170 SMLoc S, E;
3171 switch (getLexer().getKind()) {
3172 default: {
3173 SMLoc S = getLoc();
3174 const MCExpr *Expr;
3175 if (parseSymbolicImmVal(Expr))
3176 return Error(S, "invalid operand");
3177
3178 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3179 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3180 return false;
3181 }
3182 case AsmToken::LBrac: {
3183 SMLoc Loc = Parser.getTok().getLoc();
3184 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3185 getContext()));
3186 Parser.Lex(); // Eat '['
3187
3188 // There's no comma after a '[', so we can parse the next operand
3189 // immediately.
3190 return parseOperand(Operands, false, false);
3191 }
3192 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003193 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003194 case AsmToken::Identifier: {
3195 // If we're expecting a Condition Code operand, then just parse that.
3196 if (isCondCode)
3197 return parseCondCode(Operands, invertCondCode);
3198
3199 // If it's a register name, parse it.
3200 if (!parseRegister(Operands))
3201 return false;
3202
Sander de Smalen5c625982018-04-13 12:56:14 +00003203 // See if this is a "mul vl" decoration used by SVE instructions.
3204 if (!parseOptionalMulVl(Operands))
3205 return false;
3206
Tim Northover3b0846e2014-05-24 12:50:23 +00003207 // This could be an optional "shift" or "extend" operand.
3208 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3209 // We can only continue if no tokens were eaten.
3210 if (GotShift != MatchOperand_NoMatch)
3211 return GotShift;
3212
3213 // This was not a register so parse other operands that start with an
3214 // identifier (like labels) as expressions and create them as immediates.
3215 const MCExpr *IdVal;
3216 S = getLoc();
3217 if (getParser().parseExpression(IdVal))
3218 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003219 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3220 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3221 return false;
3222 }
3223 case AsmToken::Integer:
3224 case AsmToken::Real:
3225 case AsmToken::Hash: {
3226 // #42 -> immediate.
3227 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003228
3229 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003230
3231 // Parse a negative sign
3232 bool isNegative = false;
3233 if (Parser.getTok().is(AsmToken::Minus)) {
3234 isNegative = true;
3235 // We need to consume this token only when we have a Real, otherwise
3236 // we let parseSymbolicImmVal take care of it
3237 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3238 Parser.Lex();
3239 }
3240
3241 // The only Real that should come through here is a literal #0.0 for
3242 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3243 // so convert the value.
3244 const AsmToken &Tok = Parser.getTok();
3245 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003246 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003247 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3248 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3249 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3250 Mnemonic != "fcmlt")
3251 return TokError("unexpected floating point literal");
3252 else if (IntVal != 0 || isNegative)
3253 return TokError("expected floating-point constant #0.0");
3254 Parser.Lex(); // Eat the token.
3255
3256 Operands.push_back(
3257 AArch64Operand::CreateToken("#0", false, S, getContext()));
3258 Operands.push_back(
3259 AArch64Operand::CreateToken(".0", false, S, getContext()));
3260 return false;
3261 }
3262
3263 const MCExpr *ImmVal;
3264 if (parseSymbolicImmVal(ImmVal))
3265 return true;
3266
3267 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3268 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3269 return false;
3270 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003271 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003272 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003273 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003274 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003275 Parser.Lex(); // Eat '='
3276 const MCExpr *SubExprVal;
3277 if (getParser().parseExpression(SubExprVal))
3278 return true;
3279
David Peixottoae5ba762014-07-18 16:05:14 +00003280 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003281 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003282 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003283
3284 bool IsXReg =
3285 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3286 Operands[1]->getReg());
3287
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003288 MCContext& Ctx = getContext();
3289 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3290 // 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 +00003291 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003292 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3293 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3294 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3295 ShiftAmt += 16;
3296 Imm >>= 16;
3297 }
3298 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3299 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3300 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003301 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003302 if (ShiftAmt)
3303 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3304 ShiftAmt, true, S, E, Ctx));
3305 return false;
3306 }
David Peixottoae5ba762014-07-18 16:05:14 +00003307 APInt Simm = APInt(64, Imm << ShiftAmt);
3308 // check if the immediate is an unsigned or signed 32-bit int for W regs
3309 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3310 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003311 }
3312 // 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 +00003313 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003314 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003315 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3316 return false;
3317 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003318 }
3319}
3320
3321/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3322/// operands.
3323bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3324 StringRef Name, SMLoc NameLoc,
3325 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003326 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003327 Name = StringSwitch<StringRef>(Name.lower())
3328 .Case("beq", "b.eq")
3329 .Case("bne", "b.ne")
3330 .Case("bhs", "b.hs")
3331 .Case("bcs", "b.cs")
3332 .Case("blo", "b.lo")
3333 .Case("bcc", "b.cc")
3334 .Case("bmi", "b.mi")
3335 .Case("bpl", "b.pl")
3336 .Case("bvs", "b.vs")
3337 .Case("bvc", "b.vc")
3338 .Case("bhi", "b.hi")
3339 .Case("bls", "b.ls")
3340 .Case("bge", "b.ge")
3341 .Case("blt", "b.lt")
3342 .Case("bgt", "b.gt")
3343 .Case("ble", "b.le")
3344 .Case("bal", "b.al")
3345 .Case("bnv", "b.nv")
3346 .Default(Name);
3347
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003348 // First check for the AArch64-specific .req directive.
3349 if (Parser.getTok().is(AsmToken::Identifier) &&
3350 Parser.getTok().getIdentifier() == ".req") {
3351 parseDirectiveReq(Name, NameLoc);
3352 // We always return 'error' for this, as we're done with this
3353 // statement and don't need to match the 'instruction."
3354 return true;
3355 }
3356
Tim Northover3b0846e2014-05-24 12:50:23 +00003357 // Create the leading tokens for the mnemonic, split by '.' characters.
3358 size_t Start = 0, Next = Name.find('.');
3359 StringRef Head = Name.slice(Start, Next);
3360
3361 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003362 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3363 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003364
3365 Operands.push_back(
3366 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3367 Mnemonic = Head;
3368
3369 // Handle condition codes for a branch mnemonic
3370 if (Head == "b" && Next != StringRef::npos) {
3371 Start = Next;
3372 Next = Name.find('.', Start + 1);
3373 Head = Name.slice(Start + 1, Next);
3374
3375 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3376 (Head.data() - Name.data()));
3377 AArch64CC::CondCode CC = parseCondCodeString(Head);
3378 if (CC == AArch64CC::Invalid)
3379 return Error(SuffixLoc, "invalid condition code");
3380 Operands.push_back(
3381 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3382 Operands.push_back(
3383 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3384 }
3385
3386 // Add the remaining tokens in the mnemonic.
3387 while (Next != StringRef::npos) {
3388 Start = Next;
3389 Next = Name.find('.', Start + 1);
3390 Head = Name.slice(Start, Next);
3391 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3392 (Head.data() - Name.data()) + 1);
3393 Operands.push_back(
3394 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3395 }
3396
3397 // Conditional compare instructions have a Condition Code operand, which needs
3398 // to be parsed and an immediate operand created.
3399 bool condCodeFourthOperand =
3400 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3401 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3402 Head == "csinc" || Head == "csinv" || Head == "csneg");
3403
3404 // These instructions are aliases to some of the conditional select
3405 // instructions. However, the condition code is inverted in the aliased
3406 // instruction.
3407 //
3408 // FIXME: Is this the correct way to handle these? Or should the parser
3409 // generate the aliased instructions directly?
3410 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3411 bool condCodeThirdOperand =
3412 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3413
3414 // Read the remaining operands.
3415 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3416 // Read the first operand.
3417 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003418 return true;
3419 }
3420
3421 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003422 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003423 // Parse and remember the operand.
3424 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3425 (N == 3 && condCodeThirdOperand) ||
3426 (N == 2 && condCodeSecondOperand),
3427 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003428 return true;
3429 }
3430
3431 // After successfully parsing some operands there are two special cases to
3432 // consider (i.e. notional operands not separated by commas). Both are due
3433 // to memory specifiers:
3434 // + An RBrac will end an address for load/store/prefetch
3435 // + An '!' will indicate a pre-indexed operation.
3436 //
3437 // It's someone else's responsibility to make sure these tokens are sane
3438 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003439
Nirav Davee833c6c2016-11-08 18:31:04 +00003440 SMLoc RLoc = Parser.getTok().getLoc();
3441 if (parseOptionalToken(AsmToken::RBrac))
3442 Operands.push_back(
3443 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3444 SMLoc ELoc = Parser.getTok().getLoc();
3445 if (parseOptionalToken(AsmToken::Exclaim))
3446 Operands.push_back(
3447 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003448
3449 ++N;
3450 }
3451 }
3452
Nirav Davee833c6c2016-11-08 18:31:04 +00003453 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3454 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003455
Tim Northover3b0846e2014-05-24 12:50:23 +00003456 return false;
3457}
3458
3459// FIXME: This entire function is a giant hack to provide us with decent
3460// operand range validation/diagnostics until TableGen/MC can be extended
3461// to support autogeneration of this kind of validation.
3462bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3463 SmallVectorImpl<SMLoc> &Loc) {
3464 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3465 // Check for indexed addressing modes w/ the base register being the
3466 // same as a destination/source register or pair load where
3467 // the Rt == Rt2. All of those are undefined behaviour.
3468 switch (Inst.getOpcode()) {
3469 case AArch64::LDPSWpre:
3470 case AArch64::LDPWpost:
3471 case AArch64::LDPWpre:
3472 case AArch64::LDPXpost:
3473 case AArch64::LDPXpre: {
3474 unsigned Rt = Inst.getOperand(1).getReg();
3475 unsigned Rt2 = Inst.getOperand(2).getReg();
3476 unsigned Rn = Inst.getOperand(3).getReg();
3477 if (RI->isSubRegisterEq(Rn, Rt))
3478 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3479 "is also a destination");
3480 if (RI->isSubRegisterEq(Rn, Rt2))
3481 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3482 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003483 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003484 }
3485 case AArch64::LDPDi:
3486 case AArch64::LDPQi:
3487 case AArch64::LDPSi:
3488 case AArch64::LDPSWi:
3489 case AArch64::LDPWi:
3490 case AArch64::LDPXi: {
3491 unsigned Rt = Inst.getOperand(0).getReg();
3492 unsigned Rt2 = Inst.getOperand(1).getReg();
3493 if (Rt == Rt2)
3494 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3495 break;
3496 }
3497 case AArch64::LDPDpost:
3498 case AArch64::LDPDpre:
3499 case AArch64::LDPQpost:
3500 case AArch64::LDPQpre:
3501 case AArch64::LDPSpost:
3502 case AArch64::LDPSpre:
3503 case AArch64::LDPSWpost: {
3504 unsigned Rt = Inst.getOperand(1).getReg();
3505 unsigned Rt2 = Inst.getOperand(2).getReg();
3506 if (Rt == Rt2)
3507 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3508 break;
3509 }
3510 case AArch64::STPDpost:
3511 case AArch64::STPDpre:
3512 case AArch64::STPQpost:
3513 case AArch64::STPQpre:
3514 case AArch64::STPSpost:
3515 case AArch64::STPSpre:
3516 case AArch64::STPWpost:
3517 case AArch64::STPWpre:
3518 case AArch64::STPXpost:
3519 case AArch64::STPXpre: {
3520 unsigned Rt = Inst.getOperand(1).getReg();
3521 unsigned Rt2 = Inst.getOperand(2).getReg();
3522 unsigned Rn = Inst.getOperand(3).getReg();
3523 if (RI->isSubRegisterEq(Rn, Rt))
3524 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3525 "is also a source");
3526 if (RI->isSubRegisterEq(Rn, Rt2))
3527 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3528 "is also a source");
3529 break;
3530 }
3531 case AArch64::LDRBBpre:
3532 case AArch64::LDRBpre:
3533 case AArch64::LDRHHpre:
3534 case AArch64::LDRHpre:
3535 case AArch64::LDRSBWpre:
3536 case AArch64::LDRSBXpre:
3537 case AArch64::LDRSHWpre:
3538 case AArch64::LDRSHXpre:
3539 case AArch64::LDRSWpre:
3540 case AArch64::LDRWpre:
3541 case AArch64::LDRXpre:
3542 case AArch64::LDRBBpost:
3543 case AArch64::LDRBpost:
3544 case AArch64::LDRHHpost:
3545 case AArch64::LDRHpost:
3546 case AArch64::LDRSBWpost:
3547 case AArch64::LDRSBXpost:
3548 case AArch64::LDRSHWpost:
3549 case AArch64::LDRSHXpost:
3550 case AArch64::LDRSWpost:
3551 case AArch64::LDRWpost:
3552 case AArch64::LDRXpost: {
3553 unsigned Rt = Inst.getOperand(1).getReg();
3554 unsigned Rn = Inst.getOperand(2).getReg();
3555 if (RI->isSubRegisterEq(Rn, Rt))
3556 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3557 "is also a source");
3558 break;
3559 }
3560 case AArch64::STRBBpost:
3561 case AArch64::STRBpost:
3562 case AArch64::STRHHpost:
3563 case AArch64::STRHpost:
3564 case AArch64::STRWpost:
3565 case AArch64::STRXpost:
3566 case AArch64::STRBBpre:
3567 case AArch64::STRBpre:
3568 case AArch64::STRHHpre:
3569 case AArch64::STRHpre:
3570 case AArch64::STRWpre:
3571 case AArch64::STRXpre: {
3572 unsigned Rt = Inst.getOperand(1).getReg();
3573 unsigned Rn = Inst.getOperand(2).getReg();
3574 if (RI->isSubRegisterEq(Rn, Rt))
3575 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3576 "is also a source");
3577 break;
3578 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003579 case AArch64::STXRB:
3580 case AArch64::STXRH:
3581 case AArch64::STXRW:
3582 case AArch64::STXRX:
3583 case AArch64::STLXRB:
3584 case AArch64::STLXRH:
3585 case AArch64::STLXRW:
3586 case AArch64::STLXRX: {
3587 unsigned Rs = Inst.getOperand(0).getReg();
3588 unsigned Rt = Inst.getOperand(1).getReg();
3589 unsigned Rn = Inst.getOperand(2).getReg();
3590 if (RI->isSubRegisterEq(Rt, Rs) ||
3591 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3592 return Error(Loc[0],
3593 "unpredictable STXR instruction, status is also a source");
3594 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003595 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003596 case AArch64::STXPW:
3597 case AArch64::STXPX:
3598 case AArch64::STLXPW:
3599 case AArch64::STLXPX: {
3600 unsigned Rs = Inst.getOperand(0).getReg();
3601 unsigned Rt1 = Inst.getOperand(1).getReg();
3602 unsigned Rt2 = Inst.getOperand(2).getReg();
3603 unsigned Rn = Inst.getOperand(3).getReg();
3604 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3605 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3606 return Error(Loc[0],
3607 "unpredictable STXP instruction, status is also a source");
3608 break;
3609 }
3610 }
3611
Tim Northover3b0846e2014-05-24 12:50:23 +00003612
3613 // Now check immediate ranges. Separate from the above as there is overlap
3614 // in the instructions being checked and this keeps the nested conditionals
3615 // to a minimum.
3616 switch (Inst.getOpcode()) {
3617 case AArch64::ADDSWri:
3618 case AArch64::ADDSXri:
3619 case AArch64::ADDWri:
3620 case AArch64::ADDXri:
3621 case AArch64::SUBSWri:
3622 case AArch64::SUBSXri:
3623 case AArch64::SUBWri:
3624 case AArch64::SUBXri: {
3625 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3626 // some slight duplication here.
3627 if (Inst.getOperand(2).isExpr()) {
3628 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3629 AArch64MCExpr::VariantKind ELFRefKind;
3630 MCSymbolRefExpr::VariantKind DarwinRefKind;
3631 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003632 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3633
3634 // Only allow these with ADDXri.
3635 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3636 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3637 Inst.getOpcode() == AArch64::ADDXri)
3638 return false;
3639
3640 // Only allow these with ADDXri/ADDWri
3641 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3642 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3643 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3644 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3645 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3646 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3647 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003648 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3649 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3650 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003651 (Inst.getOpcode() == AArch64::ADDXri ||
3652 Inst.getOpcode() == AArch64::ADDWri))
3653 return false;
3654
3655 // Don't allow symbol refs in the immediate field otherwise
3656 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3657 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3658 // 'cmp w0, 'borked')
3659 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003660 }
Diana Picusc93518d2016-10-11 09:17:47 +00003661 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003662 }
3663 return false;
3664 }
3665 default:
3666 return false;
3667 }
3668}
3669
Craig Topper05515562017-10-26 06:46:41 +00003670static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3671 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003672
3673bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3674 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003675 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003676 case Match_InvalidTiedOperand:
3677 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003678 case Match_MissingFeature:
3679 return Error(Loc,
3680 "instruction requires a CPU feature not currently enabled");
3681 case Match_InvalidOperand:
3682 return Error(Loc, "invalid operand for instruction");
3683 case Match_InvalidSuffix:
3684 return Error(Loc, "invalid type suffix for instruction");
3685 case Match_InvalidCondCode:
3686 return Error(Loc, "expected AArch64 condition code");
3687 case Match_AddSubRegExtendSmall:
3688 return Error(Loc,
3689 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3690 case Match_AddSubRegExtendLarge:
3691 return Error(Loc,
3692 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3693 case Match_AddSubSecondSource:
3694 return Error(Loc,
3695 "expected compatible register, symbol or integer in range [0, 4095]");
3696 case Match_LogicalSecondSource:
3697 return Error(Loc, "expected compatible register or logical immediate");
3698 case Match_InvalidMovImm32Shift:
3699 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3700 case Match_InvalidMovImm64Shift:
3701 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3702 case Match_AddSubRegShift32:
3703 return Error(Loc,
3704 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3705 case Match_AddSubRegShift64:
3706 return Error(Loc,
3707 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3708 case Match_InvalidFPImm:
3709 return Error(Loc,
3710 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003711 case Match_InvalidMemoryIndexedSImm6:
3712 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003713 case Match_InvalidMemoryIndexedSImm5:
3714 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003715 case Match_InvalidMemoryIndexed1SImm4:
3716 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003717 case Match_InvalidMemoryIndexed2SImm4:
3718 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003719 case Match_InvalidMemoryIndexed3SImm4:
3720 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003721 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00003722 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00003723 case Match_InvalidMemoryIndexed16SImm4:
3724 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00003725 case Match_InvalidMemoryIndexed1SImm6:
3726 return Error(Loc, "index must be an integer in range [-32, 31].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003727 case Match_InvalidMemoryIndexedSImm9:
3728 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00003729 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00003730 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003731 case Match_InvalidMemoryIndexed4SImm7:
3732 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3733 case Match_InvalidMemoryIndexed8SImm7:
3734 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3735 case Match_InvalidMemoryIndexed16SImm7:
3736 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00003737 case Match_InvalidMemoryIndexed8UImm5:
3738 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
3739 case Match_InvalidMemoryIndexed4UImm5:
3740 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
3741 case Match_InvalidMemoryIndexed2UImm5:
3742 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00003743 case Match_InvalidMemoryIndexed8UImm6:
3744 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
3745 case Match_InvalidMemoryIndexed4UImm6:
3746 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
3747 case Match_InvalidMemoryIndexed2UImm6:
3748 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
3749 case Match_InvalidMemoryIndexed1UImm6:
3750 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003751 case Match_InvalidMemoryWExtend8:
3752 return Error(Loc,
3753 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3754 case Match_InvalidMemoryWExtend16:
3755 return Error(Loc,
3756 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3757 case Match_InvalidMemoryWExtend32:
3758 return Error(Loc,
3759 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3760 case Match_InvalidMemoryWExtend64:
3761 return Error(Loc,
3762 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3763 case Match_InvalidMemoryWExtend128:
3764 return Error(Loc,
3765 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3766 case Match_InvalidMemoryXExtend8:
3767 return Error(Loc,
3768 "expected 'lsl' or 'sxtx' with optional shift of #0");
3769 case Match_InvalidMemoryXExtend16:
3770 return Error(Loc,
3771 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3772 case Match_InvalidMemoryXExtend32:
3773 return Error(Loc,
3774 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3775 case Match_InvalidMemoryXExtend64:
3776 return Error(Loc,
3777 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3778 case Match_InvalidMemoryXExtend128:
3779 return Error(Loc,
3780 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3781 case Match_InvalidMemoryIndexed1:
3782 return Error(Loc, "index must be an integer in range [0, 4095].");
3783 case Match_InvalidMemoryIndexed2:
3784 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3785 case Match_InvalidMemoryIndexed4:
3786 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3787 case Match_InvalidMemoryIndexed8:
3788 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3789 case Match_InvalidMemoryIndexed16:
3790 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003791 case Match_InvalidImm0_1:
3792 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003793 case Match_InvalidImm0_7:
3794 return Error(Loc, "immediate must be an integer in range [0, 7].");
3795 case Match_InvalidImm0_15:
3796 return Error(Loc, "immediate must be an integer in range [0, 15].");
3797 case Match_InvalidImm0_31:
3798 return Error(Loc, "immediate must be an integer in range [0, 31].");
3799 case Match_InvalidImm0_63:
3800 return Error(Loc, "immediate must be an integer in range [0, 63].");
3801 case Match_InvalidImm0_127:
3802 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003803 case Match_InvalidImm0_255:
3804 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003805 case Match_InvalidImm0_65535:
3806 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3807 case Match_InvalidImm1_8:
3808 return Error(Loc, "immediate must be an integer in range [1, 8].");
3809 case Match_InvalidImm1_16:
3810 return Error(Loc, "immediate must be an integer in range [1, 16].");
3811 case Match_InvalidImm1_32:
3812 return Error(Loc, "immediate must be an integer in range [1, 32].");
3813 case Match_InvalidImm1_64:
3814 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00003815 case Match_InvalidSVEAddSubImm8:
3816 return Error(Loc, "immediate must be an integer in range [0, 255]"
3817 " with a shift amount of 0");
3818 case Match_InvalidSVEAddSubImm16:
3819 case Match_InvalidSVEAddSubImm32:
3820 case Match_InvalidSVEAddSubImm64:
3821 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
3822 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00003823 case Match_InvalidSVECpyImm8:
3824 return Error(Loc, "immediate must be an integer in range [-128, 255]"
3825 " with a shift amount of 0");
3826 case Match_InvalidSVECpyImm16:
3827 case Match_InvalidSVECpyImm32:
3828 case Match_InvalidSVECpyImm64:
3829 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
3830 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003831 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00003832 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003833 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00003834 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003835 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00003836 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003837 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00003838 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003839 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00003840 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003841 case Match_InvalidSVEIndexRange0_63:
3842 return Error(Loc, "vector lane must be an integer in range [0, 63].");
3843 case Match_InvalidSVEIndexRange0_31:
3844 return Error(Loc, "vector lane must be an integer in range [0, 31].");
3845 case Match_InvalidSVEIndexRange0_15:
3846 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3847 case Match_InvalidSVEIndexRange0_7:
3848 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3849 case Match_InvalidSVEIndexRange0_3:
3850 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003851 case Match_InvalidLabel:
3852 return Error(Loc, "expected label or encodable integer pc offset");
3853 case Match_MRS:
3854 return Error(Loc, "expected readable system register");
3855 case Match_MSR:
3856 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003857 case Match_InvalidComplexRotationEven:
3858 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3859 case Match_InvalidComplexRotationOdd:
3860 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003861 case Match_MnemonicFail: {
3862 std::string Suggestion = AArch64MnemonicSpellCheck(
3863 ((AArch64Operand &)*Operands[0]).getToken(),
3864 ComputeAvailableFeatures(STI->getFeatureBits()));
3865 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3866 }
Sander de Smalen367694b2018-04-20 08:54:49 +00003867 case Match_InvalidGPR64shifted8:
3868 return Error(Loc, "register must be x0..x30 or xzr, without shift");
3869 case Match_InvalidGPR64shifted16:
3870 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
3871 case Match_InvalidGPR64shifted32:
3872 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
3873 case Match_InvalidGPR64shifted64:
3874 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
3875 case Match_InvalidGPR64NoXZRshifted8:
3876 return Error(Loc, "register must be x0..x30 without shift");
3877 case Match_InvalidGPR64NoXZRshifted16:
3878 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
3879 case Match_InvalidGPR64NoXZRshifted32:
3880 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
3881 case Match_InvalidGPR64NoXZRshifted64:
3882 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00003883 case Match_InvalidZPR32UXTW8:
3884 case Match_InvalidZPR32SXTW8:
3885 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
3886 case Match_InvalidZPR32UXTW16:
3887 case Match_InvalidZPR32SXTW16:
3888 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
3889 case Match_InvalidZPR32UXTW32:
3890 case Match_InvalidZPR32SXTW32:
3891 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
3892 case Match_InvalidZPR32UXTW64:
3893 case Match_InvalidZPR32SXTW64:
3894 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
3895 case Match_InvalidZPR64UXTW8:
3896 case Match_InvalidZPR64SXTW8:
3897 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
3898 case Match_InvalidZPR64UXTW16:
3899 case Match_InvalidZPR64SXTW16:
3900 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
3901 case Match_InvalidZPR64UXTW32:
3902 case Match_InvalidZPR64SXTW32:
3903 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
3904 case Match_InvalidZPR64UXTW64:
3905 case Match_InvalidZPR64SXTW64:
3906 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
3907 case Match_InvalidZPR64LSL8:
3908 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
3909 case Match_InvalidZPR64LSL16:
3910 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
3911 case Match_InvalidZPR64LSL32:
3912 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
3913 case Match_InvalidZPR64LSL64:
3914 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00003915 case Match_InvalidZPR0:
3916 return Error(Loc, "expected register without element width sufix");
3917 case Match_InvalidZPR8:
3918 case Match_InvalidZPR16:
3919 case Match_InvalidZPR32:
3920 case Match_InvalidZPR64:
3921 case Match_InvalidZPR128:
3922 return Error(Loc, "invalid element width");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003923 case Match_InvalidSVEPattern:
3924 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003925 case Match_InvalidSVEPredicateAnyReg:
3926 case Match_InvalidSVEPredicateBReg:
3927 case Match_InvalidSVEPredicateHReg:
3928 case Match_InvalidSVEPredicateSReg:
3929 case Match_InvalidSVEPredicateDReg:
3930 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003931 case Match_InvalidSVEPredicate3bAnyReg:
3932 case Match_InvalidSVEPredicate3bBReg:
3933 case Match_InvalidSVEPredicate3bHReg:
3934 case Match_InvalidSVEPredicate3bSReg:
3935 case Match_InvalidSVEPredicate3bDReg:
3936 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003937 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003938 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003939 }
3940}
3941
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003942static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003943
3944bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3945 OperandVector &Operands,
3946 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003947 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003948 bool MatchingInlineAsm) {
3949 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003950 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3951 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003952
David Blaikie960ea3f2014-06-08 16:18:35 +00003953 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003954 unsigned NumOperands = Operands.size();
3955
3956 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003957 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3958 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003959 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003960 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003961 if (Op3CE) {
3962 uint64_t Op3Val = Op3CE->getValue();
3963 uint64_t NewOp3Val = 0;
3964 uint64_t NewOp4Val = 0;
3965 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003966 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003967 NewOp3Val = (32 - Op3Val) & 0x1f;
3968 NewOp4Val = 31 - Op3Val;
3969 } else {
3970 NewOp3Val = (64 - Op3Val) & 0x3f;
3971 NewOp4Val = 63 - Op3Val;
3972 }
3973
Jim Grosbach13760bd2015-05-30 01:25:56 +00003974 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3975 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003976
3977 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003978 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003979 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003980 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3981 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3982 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003983 }
3984 }
Tim Northover03b99f62015-04-30 18:28:58 +00003985 } else if (NumOperands == 4 && Tok == "bfc") {
3986 // FIXME: Horrible hack to handle BFC->BFM alias.
3987 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3988 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3989 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3990
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003991 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003992 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3993 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3994
3995 if (LSBCE && WidthCE) {
3996 uint64_t LSB = LSBCE->getValue();
3997 uint64_t Width = WidthCE->getValue();
3998
3999 uint64_t RegWidth = 0;
4000 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4001 Op1.getReg()))
4002 RegWidth = 64;
4003 else
4004 RegWidth = 32;
4005
4006 if (LSB >= RegWidth)
4007 return Error(LSBOp.getStartLoc(),
4008 "expected integer in range [0, 31]");
4009 if (Width < 1 || Width > RegWidth)
4010 return Error(WidthOp.getStartLoc(),
4011 "expected integer in range [1, 32]");
4012
4013 uint64_t ImmR = 0;
4014 if (RegWidth == 32)
4015 ImmR = (32 - LSB) & 0x1f;
4016 else
4017 ImmR = (64 - LSB) & 0x3f;
4018
4019 uint64_t ImmS = Width - 1;
4020
4021 if (ImmR != 0 && ImmS >= ImmR)
4022 return Error(WidthOp.getStartLoc(),
4023 "requested insert overflows register");
4024
Jim Grosbach13760bd2015-05-30 01:25:56 +00004025 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4026 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004027 Operands[0] = AArch64Operand::CreateToken(
4028 "bfm", false, Op.getStartLoc(), getContext());
4029 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004030 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4031 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004032 Operands[3] = AArch64Operand::CreateImm(
4033 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4034 Operands.emplace_back(
4035 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4036 WidthOp.getEndLoc(), getContext()));
4037 }
4038 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004039 } else if (NumOperands == 5) {
4040 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4041 // UBFIZ -> UBFM aliases.
4042 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004043 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4044 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4045 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004046
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004047 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004048 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4049 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004050
4051 if (Op3CE && Op4CE) {
4052 uint64_t Op3Val = Op3CE->getValue();
4053 uint64_t Op4Val = Op4CE->getValue();
4054
4055 uint64_t RegWidth = 0;
4056 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004057 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004058 RegWidth = 64;
4059 else
4060 RegWidth = 32;
4061
4062 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004063 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004064 "expected integer in range [0, 31]");
4065 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004066 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004067 "expected integer in range [1, 32]");
4068
4069 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004070 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004071 NewOp3Val = (32 - Op3Val) & 0x1f;
4072 else
4073 NewOp3Val = (64 - Op3Val) & 0x3f;
4074
4075 uint64_t NewOp4Val = Op4Val - 1;
4076
4077 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004078 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004079 "requested insert overflows register");
4080
4081 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004082 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004083 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004084 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004085 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004086 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004087 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004088 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004089 if (Tok == "bfi")
4090 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004091 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004092 else if (Tok == "sbfiz")
4093 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004094 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004095 else if (Tok == "ubfiz")
4096 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004097 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004098 else
4099 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004100 }
4101 }
4102
4103 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4104 // UBFX -> UBFM aliases.
4105 } else if (NumOperands == 5 &&
4106 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004107 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4108 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4109 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004110
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004111 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004112 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4113 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004114
4115 if (Op3CE && Op4CE) {
4116 uint64_t Op3Val = Op3CE->getValue();
4117 uint64_t Op4Val = Op4CE->getValue();
4118
4119 uint64_t RegWidth = 0;
4120 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004121 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004122 RegWidth = 64;
4123 else
4124 RegWidth = 32;
4125
4126 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004127 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004128 "expected integer in range [0, 31]");
4129 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004130 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004131 "expected integer in range [1, 32]");
4132
4133 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4134
4135 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004136 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004137 "requested extract overflows register");
4138
4139 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004140 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004141 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004142 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004143 if (Tok == "bfxil")
4144 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004145 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004146 else if (Tok == "sbfx")
4147 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004148 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004149 else if (Tok == "ubfx")
4150 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004151 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004152 else
4153 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004154 }
4155 }
4156 }
4157 }
Tim Northover9097a072017-12-18 10:36:00 +00004158
4159 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4160 // instruction for FP registers correctly in some rare circumstances. Convert
4161 // it to a safe instruction and warn (because silently changing someone's
4162 // assembly is rude).
4163 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4164 NumOperands == 4 && Tok == "movi") {
4165 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4166 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4167 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4168 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4169 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4170 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4171 if (Suffix.lower() == ".2d" &&
4172 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4173 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4174 " correctly on this CPU, converting to equivalent movi.16b");
4175 // Switch the suffix to .16b.
4176 unsigned Idx = Op1.isToken() ? 1 : 2;
4177 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4178 getContext());
4179 }
4180 }
4181 }
4182
Tim Northover3b0846e2014-05-24 12:50:23 +00004183 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4184 // InstAlias can't quite handle this since the reg classes aren't
4185 // subclasses.
4186 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4187 // The source register can be Wn here, but the matcher expects a
4188 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004189 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004190 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004191 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004192 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4193 Op.getStartLoc(), Op.getEndLoc(),
4194 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004195 }
4196 }
4197 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4198 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004199 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004200 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004201 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004202 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004203 // The source register can be Wn here, but the matcher expects a
4204 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004205 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004206 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004207 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004208 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4209 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004210 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004211 }
4212 }
4213 }
4214 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4215 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004216 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004217 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004218 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004219 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004220 // The source register can be Wn here, but the matcher expects a
4221 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004222 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004223 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004224 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004225 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4226 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004227 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004228 }
4229 }
4230 }
4231
Tim Northover3b0846e2014-05-24 12:50:23 +00004232 MCInst Inst;
4233 // First try to match against the secondary set of tables containing the
4234 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4235 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004236 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004237
4238 // If that fails, try against the alternate table containing long-form NEON:
4239 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004240 if (MatchResult != Match_Success) {
4241 // But first, save the short-form match result: we can use it in case the
4242 // long-form match also fails.
4243 auto ShortFormNEONErrorInfo = ErrorInfo;
4244 auto ShortFormNEONMatchResult = MatchResult;
4245
Tim Northover3b0846e2014-05-24 12:50:23 +00004246 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004247 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004248
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004249 // Now, both matches failed, and the long-form match failed on the mnemonic
4250 // suffix token operand. The short-form match failure is probably more
4251 // relevant: use it instead.
4252 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004253 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004254 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4255 MatchResult = ShortFormNEONMatchResult;
4256 ErrorInfo = ShortFormNEONErrorInfo;
4257 }
4258 }
4259
Tim Northover3b0846e2014-05-24 12:50:23 +00004260 switch (MatchResult) {
4261 case Match_Success: {
4262 // Perform range checking and other semantic validations
4263 SmallVector<SMLoc, 8> OperandLocs;
4264 NumOperands = Operands.size();
4265 for (unsigned i = 1; i < NumOperands; ++i)
4266 OperandLocs.push_back(Operands[i]->getStartLoc());
4267 if (validateInstruction(Inst, OperandLocs))
4268 return true;
4269
4270 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004271 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004272 return false;
4273 }
4274 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004275 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004276 // Special case the error message for the very common case where only
4277 // a single subtarget feature is missing (neon, e.g.).
4278 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004279 uint64_t Mask = 1;
4280 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4281 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004282 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004283 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004284 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004285 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004286 }
4287 return Error(IDLoc, Msg);
4288 }
4289 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004290 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004291 case Match_InvalidOperand: {
4292 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004293
Tim Northover26bb14e2014-08-18 11:49:42 +00004294 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004295 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004296 return Error(IDLoc, "too few operands for instruction",
4297 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004298
David Blaikie960ea3f2014-06-08 16:18:35 +00004299 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004300 if (ErrorLoc == SMLoc())
4301 ErrorLoc = IDLoc;
4302 }
4303 // If the match failed on a suffix token operand, tweak the diagnostic
4304 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004305 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4306 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004307 MatchResult = Match_InvalidSuffix;
4308
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004309 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004310 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004311 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004312 case Match_InvalidMemoryIndexed1:
4313 case Match_InvalidMemoryIndexed2:
4314 case Match_InvalidMemoryIndexed4:
4315 case Match_InvalidMemoryIndexed8:
4316 case Match_InvalidMemoryIndexed16:
4317 case Match_InvalidCondCode:
4318 case Match_AddSubRegExtendSmall:
4319 case Match_AddSubRegExtendLarge:
4320 case Match_AddSubSecondSource:
4321 case Match_LogicalSecondSource:
4322 case Match_AddSubRegShift32:
4323 case Match_AddSubRegShift64:
4324 case Match_InvalidMovImm32Shift:
4325 case Match_InvalidMovImm64Shift:
4326 case Match_InvalidFPImm:
4327 case Match_InvalidMemoryWExtend8:
4328 case Match_InvalidMemoryWExtend16:
4329 case Match_InvalidMemoryWExtend32:
4330 case Match_InvalidMemoryWExtend64:
4331 case Match_InvalidMemoryWExtend128:
4332 case Match_InvalidMemoryXExtend8:
4333 case Match_InvalidMemoryXExtend16:
4334 case Match_InvalidMemoryXExtend32:
4335 case Match_InvalidMemoryXExtend64:
4336 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004337 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004338 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004339 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004340 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004341 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004342 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004343 case Match_InvalidMemoryIndexed4SImm7:
4344 case Match_InvalidMemoryIndexed8SImm7:
4345 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004346 case Match_InvalidMemoryIndexed8UImm5:
4347 case Match_InvalidMemoryIndexed4UImm5:
4348 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004349 case Match_InvalidMemoryIndexed1UImm6:
4350 case Match_InvalidMemoryIndexed2UImm6:
4351 case Match_InvalidMemoryIndexed4UImm6:
4352 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004353 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004354 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004355 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004356 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004357 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004358 case Match_InvalidImm0_7:
4359 case Match_InvalidImm0_15:
4360 case Match_InvalidImm0_31:
4361 case Match_InvalidImm0_63:
4362 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004363 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004364 case Match_InvalidImm0_65535:
4365 case Match_InvalidImm1_8:
4366 case Match_InvalidImm1_16:
4367 case Match_InvalidImm1_32:
4368 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004369 case Match_InvalidSVEAddSubImm8:
4370 case Match_InvalidSVEAddSubImm16:
4371 case Match_InvalidSVEAddSubImm32:
4372 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004373 case Match_InvalidSVECpyImm8:
4374 case Match_InvalidSVECpyImm16:
4375 case Match_InvalidSVECpyImm32:
4376 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004377 case Match_InvalidIndexRange1_1:
4378 case Match_InvalidIndexRange0_15:
4379 case Match_InvalidIndexRange0_7:
4380 case Match_InvalidIndexRange0_3:
4381 case Match_InvalidIndexRange0_1:
4382 case Match_InvalidSVEIndexRange0_63:
4383 case Match_InvalidSVEIndexRange0_31:
4384 case Match_InvalidSVEIndexRange0_15:
4385 case Match_InvalidSVEIndexRange0_7:
4386 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004387 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004388 case Match_InvalidComplexRotationEven:
4389 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004390 case Match_InvalidGPR64shifted8:
4391 case Match_InvalidGPR64shifted16:
4392 case Match_InvalidGPR64shifted32:
4393 case Match_InvalidGPR64shifted64:
4394 case Match_InvalidGPR64NoXZRshifted8:
4395 case Match_InvalidGPR64NoXZRshifted16:
4396 case Match_InvalidGPR64NoXZRshifted32:
4397 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004398 case Match_InvalidZPR32UXTW8:
4399 case Match_InvalidZPR32UXTW16:
4400 case Match_InvalidZPR32UXTW32:
4401 case Match_InvalidZPR32UXTW64:
4402 case Match_InvalidZPR32SXTW8:
4403 case Match_InvalidZPR32SXTW16:
4404 case Match_InvalidZPR32SXTW32:
4405 case Match_InvalidZPR32SXTW64:
4406 case Match_InvalidZPR64UXTW8:
4407 case Match_InvalidZPR64SXTW8:
4408 case Match_InvalidZPR64UXTW16:
4409 case Match_InvalidZPR64SXTW16:
4410 case Match_InvalidZPR64UXTW32:
4411 case Match_InvalidZPR64SXTW32:
4412 case Match_InvalidZPR64UXTW64:
4413 case Match_InvalidZPR64SXTW64:
4414 case Match_InvalidZPR64LSL8:
4415 case Match_InvalidZPR64LSL16:
4416 case Match_InvalidZPR64LSL32:
4417 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004418 case Match_InvalidZPR0:
4419 case Match_InvalidZPR8:
4420 case Match_InvalidZPR16:
4421 case Match_InvalidZPR32:
4422 case Match_InvalidZPR64:
4423 case Match_InvalidZPR128:
Sander de Smalencd6be962017-12-20 11:02:42 +00004424 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004425 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004426 case Match_InvalidSVEPredicateBReg:
4427 case Match_InvalidSVEPredicateHReg:
4428 case Match_InvalidSVEPredicateSReg:
4429 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004430 case Match_InvalidSVEPredicate3bAnyReg:
4431 case Match_InvalidSVEPredicate3bBReg:
4432 case Match_InvalidSVEPredicate3bHReg:
4433 case Match_InvalidSVEPredicate3bSReg:
4434 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004435 case Match_MSR:
4436 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004437 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004438 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004439 // Any time we get here, there's nothing fancy to do. Just get the
4440 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004441 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004442 if (ErrorLoc == SMLoc())
4443 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004444 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004445 }
4446 }
4447
4448 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004449}
4450
4451/// ParseDirective parses the arm specific directives
4452bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004453 const MCObjectFileInfo::Environment Format =
4454 getContext().getObjectFileInfo()->getObjectFileType();
4455 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4456 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004457
Tim Northover3b0846e2014-05-24 12:50:23 +00004458 StringRef IDVal = DirectiveID.getIdentifier();
4459 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004460 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004461 parseDirectiveArch(Loc);
4462 else if (IDVal == ".cpu")
4463 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00004464 else if (IDVal == ".tlsdesccall")
4465 parseDirectiveTLSDescCall(Loc);
4466 else if (IDVal == ".ltorg" || IDVal == ".pool")
4467 parseDirectiveLtorg(Loc);
4468 else if (IDVal == ".unreq")
4469 parseDirectiveUnreq(Loc);
4470 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004471 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004472 parseDirectiveInst(Loc);
4473 else
4474 return true;
4475 } else if (IDVal == MCLOHDirectiveName())
4476 parseDirectiveLOH(IDVal, Loc);
4477 else
4478 return true;
4479 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004480}
4481
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004482static const struct {
4483 const char *Name;
4484 const FeatureBitset Features;
4485} ExtensionMap[] = {
4486 { "crc", {AArch64::FeatureCRC} },
4487 { "crypto", {AArch64::FeatureCrypto} },
4488 { "fp", {AArch64::FeatureFPARMv8} },
4489 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004490 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004491 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004492
4493 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004494 { "pan", {} },
4495 { "lor", {} },
4496 { "rdma", {} },
4497 { "profile", {} },
4498};
4499
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004500/// parseDirectiveArch
4501/// ::= .arch token
4502bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4503 SMLoc ArchLoc = getLoc();
4504
4505 StringRef Arch, ExtensionString;
4506 std::tie(Arch, ExtensionString) =
4507 getParser().parseStringToEndOfStatement().trim().split('+');
4508
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004509 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4510 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004511 return Error(ArchLoc, "unknown arch name");
4512
4513 if (parseToken(AsmToken::EndOfStatement))
4514 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004515
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004516 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004517 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004518 AArch64::getArchFeatures(ID, AArch64Features);
4519 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4520 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004521
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004522 MCSubtargetInfo &STI = copySTI();
4523 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4524 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4525
4526 SmallVector<StringRef, 4> RequestedExtensions;
4527 if (!ExtensionString.empty())
4528 ExtensionString.split(RequestedExtensions, '+');
4529
4530 FeatureBitset Features = STI.getFeatureBits();
4531 for (auto Name : RequestedExtensions) {
4532 bool EnableFeature = true;
4533
4534 if (Name.startswith_lower("no")) {
4535 EnableFeature = false;
4536 Name = Name.substr(2);
4537 }
4538
4539 for (const auto &Extension : ExtensionMap) {
4540 if (Extension.Name != Name)
4541 continue;
4542
4543 if (Extension.Features.none())
4544 report_fatal_error("unsupported architectural extension: " + Name);
4545
4546 FeatureBitset ToggleFeatures = EnableFeature
4547 ? (~Features & Extension.Features)
4548 : ( Features & Extension.Features);
4549 uint64_t Features =
4550 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4551 setAvailableFeatures(Features);
4552 break;
4553 }
4554 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004555 return false;
4556}
4557
Tim Northover8b96c7e2017-05-15 19:42:15 +00004558static SMLoc incrementLoc(SMLoc L, int Offset) {
4559 return SMLoc::getFromPointer(L.getPointer() + Offset);
4560}
4561
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004562/// parseDirectiveCPU
4563/// ::= .cpu id
4564bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004565 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004566
4567 StringRef CPU, ExtensionString;
4568 std::tie(CPU, ExtensionString) =
4569 getParser().parseStringToEndOfStatement().trim().split('+');
4570
Nirav Davee833c6c2016-11-08 18:31:04 +00004571 if (parseToken(AsmToken::EndOfStatement))
4572 return true;
4573
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004574 SmallVector<StringRef, 4> RequestedExtensions;
4575 if (!ExtensionString.empty())
4576 ExtensionString.split(RequestedExtensions, '+');
4577
4578 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4579 // once that is tablegen'ed
4580 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004581 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004582 return false;
4583 }
4584
4585 MCSubtargetInfo &STI = copySTI();
4586 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004587 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004588
4589 FeatureBitset Features = STI.getFeatureBits();
4590 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004591 // Advance source location past '+'.
4592 CurLoc = incrementLoc(CurLoc, 1);
4593
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004594 bool EnableFeature = true;
4595
4596 if (Name.startswith_lower("no")) {
4597 EnableFeature = false;
4598 Name = Name.substr(2);
4599 }
4600
Tim Northover8b96c7e2017-05-15 19:42:15 +00004601 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004602 for (const auto &Extension : ExtensionMap) {
4603 if (Extension.Name != Name)
4604 continue;
4605
4606 if (Extension.Features.none())
4607 report_fatal_error("unsupported architectural extension: " + Name);
4608
4609 FeatureBitset ToggleFeatures = EnableFeature
4610 ? (~Features & Extension.Features)
4611 : ( Features & Extension.Features);
4612 uint64_t Features =
4613 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4614 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004615 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004616
4617 break;
4618 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004619
4620 if (!FoundExtension)
4621 Error(CurLoc, "unsupported architectural extension");
4622
4623 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004624 }
4625 return false;
4626}
4627
Chad Rosierdcd2a302014-10-22 20:35:57 +00004628/// parseDirectiveInst
4629/// ::= .inst opcode [, ...]
4630bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004631 if (getLexer().is(AsmToken::EndOfStatement))
4632 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004633
Nirav Davee833c6c2016-11-08 18:31:04 +00004634 auto parseOp = [&]() -> bool {
4635 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004636 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004637 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4638 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004639 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004640 if (check(!Value, L, "expected constant expression"))
4641 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004642 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004643 return false;
4644 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004645
Nirav Davee833c6c2016-11-08 18:31:04 +00004646 if (parseMany(parseOp))
4647 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004648 return false;
4649}
4650
Tim Northover3b0846e2014-05-24 12:50:23 +00004651// parseDirectiveTLSDescCall:
4652// ::= .tlsdesccall symbol
4653bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4654 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004655 if (check(getParser().parseIdentifier(Name), L,
4656 "expected symbol after directive") ||
4657 parseToken(AsmToken::EndOfStatement))
4658 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004659
Jim Grosbach6f482002015-05-18 18:43:14 +00004660 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004661 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4662 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004663
4664 MCInst Inst;
4665 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004666 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004667
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004668 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004669 return false;
4670}
4671
4672/// ::= .loh <lohName | lohId> label1, ..., labelN
4673/// The number of arguments depends on the loh identifier.
4674bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004675 MCLOHType Kind;
4676 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4677 if (getParser().getTok().isNot(AsmToken::Integer))
4678 return TokError("expected an identifier or a number in directive");
4679 // We successfully get a numeric value for the identifier.
4680 // Check if it is valid.
4681 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004682 if (Id <= -1U && !isValidMCLOHType(Id))
4683 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004684 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004685 } else {
4686 StringRef Name = getTok().getIdentifier();
4687 // We successfully parse an identifier.
4688 // Check if it is a recognized one.
4689 int Id = MCLOHNameToId(Name);
4690
4691 if (Id == -1)
4692 return TokError("invalid identifier in directive");
4693 Kind = (MCLOHType)Id;
4694 }
4695 // Consume the identifier.
4696 Lex();
4697 // Get the number of arguments of this LOH.
4698 int NbArgs = MCLOHIdToNbArgs(Kind);
4699
4700 assert(NbArgs != -1 && "Invalid number of arguments");
4701
4702 SmallVector<MCSymbol *, 3> Args;
4703 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4704 StringRef Name;
4705 if (getParser().parseIdentifier(Name))
4706 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004707 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004708
4709 if (Idx + 1 == NbArgs)
4710 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004711 if (parseToken(AsmToken::Comma,
4712 "unexpected token in '" + Twine(IDVal) + "' directive"))
4713 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004714 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004715 if (parseToken(AsmToken::EndOfStatement,
4716 "unexpected token in '" + Twine(IDVal) + "' directive"))
4717 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004718
4719 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4720 return false;
4721}
4722
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004723/// parseDirectiveLtorg
4724/// ::= .ltorg | .pool
4725bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004726 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4727 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004728 getTargetStreamer().emitCurrentConstantPool();
4729 return false;
4730}
4731
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004732/// parseDirectiveReq
4733/// ::= name .req registername
4734bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004735 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004736 Parser.Lex(); // Eat the '.req' token.
4737 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004738 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004739 unsigned RegNum;
4740 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004741
Sander de Smalen50d87022018-04-19 07:35:08 +00004742 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004743 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004744 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004745 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004746
Sander de Smalen50d87022018-04-19 07:35:08 +00004747 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004748 return true;
4749
Sander de Smalen50d87022018-04-19 07:35:08 +00004750 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004751 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004752 }
4753
Sander de Smalen50d87022018-04-19 07:35:08 +00004754 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004755 StringRef Kind;
4756 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004757 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004758 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004759
Sander de Smalen50d87022018-04-19 07:35:08 +00004760 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004761 return true;
4762
Sander de Smalen50d87022018-04-19 07:35:08 +00004763 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004764 return Error(SRegLoc,
4765 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004766 }
4767
Sander de Smalen50d87022018-04-19 07:35:08 +00004768 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00004769 StringRef Kind;
4770 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004771 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004772
Sander de Smalen50d87022018-04-19 07:35:08 +00004773 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00004774 return true;
4775
Sander de Smalen50d87022018-04-19 07:35:08 +00004776 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00004777 return Error(SRegLoc,
4778 "sve predicate register without type specifier expected");
4779 }
4780
Sander de Smalen50d87022018-04-19 07:35:08 +00004781 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00004782 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004783
4784 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004785 if (parseToken(AsmToken::EndOfStatement,
4786 "unexpected input in .req directive"))
4787 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004788
Sander de Smalen8e607342017-11-15 15:44:43 +00004789 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004790 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004791 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4792
Nirav Dave2364748a2016-09-16 18:30:20 +00004793 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004794}
4795
4796/// parseDirectiveUneq
4797/// ::= .unreq registername
4798bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004799 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004800 if (getTok().isNot(AsmToken::Identifier))
4801 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004802 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4803 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004804 if (parseToken(AsmToken::EndOfStatement))
4805 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004806 return false;
4807}
4808
Tim Northover3b0846e2014-05-24 12:50:23 +00004809bool
4810AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4811 AArch64MCExpr::VariantKind &ELFRefKind,
4812 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4813 int64_t &Addend) {
4814 ELFRefKind = AArch64MCExpr::VK_INVALID;
4815 DarwinRefKind = MCSymbolRefExpr::VK_None;
4816 Addend = 0;
4817
4818 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4819 ELFRefKind = AE->getKind();
4820 Expr = AE->getSubExpr();
4821 }
4822
4823 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4824 if (SE) {
4825 // It's a simple symbol reference with no addend.
4826 DarwinRefKind = SE->getKind();
4827 return true;
4828 }
4829
4830 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4831 if (!BE)
4832 return false;
4833
4834 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4835 if (!SE)
4836 return false;
4837 DarwinRefKind = SE->getKind();
4838
4839 if (BE->getOpcode() != MCBinaryExpr::Add &&
4840 BE->getOpcode() != MCBinaryExpr::Sub)
4841 return false;
4842
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004843 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004844 // on here than we can deal with.
4845 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4846 if (!AddendExpr)
4847 return false;
4848
4849 Addend = AddendExpr->getValue();
4850 if (BE->getOpcode() == MCBinaryExpr::Sub)
4851 Addend = -Addend;
4852
4853 // It's some symbol reference + a constant addend, but really
4854 // shouldn't use both Darwin and ELF syntax.
4855 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4856 DarwinRefKind == MCSymbolRefExpr::VK_None;
4857}
4858
4859/// Force static initialization.
4860extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004861 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4862 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4863 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004864}
4865
4866#define GET_REGISTER_MATCHER
4867#define GET_SUBTARGET_FEATURE_NAME
4868#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004869#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004870#include "AArch64GenAsmMatcher.inc"
4871
4872// Define this matcher function after the auto-generated include so we
4873// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004874unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004875 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004876 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004877 // If the kind is a token for a literal immediate, check if our asm
4878 // operand matches. This is for InstAliases which have a fixed-value
4879 // immediate in the syntax.
4880 int64_t ExpectedVal;
4881 switch (Kind) {
4882 default:
4883 return Match_InvalidOperand;
4884 case MCK__35_0:
4885 ExpectedVal = 0;
4886 break;
4887 case MCK__35_1:
4888 ExpectedVal = 1;
4889 break;
4890 case MCK__35_12:
4891 ExpectedVal = 12;
4892 break;
4893 case MCK__35_16:
4894 ExpectedVal = 16;
4895 break;
4896 case MCK__35_2:
4897 ExpectedVal = 2;
4898 break;
4899 case MCK__35_24:
4900 ExpectedVal = 24;
4901 break;
4902 case MCK__35_3:
4903 ExpectedVal = 3;
4904 break;
4905 case MCK__35_32:
4906 ExpectedVal = 32;
4907 break;
4908 case MCK__35_4:
4909 ExpectedVal = 4;
4910 break;
4911 case MCK__35_48:
4912 ExpectedVal = 48;
4913 break;
4914 case MCK__35_6:
4915 ExpectedVal = 6;
4916 break;
4917 case MCK__35_64:
4918 ExpectedVal = 64;
4919 break;
4920 case MCK__35_8:
4921 ExpectedVal = 8;
4922 break;
4923 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004924 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004925 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004926 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004927 if (!CE)
4928 return Match_InvalidOperand;
4929 if (CE->getValue() == ExpectedVal)
4930 return Match_Success;
4931 return Match_InvalidOperand;
4932}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004933
Alex Bradbury58eba092016-11-01 16:32:05 +00004934OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004935AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4936
4937 SMLoc S = getLoc();
4938
4939 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4940 Error(S, "expected register");
4941 return MatchOperand_ParseFail;
4942 }
4943
Sander de Smalen50d87022018-04-19 07:35:08 +00004944 unsigned FirstReg;
4945 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
4946 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004947 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00004948
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004949 const MCRegisterClass &WRegClass =
4950 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4951 const MCRegisterClass &XRegClass =
4952 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4953
4954 bool isXReg = XRegClass.contains(FirstReg),
4955 isWReg = WRegClass.contains(FirstReg);
4956 if (!isXReg && !isWReg) {
4957 Error(S, "expected first even register of a "
4958 "consecutive same-size even/odd register pair");
4959 return MatchOperand_ParseFail;
4960 }
4961
4962 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4963 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4964
4965 if (FirstEncoding & 0x1) {
4966 Error(S, "expected first even register of a "
4967 "consecutive same-size even/odd register pair");
4968 return MatchOperand_ParseFail;
4969 }
4970
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004971 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00004972 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004973 return MatchOperand_ParseFail;
4974 }
4975 // Eat the comma
4976 getParser().Lex();
4977
4978 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00004979 unsigned SecondReg;
4980 Res = tryParseScalarRegister(SecondReg);
4981 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004982 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004983
Eugene Zelenko049b0172017-01-06 00:30:53 +00004984 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004985 (isXReg && !XRegClass.contains(SecondReg)) ||
4986 (isWReg && !WRegClass.contains(SecondReg))) {
4987 Error(E,"expected second odd register of a "
4988 "consecutive same-size even/odd register pair");
4989 return MatchOperand_ParseFail;
4990 }
Joel Jones504bf332016-10-24 13:37:13 +00004991
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004992 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004993 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004994 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4995 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4996 } else {
4997 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4998 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4999 }
5000
Florian Hahnc4422242017-11-07 13:07:50 +00005001 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5002 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005003
5004 return MatchOperand_Success;
5005}
Florian Hahn91f11e52017-11-07 16:45:48 +00005006
Sander de Smaleneb896b12018-04-25 09:26:47 +00005007template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005008OperandMatchResultTy
5009AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005010 const SMLoc S = getLoc();
5011 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005012 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005013 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005014
Sander de Smalen8e607342017-11-15 15:44:43 +00005015 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005016 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005017
5018 if (Res != MatchOperand_Success)
5019 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005020
5021 if (ParseSuffix && Kind.empty())
5022 return MatchOperand_NoMatch;
5023
Sander de Smalen73937b72018-04-11 07:36:10 +00005024 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5025 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005026 return MatchOperand_NoMatch;
5027
Sander de Smalen73937b72018-04-11 07:36:10 +00005028 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005029
5030 // No shift/extend is the default.
5031 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5032 Operands.push_back(AArch64Operand::CreateVectorReg(
5033 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5034
Sander de Smalenc33d6682018-06-04 06:40:55 +00005035 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5036 if (Res == MatchOperand_ParseFail)
5037 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005038 return MatchOperand_Success;
5039 }
5040
5041 // Eat the comma
5042 getParser().Lex();
5043
5044 // Match the shift
5045 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5046 Res = tryParseOptionalShiftExtend(ExtOpnd);
5047 if (Res != MatchOperand_Success)
5048 return Res;
5049
5050 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005051 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005052 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5053 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5054 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005055
5056 return MatchOperand_Success;
5057}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005058
5059OperandMatchResultTy
5060AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5061 MCAsmParser &Parser = getParser();
5062
5063 SMLoc SS = getLoc();
5064 const AsmToken &TokE = Parser.getTok();
5065 bool IsHash = TokE.is(AsmToken::Hash);
5066
5067 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5068 return MatchOperand_NoMatch;
5069
5070 int64_t Pattern;
5071 if (IsHash) {
5072 Parser.Lex(); // Eat hash
5073
5074 // Parse the immediate operand.
5075 const MCExpr *ImmVal;
5076 SS = getLoc();
5077 if (Parser.parseExpression(ImmVal))
5078 return MatchOperand_ParseFail;
5079
5080 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5081 if (!MCE)
5082 return MatchOperand_ParseFail;
5083
5084 Pattern = MCE->getValue();
5085 } else {
5086 // Parse the pattern
5087 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5088 if (!Pat)
5089 return MatchOperand_NoMatch;
5090
5091 Parser.Lex();
5092 Pattern = Pat->Encoding;
5093 assert(Pattern >= 0 && Pattern < 32);
5094 }
5095
5096 Operands.push_back(
5097 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5098 SS, getLoc(), getContext()));
5099
5100 return MatchOperand_Success;
5101}