blob: 83d984c9e4b8b96c4fe739ab505a051c020d8fc7 [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);
136 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
137 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
Tim Northover3b0846e2014-05-24 12:50:23 +0000639 bool isAddSubImm() const {
640 if (!isShiftedImm() && !isImm())
641 return false;
642
643 const MCExpr *Expr;
644
645 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
646 if (isShiftedImm()) {
647 unsigned Shift = ShiftedImm.ShiftAmount;
648 Expr = ShiftedImm.Val;
649 if (Shift != 0 && Shift != 12)
650 return false;
651 } else {
652 Expr = getImm();
653 }
654
655 AArch64MCExpr::VariantKind ELFRefKind;
656 MCSymbolRefExpr::VariantKind DarwinRefKind;
657 int64_t Addend;
658 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
659 DarwinRefKind, Addend)) {
660 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
661 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
662 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
663 || ELFRefKind == AArch64MCExpr::VK_LO12
664 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
665 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
666 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
667 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
668 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
669 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000670 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
671 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
672 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000673 }
674
Diana Picusc93518d2016-10-11 09:17:47 +0000675 // If it's a constant, it should be a real immediate in range:
676 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
677 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
678
679 // If it's an expression, we hope for the best and let the fixup/relocation
680 // code deal with it.
681 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000682 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000683
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000684 bool isAddSubImmNeg() const {
685 if (!isShiftedImm() && !isImm())
686 return false;
687
688 const MCExpr *Expr;
689
690 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
691 if (isShiftedImm()) {
692 unsigned Shift = ShiftedImm.ShiftAmount;
693 Expr = ShiftedImm.Val;
694 if (Shift != 0 && Shift != 12)
695 return false;
696 } else
697 Expr = getImm();
698
699 // Otherwise it should be a real negative immediate in range:
700 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
701 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
702 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000703
Tim Northover3b0846e2014-05-24 12:50:23 +0000704 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000705
Tim Northover3b0846e2014-05-24 12:50:23 +0000706 bool isSIMDImmType10() const {
707 if (!isImm())
708 return false;
709 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
710 if (!MCE)
711 return false;
712 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
713 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000714
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000715 template<int N>
716 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000717 if (!isImm())
718 return false;
719 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
720 if (!MCE)
721 return true;
722 int64_t Val = MCE->getValue();
723 if (Val & 0x3)
724 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000725 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
726 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000727 }
728
729 bool
730 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
731 if (!isImm())
732 return false;
733
734 AArch64MCExpr::VariantKind ELFRefKind;
735 MCSymbolRefExpr::VariantKind DarwinRefKind;
736 int64_t Addend;
737 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
738 DarwinRefKind, Addend)) {
739 return false;
740 }
741 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
742 return false;
743
744 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
745 if (ELFRefKind == AllowedModifiers[i])
746 return Addend == 0;
747 }
748
749 return false;
750 }
751
752 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000753 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000754 }
755
756 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000757 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
758 AArch64MCExpr::VK_TPREL_G2,
759 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000760 }
761
762 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000763 return isMovWSymbol({
764 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000765 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
766 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000767 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000768 }
769
770 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000771 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
772 AArch64MCExpr::VK_TPREL_G0,
773 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000774 }
775
776 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000777 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000778 }
779
780 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000781 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000782 }
783
784 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000785 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
786 AArch64MCExpr::VK_TPREL_G1_NC,
787 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000788 }
789
790 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000791 return isMovWSymbol(
792 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
793 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000794 }
795
796 template<int RegWidth, int Shift>
797 bool isMOVZMovAlias() const {
798 if (!isImm()) return false;
799
800 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
801 if (!CE) return false;
802 uint64_t Value = CE->getValue();
803
Tim Northoverdaa1c012016-06-16 01:42:25 +0000804 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000805 }
806
807 template<int RegWidth, int Shift>
808 bool isMOVNMovAlias() const {
809 if (!isImm()) return false;
810
811 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
812 if (!CE) return false;
813 uint64_t Value = CE->getValue();
814
Tim Northoverdaa1c012016-06-16 01:42:25 +0000815 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000816 }
817
818 bool isFPImm() const { return Kind == k_FPImm; }
819 bool isBarrier() const { return Kind == k_Barrier; }
820 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000821
Tim Northover3b0846e2014-05-24 12:50:23 +0000822 bool isMRSSystemRegister() const {
823 if (!isSysReg()) return false;
824
Tim Northover7cd58932015-01-22 17:23:04 +0000825 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000826 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000827
Tim Northover3b0846e2014-05-24 12:50:23 +0000828 bool isMSRSystemRegister() const {
829 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000830 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000831 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000832
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000833 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000834 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000835 return (SysReg.PStateField == AArch64PState::PAN ||
836 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000837 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000838
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000839 bool isSystemPStateFieldWithImm0_15() const {
840 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000841 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000842 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000843
Florian Hahnc4422242017-11-07 13:07:50 +0000844 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000845 return Kind == k_Register;
846 }
847
848 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000849 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
850 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000851
Florian Hahnc4422242017-11-07 13:07:50 +0000852 bool isNeonVectorReg() const {
853 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
854 }
855
856 bool isNeonVectorRegLo() const {
857 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000858 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
859 Reg.RegNum);
860 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000861
Sander de Smalencd6be962017-12-20 11:02:42 +0000862 template <unsigned Class> bool isSVEVectorReg() const {
863 RegKind RK;
864 switch (Class) {
865 case AArch64::ZPRRegClassID:
866 RK = RegKind::SVEDataVector;
867 break;
868 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000869 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000870 RK = RegKind::SVEPredicateVector;
871 break;
872 default:
873 llvm_unreachable("Unsupport register class");
874 }
875
876 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000877 AArch64MCRegisterClasses[Class].contains(getReg());
878 }
879
Sander de Smalencd6be962017-12-20 11:02:42 +0000880 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +0000881 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
882 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
883 return DiagnosticPredicateTy::NoMatch;
884
885 if (isSVEVectorReg<Class>() &&
886 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
887 return DiagnosticPredicateTy::Match;
888
889 return DiagnosticPredicateTy::NearMatch;
890 }
891
892 template <int ElementWidth, unsigned Class>
893 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
894 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
895 return DiagnosticPredicateTy::NoMatch;
896
897 if (isSVEVectorReg<Class>() &&
898 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
899 return DiagnosticPredicateTy::Match;
900
901 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +0000902 }
903
Sander de Smaleneb896b12018-04-25 09:26:47 +0000904 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +0000905 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
906 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +0000907 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
908 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
909 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000910 return DiagnosticPredicateTy::NoMatch;
911
Sander de Smalen5861c262018-04-30 07:24:38 +0000912 // Give a more specific diagnostic when the user has explicitly typed in
913 // a shift-amount that does not match what is expected, but for which
914 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
915 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
916 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
917 ShiftExtendTy == AArch64_AM::SXTW) &&
918 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
919 return DiagnosticPredicateTy::NoMatch;
920
921 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000922 return DiagnosticPredicateTy::Match;
923
924 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +0000925 }
926
Tim Northover3b0846e2014-05-24 12:50:23 +0000927 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000928 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000929 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
930 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000931
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000932 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000933 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000934 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
935 Reg.RegNum);
936 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000937
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000938 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000939 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000940 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
941 Reg.RegNum);
942 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000943
Sam Parker5f934642017-08-31 09:27:04 +0000944 template<int64_t Angle, int64_t Remainder>
945 bool isComplexRotation() const {
946 if (!isImm()) return false;
947
948 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
949 if (!CE) return false;
950 uint64_t Value = CE->getValue();
951
952 return (Value % Angle == Remainder && Value <= 270);
953 }
954
Sander de Smalen149916d2018-04-20 07:24:20 +0000955 template <unsigned RegClassID> bool isGPR64() const {
956 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
957 AArch64MCRegisterClasses[RegClassID].contains(getReg());
958 }
959
960 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +0000961 DiagnosticPredicate isGPR64WithShiftExtend() const {
962 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
963 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +0000964
Sander de Smalenfe17a782018-04-26 12:54:42 +0000965 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
966 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
967 return DiagnosticPredicateTy::Match;
968 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +0000969 }
970
Tim Northover3b0846e2014-05-24 12:50:23 +0000971 /// Is this a vector list with the type implicit (presumably attached to the
972 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +0000973 template <RegKind VectorKind, unsigned NumRegs>
974 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000975 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +0000976 VectorList.NumElements == 0 &&
977 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000978 }
979
Sander de Smalen650234b2018-04-12 11:40:52 +0000980 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
981 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +0000982 bool isTypedVectorList() const {
983 if (Kind != k_VectorList)
984 return false;
985 if (VectorList.Count != NumRegs)
986 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +0000987 if (VectorList.RegisterKind != VectorKind)
988 return false;
989 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +0000990 return false;
991 return VectorList.NumElements == NumElements;
992 }
993
994 bool isVectorIndex1() const {
995 return Kind == k_VectorIndex && VectorIndex.Val == 1;
996 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000997
Tim Northover3b0846e2014-05-24 12:50:23 +0000998 bool isVectorIndexB() const {
999 return Kind == k_VectorIndex && VectorIndex.Val < 16;
1000 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001001
Tim Northover3b0846e2014-05-24 12:50:23 +00001002 bool isVectorIndexH() const {
1003 return Kind == k_VectorIndex && VectorIndex.Val < 8;
1004 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001005
Tim Northover3b0846e2014-05-24 12:50:23 +00001006 bool isVectorIndexS() const {
1007 return Kind == k_VectorIndex && VectorIndex.Val < 4;
1008 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001009
Tim Northover3b0846e2014-05-24 12:50:23 +00001010 bool isVectorIndexD() const {
1011 return Kind == k_VectorIndex && VectorIndex.Val < 2;
1012 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001013
Tim Northover3b0846e2014-05-24 12:50:23 +00001014 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001015
Tim Northover3b0846e2014-05-24 12:50:23 +00001016 bool isTokenEqual(StringRef Str) const {
1017 return Kind == k_Token && getToken() == Str;
1018 }
1019 bool isSysCR() const { return Kind == k_SysCR; }
1020 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001021 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001022 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1023 bool isShifter() const {
1024 if (!isShiftExtend())
1025 return false;
1026
1027 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1028 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1029 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1030 ST == AArch64_AM::MSL);
1031 }
1032 bool isExtend() const {
1033 if (!isShiftExtend())
1034 return false;
1035
1036 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1037 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1038 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1039 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1040 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1041 ET == AArch64_AM::LSL) &&
1042 getShiftExtendAmount() <= 4;
1043 }
1044
1045 bool isExtend64() const {
1046 if (!isExtend())
1047 return false;
1048 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1049 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1050 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1051 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001052
Tim Northover3b0846e2014-05-24 12:50:23 +00001053 bool isExtendLSL64() const {
1054 if (!isExtend())
1055 return false;
1056 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1057 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1058 ET == AArch64_AM::LSL) &&
1059 getShiftExtendAmount() <= 4;
1060 }
1061
1062 template<int Width> bool isMemXExtend() const {
1063 if (!isExtend())
1064 return false;
1065 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1066 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1067 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1068 getShiftExtendAmount() == 0);
1069 }
1070
1071 template<int Width> bool isMemWExtend() const {
1072 if (!isExtend())
1073 return false;
1074 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1075 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1076 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1077 getShiftExtendAmount() == 0);
1078 }
1079
1080 template <unsigned width>
1081 bool isArithmeticShifter() const {
1082 if (!isShifter())
1083 return false;
1084
1085 // An arithmetic shifter is LSL, LSR, or ASR.
1086 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1087 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1088 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1089 }
1090
1091 template <unsigned width>
1092 bool isLogicalShifter() const {
1093 if (!isShifter())
1094 return false;
1095
1096 // A logical shifter is LSL, LSR, ASR or ROR.
1097 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1098 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1099 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1100 getShiftExtendAmount() < width;
1101 }
1102
1103 bool isMovImm32Shifter() const {
1104 if (!isShifter())
1105 return false;
1106
1107 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1108 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1109 if (ST != AArch64_AM::LSL)
1110 return false;
1111 uint64_t Val = getShiftExtendAmount();
1112 return (Val == 0 || Val == 16);
1113 }
1114
1115 bool isMovImm64Shifter() const {
1116 if (!isShifter())
1117 return false;
1118
1119 // A MOVi shifter is LSL of 0 or 16.
1120 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1121 if (ST != AArch64_AM::LSL)
1122 return false;
1123 uint64_t Val = getShiftExtendAmount();
1124 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1125 }
1126
1127 bool isLogicalVecShifter() const {
1128 if (!isShifter())
1129 return false;
1130
1131 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1132 unsigned Shift = getShiftExtendAmount();
1133 return getShiftExtendType() == AArch64_AM::LSL &&
1134 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1135 }
1136
1137 bool isLogicalVecHalfWordShifter() const {
1138 if (!isLogicalVecShifter())
1139 return false;
1140
1141 // A logical vector shifter is a left shift by 0 or 8.
1142 unsigned Shift = getShiftExtendAmount();
1143 return getShiftExtendType() == AArch64_AM::LSL &&
1144 (Shift == 0 || Shift == 8);
1145 }
1146
1147 bool isMoveVecShifter() const {
1148 if (!isShiftExtend())
1149 return false;
1150
1151 // A logical vector shifter is a left shift by 8 or 16.
1152 unsigned Shift = getShiftExtendAmount();
1153 return getShiftExtendType() == AArch64_AM::MSL &&
1154 (Shift == 8 || Shift == 16);
1155 }
1156
1157 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1158 // to LDUR/STUR when the offset is not legal for the former but is for
1159 // the latter. As such, in addition to checking for being a legal unscaled
1160 // address, also check that it is not a legal scaled address. This avoids
1161 // ambiguity in the matcher.
1162 template<int Width>
1163 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001164 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001165 }
1166
1167 bool isAdrpLabel() const {
1168 // Validation was handled during parsing, so we just sanity check that
1169 // something didn't go haywire.
1170 if (!isImm())
1171 return false;
1172
1173 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1174 int64_t Val = CE->getValue();
1175 int64_t Min = - (4096 * (1LL << (21 - 1)));
1176 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1177 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1178 }
1179
1180 return true;
1181 }
1182
1183 bool isAdrLabel() const {
1184 // Validation was handled during parsing, so we just sanity check that
1185 // something didn't go haywire.
1186 if (!isImm())
1187 return false;
1188
1189 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1190 int64_t Val = CE->getValue();
1191 int64_t Min = - (1LL << (21 - 1));
1192 int64_t Max = ((1LL << (21 - 1)) - 1);
1193 return Val >= Min && Val <= Max;
1194 }
1195
1196 return true;
1197 }
1198
1199 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1200 // Add as immediates when possible. Null MCExpr = 0.
1201 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001202 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001203 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001204 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001205 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001206 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001207 }
1208
1209 void addRegOperands(MCInst &Inst, unsigned N) const {
1210 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001211 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001212 }
1213
1214 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1215 assert(N == 1 && "Invalid number of operands!");
1216 assert(
1217 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1218
1219 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1220 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1221 RI->getEncodingValue(getReg()));
1222
Jim Grosbache9119e42015-05-13 18:37:00 +00001223 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001224 }
1225
1226 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1227 assert(N == 1 && "Invalid number of operands!");
1228 assert(
1229 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001230 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001231 }
1232
1233 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1234 assert(N == 1 && "Invalid number of operands!");
1235 assert(
1236 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001237 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001238 }
1239
1240 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1241 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001242 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001243 }
1244
Sander de Smalen525e3222018-04-12 13:19:32 +00001245 enum VecListIndexType {
1246 VecListIdx_DReg = 0,
1247 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001248 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001249 };
1250
1251 template <VecListIndexType RegTy, unsigned NumRegs>
1252 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001253 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001254 static const unsigned FirstRegs[][5] = {
1255 /* DReg */ { AArch64::Q0,
1256 AArch64::D0, AArch64::D0_D1,
1257 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1258 /* QReg */ { AArch64::Q0,
1259 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001260 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1261 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001262 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001263 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001264 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001265
Sander de Smalen7a210db2018-04-16 10:46:18 +00001266 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1267 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001268
Sander de Smalen525e3222018-04-12 13:19:32 +00001269 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1270 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1271 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001272 }
1273
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001274 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001275 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001276 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001277 }
1278
1279 void addImmOperands(MCInst &Inst, unsigned N) const {
1280 assert(N == 1 && "Invalid number of operands!");
1281 // If this is a pageoff symrefexpr with an addend, adjust the addend
1282 // to be only the page-offset portion. Otherwise, just add the expr
1283 // as-is.
1284 addExpr(Inst, getImm());
1285 }
1286
1287 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1288 assert(N == 2 && "Invalid number of operands!");
1289 if (isShiftedImm()) {
1290 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001291 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001292 } else {
1293 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001294 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001295 }
1296 }
1297
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001298 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1299 assert(N == 2 && "Invalid number of operands!");
1300
1301 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1302 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1303 int64_t Val = -CE->getValue();
1304 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1305
1306 Inst.addOperand(MCOperand::createImm(Val));
1307 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1308 }
1309
Tim Northover3b0846e2014-05-24 12:50:23 +00001310 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1311 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001312 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001313 }
1314
1315 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1316 assert(N == 1 && "Invalid number of operands!");
1317 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1318 if (!MCE)
1319 addExpr(Inst, getImm());
1320 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001321 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001322 }
1323
1324 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1325 addImmOperands(Inst, N);
1326 }
1327
1328 template<int Scale>
1329 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1330 assert(N == 1 && "Invalid number of operands!");
1331 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1332
1333 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001334 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001335 return;
1336 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001337 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001338 }
1339
Sander de Smalen5c625982018-04-13 12:56:14 +00001340 template <int Scale>
1341 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1342 assert(N == 1 && "Invalid number of operands!");
1343 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1344 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1345 }
1346
Sander de Smalena1c259c2018-01-29 13:05:38 +00001347 template <typename T>
1348 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001349 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001350 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001351 typename std::make_unsigned<T>::type Val = MCE->getValue();
1352 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001353 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001354 }
1355
Sander de Smalena1c259c2018-01-29 13:05:38 +00001356 template <typename T>
1357 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001358 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001359 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001360 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1361 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001362 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001363 }
1364
Tim Northover3b0846e2014-05-24 12:50:23 +00001365 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1366 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001367 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001368 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001369 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001370 }
1371
1372 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1373 // Branch operands don't encode the low bits, so shift them off
1374 // here. If it's a label, however, just put it on directly as there's
1375 // not enough information now to do anything.
1376 assert(N == 1 && "Invalid number of operands!");
1377 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1378 if (!MCE) {
1379 addExpr(Inst, getImm());
1380 return;
1381 }
1382 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001383 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001384 }
1385
1386 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1387 // Branch operands don't encode the low bits, so shift them off
1388 // here. If it's a label, however, just put it on directly as there's
1389 // not enough information now to do anything.
1390 assert(N == 1 && "Invalid number of operands!");
1391 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1392 if (!MCE) {
1393 addExpr(Inst, getImm());
1394 return;
1395 }
1396 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001397 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001398 }
1399
1400 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1401 // Branch operands don't encode the low bits, so shift them off
1402 // here. If it's a label, however, just put it on directly as there's
1403 // not enough information now to do anything.
1404 assert(N == 1 && "Invalid number of operands!");
1405 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1406 if (!MCE) {
1407 addExpr(Inst, getImm());
1408 return;
1409 }
1410 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001411 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001412 }
1413
1414 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1415 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001416 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001417 }
1418
1419 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1420 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001421 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001422 }
1423
1424 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1425 assert(N == 1 && "Invalid number of operands!");
1426
Jim Grosbache9119e42015-05-13 18:37:00 +00001427 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001428 }
1429
1430 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1431 assert(N == 1 && "Invalid number of operands!");
1432
Jim Grosbache9119e42015-05-13 18:37:00 +00001433 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 }
1435
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001436 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1437 assert(N == 1 && "Invalid number of operands!");
1438
1439 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1440 }
1441
1442 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001443 assert(N == 1 && "Invalid number of operands!");
1444
Jim Grosbache9119e42015-05-13 18:37:00 +00001445 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001446 }
1447
1448 void addSysCROperands(MCInst &Inst, unsigned N) const {
1449 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001450 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001451 }
1452
1453 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1454 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001455 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001456 }
1457
Oliver Stannarda34e4702015-12-01 10:48:51 +00001458 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1459 assert(N == 1 && "Invalid number of operands!");
1460 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1461 }
1462
Tim Northover3b0846e2014-05-24 12:50:23 +00001463 void addShifterOperands(MCInst &Inst, unsigned N) const {
1464 assert(N == 1 && "Invalid number of operands!");
1465 unsigned Imm =
1466 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001467 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001468 }
1469
1470 void addExtendOperands(MCInst &Inst, unsigned N) const {
1471 assert(N == 1 && "Invalid number of operands!");
1472 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1473 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1474 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001475 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001476 }
1477
1478 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1479 assert(N == 1 && "Invalid number of operands!");
1480 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1481 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1482 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001483 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001484 }
1485
1486 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1487 assert(N == 2 && "Invalid number of operands!");
1488 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1489 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001490 Inst.addOperand(MCOperand::createImm(IsSigned));
1491 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001492 }
1493
1494 // For 8-bit load/store instructions with a register offset, both the
1495 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1496 // they're disambiguated by whether the shift was explicit or implicit rather
1497 // than its size.
1498 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1499 assert(N == 2 && "Invalid number of operands!");
1500 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1501 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001502 Inst.addOperand(MCOperand::createImm(IsSigned));
1503 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001504 }
1505
1506 template<int Shift>
1507 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1508 assert(N == 1 && "Invalid number of operands!");
1509
1510 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1511 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001512 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001513 }
1514
1515 template<int Shift>
1516 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1517 assert(N == 1 && "Invalid number of operands!");
1518
1519 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1520 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001521 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001522 }
1523
Sam Parker5f934642017-08-31 09:27:04 +00001524 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1525 assert(N == 1 && "Invalid number of operands!");
1526 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1527 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1528 }
1529
1530 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1531 assert(N == 1 && "Invalid number of operands!");
1532 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1533 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1534 }
1535
Tim Northover3b0846e2014-05-24 12:50:23 +00001536 void print(raw_ostream &OS) const override;
1537
David Blaikie960ea3f2014-06-08 16:18:35 +00001538 static std::unique_ptr<AArch64Operand>
1539 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1540 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001541 Op->Tok.Data = Str.data();
1542 Op->Tok.Length = Str.size();
1543 Op->Tok.IsSuffix = IsSuffix;
1544 Op->StartLoc = S;
1545 Op->EndLoc = S;
1546 return Op;
1547 }
1548
David Blaikie960ea3f2014-06-08 16:18:35 +00001549 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001550 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
1551 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1552 unsigned ShiftAmount = 0,
1553 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001554 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001555 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001556 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001557 Op->Reg.ElementWidth = 0;
1558 Op->Reg.ShiftExtend.Type = ExtTy;
1559 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1560 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001561 Op->StartLoc = S;
1562 Op->EndLoc = E;
1563 return Op;
1564 }
1565
David Blaikie960ea3f2014-06-08 16:18:35 +00001566 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001567 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001568 SMLoc S, SMLoc E, MCContext &Ctx,
1569 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1570 unsigned ShiftAmount = 0,
1571 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001572 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1573 Kind == RegKind::SVEPredicateVector) &&
1574 "Invalid vector kind");
Sander de Smalen149916d2018-04-20 07:24:20 +00001575 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, ExtTy, ShiftAmount,
1576 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001577 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001578 return Op;
1579 }
1580
1581 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001582 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001583 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1584 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001585 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001586 Op->VectorList.RegNum = RegNum;
1587 Op->VectorList.Count = Count;
1588 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001589 Op->VectorList.ElementWidth = ElementWidth;
1590 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001591 Op->StartLoc = S;
1592 Op->EndLoc = E;
1593 return Op;
1594 }
1595
David Blaikie960ea3f2014-06-08 16:18:35 +00001596 static std::unique_ptr<AArch64Operand>
1597 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1598 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001599 Op->VectorIndex.Val = Idx;
1600 Op->StartLoc = S;
1601 Op->EndLoc = E;
1602 return Op;
1603 }
1604
David Blaikie960ea3f2014-06-08 16:18:35 +00001605 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1606 SMLoc E, MCContext &Ctx) {
1607 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001608 Op->Imm.Val = Val;
1609 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> CreateShiftedImm(const MCExpr *Val,
1615 unsigned ShiftAmount,
1616 SMLoc S, SMLoc E,
1617 MCContext &Ctx) {
1618 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001619 Op->ShiftedImm .Val = Val;
1620 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1621 Op->StartLoc = S;
1622 Op->EndLoc = E;
1623 return Op;
1624 }
1625
David Blaikie960ea3f2014-06-08 16:18:35 +00001626 static std::unique_ptr<AArch64Operand>
1627 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1628 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001629 Op->CondCode.Code = Code;
1630 Op->StartLoc = S;
1631 Op->EndLoc = E;
1632 return Op;
1633 }
1634
David Blaikie960ea3f2014-06-08 16:18:35 +00001635 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1636 MCContext &Ctx) {
1637 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001638 Op->FPImm.Val = Val;
1639 Op->StartLoc = S;
1640 Op->EndLoc = S;
1641 return Op;
1642 }
1643
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001644 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1645 StringRef Str,
1646 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001647 MCContext &Ctx) {
1648 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001649 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001650 Op->Barrier.Data = Str.data();
1651 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001652 Op->StartLoc = S;
1653 Op->EndLoc = S;
1654 return Op;
1655 }
1656
Tim Northover7cd58932015-01-22 17:23:04 +00001657 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1658 uint32_t MRSReg,
1659 uint32_t MSRReg,
1660 uint32_t PStateField,
1661 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001662 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001663 Op->SysReg.Data = Str.data();
1664 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001665 Op->SysReg.MRSReg = MRSReg;
1666 Op->SysReg.MSRReg = MSRReg;
1667 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001668 Op->StartLoc = S;
1669 Op->EndLoc = S;
1670 return Op;
1671 }
1672
David Blaikie960ea3f2014-06-08 16:18:35 +00001673 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1674 SMLoc E, MCContext &Ctx) {
1675 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001676 Op->SysCRImm.Val = Val;
1677 Op->StartLoc = S;
1678 Op->EndLoc = E;
1679 return Op;
1680 }
1681
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001682 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1683 StringRef Str,
1684 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001685 MCContext &Ctx) {
1686 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001687 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001688 Op->Barrier.Data = Str.data();
1689 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001690 Op->StartLoc = S;
1691 Op->EndLoc = S;
1692 return Op;
1693 }
1694
Oliver Stannarda34e4702015-12-01 10:48:51 +00001695 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1696 StringRef Str,
1697 SMLoc S,
1698 MCContext &Ctx) {
1699 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1700 Op->PSBHint.Val = Val;
1701 Op->PSBHint.Data = Str.data();
1702 Op->PSBHint.Length = Str.size();
1703 Op->StartLoc = S;
1704 Op->EndLoc = S;
1705 return Op;
1706 }
1707
David Blaikie960ea3f2014-06-08 16:18:35 +00001708 static std::unique_ptr<AArch64Operand>
1709 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1710 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1711 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001712 Op->ShiftExtend.Type = ShOp;
1713 Op->ShiftExtend.Amount = Val;
1714 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1715 Op->StartLoc = S;
1716 Op->EndLoc = E;
1717 return Op;
1718 }
1719};
1720
1721} // end anonymous namespace.
1722
1723void AArch64Operand::print(raw_ostream &OS) const {
1724 switch (Kind) {
1725 case k_FPImm:
1726 OS << "<fpimm " << getFPImm() << "("
1727 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1728 break;
1729 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001730 StringRef Name = getBarrierName();
1731 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001732 OS << "<barrier " << Name << ">";
1733 else
1734 OS << "<barrier invalid #" << getBarrier() << ">";
1735 break;
1736 }
1737 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001738 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001739 break;
1740 case k_ShiftedImm: {
1741 unsigned Shift = getShiftedImmShift();
1742 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001743 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001744 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1745 break;
1746 }
1747 case k_CondCode:
1748 OS << "<condcode " << getCondCode() << ">";
1749 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001750 case k_VectorList: {
1751 OS << "<vectorlist ";
1752 unsigned Reg = getVectorListStart();
1753 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1754 OS << Reg + i << " ";
1755 OS << ">";
1756 break;
1757 }
1758 case k_VectorIndex:
1759 OS << "<vectorindex " << getVectorIndex() << ">";
1760 break;
1761 case k_SysReg:
1762 OS << "<sysreg: " << getSysReg() << '>';
1763 break;
1764 case k_Token:
1765 OS << "'" << getToken() << "'";
1766 break;
1767 case k_SysCR:
1768 OS << "c" << getSysCR();
1769 break;
1770 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001771 StringRef Name = getPrefetchName();
1772 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001773 OS << "<prfop " << Name << ">";
1774 else
1775 OS << "<prfop invalid #" << getPrefetch() << ">";
1776 break;
1777 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001778 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001779 OS << getPSBHintName();
1780 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00001781 case k_Register:
1782 OS << "<register " << getReg() << ">";
1783 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
1784 break;
1785 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001786 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001787 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1788 << getShiftExtendAmount();
1789 if (!hasShiftExtendAmount())
1790 OS << "<imp>";
1791 OS << '>';
1792 break;
1793 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001794}
1795
1796/// @name Auto-generated Match Functions
1797/// {
1798
1799static unsigned MatchRegisterName(StringRef Name);
1800
1801/// }
1802
Florian Hahnc4422242017-11-07 13:07:50 +00001803static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001804 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001805 .Case("v0", AArch64::Q0)
1806 .Case("v1", AArch64::Q1)
1807 .Case("v2", AArch64::Q2)
1808 .Case("v3", AArch64::Q3)
1809 .Case("v4", AArch64::Q4)
1810 .Case("v5", AArch64::Q5)
1811 .Case("v6", AArch64::Q6)
1812 .Case("v7", AArch64::Q7)
1813 .Case("v8", AArch64::Q8)
1814 .Case("v9", AArch64::Q9)
1815 .Case("v10", AArch64::Q10)
1816 .Case("v11", AArch64::Q11)
1817 .Case("v12", AArch64::Q12)
1818 .Case("v13", AArch64::Q13)
1819 .Case("v14", AArch64::Q14)
1820 .Case("v15", AArch64::Q15)
1821 .Case("v16", AArch64::Q16)
1822 .Case("v17", AArch64::Q17)
1823 .Case("v18", AArch64::Q18)
1824 .Case("v19", AArch64::Q19)
1825 .Case("v20", AArch64::Q20)
1826 .Case("v21", AArch64::Q21)
1827 .Case("v22", AArch64::Q22)
1828 .Case("v23", AArch64::Q23)
1829 .Case("v24", AArch64::Q24)
1830 .Case("v25", AArch64::Q25)
1831 .Case("v26", AArch64::Q26)
1832 .Case("v27", AArch64::Q27)
1833 .Case("v28", AArch64::Q28)
1834 .Case("v29", AArch64::Q29)
1835 .Case("v30", AArch64::Q30)
1836 .Case("v31", AArch64::Q31)
1837 .Default(0);
1838}
1839
Sander de Smalen73937b72018-04-11 07:36:10 +00001840/// Returns an optional pair of (#elements, element-width) if Suffix
1841/// is a valid vector kind. Where the number of elements in a vector
1842/// or the vector width is implicit or explicitly unknown (but still a
1843/// valid suffix kind), 0 is used.
1844static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1845 RegKind VectorKind) {
1846 std::pair<int, int> Res = {-1, -1};
1847
1848 switch (VectorKind) {
1849 case RegKind::NeonVector:
1850 Res =
1851 StringSwitch<std::pair<int, int>>(Suffix.lower())
1852 .Case("", {0, 0})
1853 .Case(".1d", {1, 64})
1854 .Case(".1q", {1, 128})
1855 // '.2h' needed for fp16 scalar pairwise reductions
1856 .Case(".2h", {2, 16})
1857 .Case(".2s", {2, 32})
1858 .Case(".2d", {2, 64})
1859 // '.4b' is another special case for the ARMv8.2a dot product
1860 // operand
1861 .Case(".4b", {4, 8})
1862 .Case(".4h", {4, 16})
1863 .Case(".4s", {4, 32})
1864 .Case(".8b", {8, 8})
1865 .Case(".8h", {8, 16})
1866 .Case(".16b", {16, 8})
1867 // Accept the width neutral ones, too, for verbose syntax. If those
1868 // aren't used in the right places, the token operand won't match so
1869 // all will work out.
1870 .Case(".b", {0, 8})
1871 .Case(".h", {0, 16})
1872 .Case(".s", {0, 32})
1873 .Case(".d", {0, 64})
1874 .Default({-1, -1});
1875 break;
1876 case RegKind::SVEPredicateVector:
1877 case RegKind::SVEDataVector:
1878 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1879 .Case("", {0, 0})
1880 .Case(".b", {0, 8})
1881 .Case(".h", {0, 16})
1882 .Case(".s", {0, 32})
1883 .Case(".d", {0, 64})
1884 .Case(".q", {0, 128})
1885 .Default({-1, -1});
1886 break;
1887 default:
1888 llvm_unreachable("Unsupported RegKind");
1889 }
1890
1891 if (Res == std::make_pair(-1, -1))
1892 return Optional<std::pair<int, int>>();
1893
1894 return Optional<std::pair<int, int>>(Res);
1895}
1896
1897static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1898 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001899}
1900
Florian Hahn91f11e52017-11-07 16:45:48 +00001901static unsigned matchSVEDataVectorRegName(StringRef Name) {
1902 return StringSwitch<unsigned>(Name.lower())
1903 .Case("z0", AArch64::Z0)
1904 .Case("z1", AArch64::Z1)
1905 .Case("z2", AArch64::Z2)
1906 .Case("z3", AArch64::Z3)
1907 .Case("z4", AArch64::Z4)
1908 .Case("z5", AArch64::Z5)
1909 .Case("z6", AArch64::Z6)
1910 .Case("z7", AArch64::Z7)
1911 .Case("z8", AArch64::Z8)
1912 .Case("z9", AArch64::Z9)
1913 .Case("z10", AArch64::Z10)
1914 .Case("z11", AArch64::Z11)
1915 .Case("z12", AArch64::Z12)
1916 .Case("z13", AArch64::Z13)
1917 .Case("z14", AArch64::Z14)
1918 .Case("z15", AArch64::Z15)
1919 .Case("z16", AArch64::Z16)
1920 .Case("z17", AArch64::Z17)
1921 .Case("z18", AArch64::Z18)
1922 .Case("z19", AArch64::Z19)
1923 .Case("z20", AArch64::Z20)
1924 .Case("z21", AArch64::Z21)
1925 .Case("z22", AArch64::Z22)
1926 .Case("z23", AArch64::Z23)
1927 .Case("z24", AArch64::Z24)
1928 .Case("z25", AArch64::Z25)
1929 .Case("z26", AArch64::Z26)
1930 .Case("z27", AArch64::Z27)
1931 .Case("z28", AArch64::Z28)
1932 .Case("z29", AArch64::Z29)
1933 .Case("z30", AArch64::Z30)
1934 .Case("z31", AArch64::Z31)
1935 .Default(0);
1936}
1937
Sander de Smalencd6be962017-12-20 11:02:42 +00001938static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1939 return StringSwitch<unsigned>(Name.lower())
1940 .Case("p0", AArch64::P0)
1941 .Case("p1", AArch64::P1)
1942 .Case("p2", AArch64::P2)
1943 .Case("p3", AArch64::P3)
1944 .Case("p4", AArch64::P4)
1945 .Case("p5", AArch64::P5)
1946 .Case("p6", AArch64::P6)
1947 .Case("p7", AArch64::P7)
1948 .Case("p8", AArch64::P8)
1949 .Case("p9", AArch64::P9)
1950 .Case("p10", AArch64::P10)
1951 .Case("p11", AArch64::P11)
1952 .Case("p12", AArch64::P12)
1953 .Case("p13", AArch64::P13)
1954 .Case("p14", AArch64::P14)
1955 .Case("p15", AArch64::P15)
1956 .Default(0);
1957}
1958
Tim Northover3b0846e2014-05-24 12:50:23 +00001959bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1960 SMLoc &EndLoc) {
1961 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00001962 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00001963 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00001964 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00001965}
1966
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001967// Matches a register name or register alias previously defined by '.req'
1968unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001969 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001970 unsigned RegNum = 0;
1971 if ((RegNum = matchSVEDataVectorRegName(Name)))
1972 return Kind == RegKind::SVEDataVector ? RegNum : 0;
1973
Sander de Smalencd6be962017-12-20 11:02:42 +00001974 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
1975 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
1976
Sander de Smalenc067c302017-12-20 09:45:45 +00001977 if ((RegNum = MatchNeonVectorRegName(Name)))
1978 return Kind == RegKind::NeonVector ? RegNum : 0;
1979
1980 // The parsed register must be of RegKind Scalar
1981 if ((RegNum = MatchRegisterName(Name)))
1982 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001983
Florian Hahnc4422242017-11-07 13:07:50 +00001984 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00001985 // Handle a few common aliases of registers.
1986 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
1987 .Case("fp", AArch64::FP)
1988 .Case("lr", AArch64::LR)
1989 .Case("x31", AArch64::XZR)
1990 .Case("w31", AArch64::WZR)
1991 .Default(0))
1992 return Kind == RegKind::Scalar ? RegNum : 0;
1993
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001994 // Check for aliases registered via .req. Canonicalize to lower case.
1995 // That's more consistent since register names are case insensitive, and
1996 // it's how the original entry was passed in from MC/MCParser/AsmParser.
1997 auto Entry = RegisterReqs.find(Name.lower());
1998 if (Entry == RegisterReqs.end())
1999 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002000
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002001 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002002 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002003 RegNum = Entry->getValue().second;
2004 }
2005 return RegNum;
2006}
2007
Sander de Smalen50d87022018-04-19 07:35:08 +00002008/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002009/// Identifier when called, and if it is a register name the token is eaten and
2010/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002011OperandMatchResultTy
2012AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002013 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002014 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002015 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002016 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002017
2018 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002019 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2020 if (Reg == 0)
2021 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002022
Sander de Smalen50d87022018-04-19 07:35:08 +00002023 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002024 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002025 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002026}
2027
Tim Northover3b0846e2014-05-24 12:50:23 +00002028/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002029OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002030AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002031 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002032 SMLoc S = getLoc();
2033
2034 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2035 Error(S, "Expected cN operand where 0 <= N <= 15");
2036 return MatchOperand_ParseFail;
2037 }
2038
2039 StringRef Tok = Parser.getTok().getIdentifier();
2040 if (Tok[0] != 'c' && Tok[0] != 'C') {
2041 Error(S, "Expected cN operand where 0 <= N <= 15");
2042 return MatchOperand_ParseFail;
2043 }
2044
2045 uint32_t CRNum;
2046 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2047 if (BadNum || CRNum > 15) {
2048 Error(S, "Expected cN operand where 0 <= N <= 15");
2049 return MatchOperand_ParseFail;
2050 }
2051
2052 Parser.Lex(); // Eat identifier token.
2053 Operands.push_back(
2054 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2055 return MatchOperand_Success;
2056}
2057
2058/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002059template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002060OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002061AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002062 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002063 SMLoc S = getLoc();
2064 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002065
2066 auto LookupByName = [](StringRef N) {
2067 if (IsSVEPrefetch) {
2068 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2069 return Optional<unsigned>(Res->Encoding);
2070 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2071 return Optional<unsigned>(Res->Encoding);
2072 return Optional<unsigned>();
2073 };
2074
2075 auto LookupByEncoding = [](unsigned E) {
2076 if (IsSVEPrefetch) {
2077 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2078 return Optional<StringRef>(Res->Name);
2079 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2080 return Optional<StringRef>(Res->Name);
2081 return Optional<StringRef>();
2082 };
2083 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2084
Tim Northover3b0846e2014-05-24 12:50:23 +00002085 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002086 // Eat optional hash.
2087 if (parseOptionalToken(AsmToken::Hash) ||
2088 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002089 const MCExpr *ImmVal;
2090 if (getParser().parseExpression(ImmVal))
2091 return MatchOperand_ParseFail;
2092
2093 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2094 if (!MCE) {
2095 TokError("immediate value expected for prefetch operand");
2096 return MatchOperand_ParseFail;
2097 }
2098 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002099 if (prfop > MaxVal) {
2100 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2101 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002102 return MatchOperand_ParseFail;
2103 }
2104
Sander de Smalen93380372018-05-14 11:54:41 +00002105 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002106 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002107 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002108 return MatchOperand_Success;
2109 }
2110
2111 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002112 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002113 return MatchOperand_ParseFail;
2114 }
2115
Sander de Smalen93380372018-05-14 11:54:41 +00002116 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002117 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002118 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002119 return MatchOperand_ParseFail;
2120 }
2121
2122 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002123 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002124 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002125 return MatchOperand_Success;
2126}
2127
Oliver Stannarda34e4702015-12-01 10:48:51 +00002128/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002129OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002130AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2131 MCAsmParser &Parser = getParser();
2132 SMLoc S = getLoc();
2133 const AsmToken &Tok = Parser.getTok();
2134 if (Tok.isNot(AsmToken::Identifier)) {
2135 TokError("invalid operand for instruction");
2136 return MatchOperand_ParseFail;
2137 }
2138
Tim Northovere6ae6762016-07-05 21:23:04 +00002139 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2140 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002141 TokError("invalid operand for instruction");
2142 return MatchOperand_ParseFail;
2143 }
2144
2145 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002146 Operands.push_back(AArch64Operand::CreatePSBHint(
2147 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002148 return MatchOperand_Success;
2149}
2150
Tim Northover3b0846e2014-05-24 12:50:23 +00002151/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2152/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002153OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002154AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002155 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002156 SMLoc S = getLoc();
2157 const MCExpr *Expr;
2158
2159 if (Parser.getTok().is(AsmToken::Hash)) {
2160 Parser.Lex(); // Eat hash token.
2161 }
2162
2163 if (parseSymbolicImmVal(Expr))
2164 return MatchOperand_ParseFail;
2165
2166 AArch64MCExpr::VariantKind ELFRefKind;
2167 MCSymbolRefExpr::VariantKind DarwinRefKind;
2168 int64_t Addend;
2169 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2170 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2171 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2172 // No modifier was specified at all; this is the syntax for an ELF basic
2173 // ADRP relocation (unfortunately).
2174 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002175 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002176 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2177 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2178 Addend != 0) {
2179 Error(S, "gotpage label reference not allowed an addend");
2180 return MatchOperand_ParseFail;
2181 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2182 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2183 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2184 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2185 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2186 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2187 // The operand must be an @page or @gotpage qualified symbolref.
2188 Error(S, "page or gotpage label reference expected");
2189 return MatchOperand_ParseFail;
2190 }
2191 }
2192
2193 // We have either a label reference possibly with addend or an immediate. The
2194 // addend is a raw value here. The linker will adjust it to only reference the
2195 // page.
2196 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2197 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2198
2199 return MatchOperand_Success;
2200}
2201
2202/// tryParseAdrLabel - Parse and validate a source label for the ADR
2203/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002204OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002205AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2206 SMLoc S = getLoc();
2207 const MCExpr *Expr;
2208
Nirav Davee833c6c2016-11-08 18:31:04 +00002209 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002210 if (getParser().parseExpression(Expr))
2211 return MatchOperand_ParseFail;
2212
2213 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2214 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2215
2216 return MatchOperand_Success;
2217}
2218
2219/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002220OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002221AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002222 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002223 SMLoc S = getLoc();
2224
Nirav Davee833c6c2016-11-08 18:31:04 +00002225 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002226
2227 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002228 bool isNegative = parseOptionalToken(AsmToken::Minus);
2229
Tim Northover3b0846e2014-05-24 12:50:23 +00002230 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002231 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002232 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002233 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002234 Val = Tok.getIntVal();
2235 if (Val > 255 || Val < 0) {
2236 TokError("encoded floating point value out of range");
2237 return MatchOperand_ParseFail;
2238 }
2239 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002240 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002241 if (isNegative)
2242 RealVal.changeSign();
2243
Tim Northover3b0846e2014-05-24 12:50:23 +00002244 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002245 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002246
John Brawn5ca5daa2017-04-20 10:13:54 +00002247 // Check for out of range values. As an exception we let Zero through,
2248 // but as tokens instead of an FPImm so that it can be matched by the
2249 // appropriate alias if one exists.
2250 if (RealVal.isPosZero()) {
2251 Parser.Lex(); // Eat the token.
2252 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2253 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2254 return MatchOperand_Success;
2255 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002256 TokError("expected compatible register or floating-point constant");
2257 return MatchOperand_ParseFail;
2258 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002259 }
2260 Parser.Lex(); // Eat the token.
2261 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2262 return MatchOperand_Success;
2263 }
2264
2265 if (!Hash)
2266 return MatchOperand_NoMatch;
2267
2268 TokError("invalid floating point immediate");
2269 return MatchOperand_ParseFail;
2270}
2271
2272/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002273OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002274AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002275 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002276 SMLoc S = getLoc();
2277
2278 if (Parser.getTok().is(AsmToken::Hash))
2279 Parser.Lex(); // Eat '#'
2280 else if (Parser.getTok().isNot(AsmToken::Integer))
2281 // Operand should start from # or should be integer, emit error otherwise.
2282 return MatchOperand_NoMatch;
2283
2284 const MCExpr *Imm;
2285 if (parseSymbolicImmVal(Imm))
2286 return MatchOperand_ParseFail;
2287 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2288 uint64_t ShiftAmount = 0;
2289 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2290 if (MCE) {
2291 int64_t Val = MCE->getValue();
2292 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002293 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002294 ShiftAmount = 12;
2295 }
2296 }
2297 SMLoc E = Parser.getTok().getLoc();
2298 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2299 getContext()));
2300 return MatchOperand_Success;
2301 }
2302
2303 // Eat ','
2304 Parser.Lex();
2305
2306 // The optional operand must be "lsl #N" where N is non-negative.
2307 if (!Parser.getTok().is(AsmToken::Identifier) ||
2308 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2309 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2310 return MatchOperand_ParseFail;
2311 }
2312
2313 // Eat 'lsl'
2314 Parser.Lex();
2315
Nirav Davee833c6c2016-11-08 18:31:04 +00002316 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002317
2318 if (Parser.getTok().isNot(AsmToken::Integer)) {
2319 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2320 return MatchOperand_ParseFail;
2321 }
2322
2323 int64_t ShiftAmount = Parser.getTok().getIntVal();
2324
2325 if (ShiftAmount < 0) {
2326 Error(Parser.getTok().getLoc(), "positive shift amount required");
2327 return MatchOperand_ParseFail;
2328 }
2329 Parser.Lex(); // Eat the number
2330
2331 SMLoc E = Parser.getTok().getLoc();
2332 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2333 S, E, getContext()));
2334 return MatchOperand_Success;
2335}
2336
2337/// parseCondCodeString - Parse a Condition Code string.
2338AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2339 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2340 .Case("eq", AArch64CC::EQ)
2341 .Case("ne", AArch64CC::NE)
2342 .Case("cs", AArch64CC::HS)
2343 .Case("hs", AArch64CC::HS)
2344 .Case("cc", AArch64CC::LO)
2345 .Case("lo", AArch64CC::LO)
2346 .Case("mi", AArch64CC::MI)
2347 .Case("pl", AArch64CC::PL)
2348 .Case("vs", AArch64CC::VS)
2349 .Case("vc", AArch64CC::VC)
2350 .Case("hi", AArch64CC::HI)
2351 .Case("ls", AArch64CC::LS)
2352 .Case("ge", AArch64CC::GE)
2353 .Case("lt", AArch64CC::LT)
2354 .Case("gt", AArch64CC::GT)
2355 .Case("le", AArch64CC::LE)
2356 .Case("al", AArch64CC::AL)
2357 .Case("nv", AArch64CC::NV)
2358 .Default(AArch64CC::Invalid);
2359 return CC;
2360}
2361
2362/// parseCondCode - Parse a Condition Code operand.
2363bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2364 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002365 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002366 SMLoc S = getLoc();
2367 const AsmToken &Tok = Parser.getTok();
2368 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2369
2370 StringRef Cond = Tok.getString();
2371 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2372 if (CC == AArch64CC::Invalid)
2373 return TokError("invalid condition code");
2374 Parser.Lex(); // Eat identifier token.
2375
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002376 if (invertCondCode) {
2377 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2378 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002379 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002380 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002381
2382 Operands.push_back(
2383 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2384 return false;
2385}
2386
2387/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2388/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002389OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002390AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002391 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002392 const AsmToken &Tok = Parser.getTok();
2393 std::string LowerID = Tok.getString().lower();
2394 AArch64_AM::ShiftExtendType ShOp =
2395 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2396 .Case("lsl", AArch64_AM::LSL)
2397 .Case("lsr", AArch64_AM::LSR)
2398 .Case("asr", AArch64_AM::ASR)
2399 .Case("ror", AArch64_AM::ROR)
2400 .Case("msl", AArch64_AM::MSL)
2401 .Case("uxtb", AArch64_AM::UXTB)
2402 .Case("uxth", AArch64_AM::UXTH)
2403 .Case("uxtw", AArch64_AM::UXTW)
2404 .Case("uxtx", AArch64_AM::UXTX)
2405 .Case("sxtb", AArch64_AM::SXTB)
2406 .Case("sxth", AArch64_AM::SXTH)
2407 .Case("sxtw", AArch64_AM::SXTW)
2408 .Case("sxtx", AArch64_AM::SXTX)
2409 .Default(AArch64_AM::InvalidShiftExtend);
2410
2411 if (ShOp == AArch64_AM::InvalidShiftExtend)
2412 return MatchOperand_NoMatch;
2413
2414 SMLoc S = Tok.getLoc();
2415 Parser.Lex();
2416
Nirav Davee833c6c2016-11-08 18:31:04 +00002417 bool Hash = parseOptionalToken(AsmToken::Hash);
2418
Tim Northover3b0846e2014-05-24 12:50:23 +00002419 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2420 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2421 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2422 ShOp == AArch64_AM::MSL) {
2423 // We expect a number here.
2424 TokError("expected #imm after shift specifier");
2425 return MatchOperand_ParseFail;
2426 }
2427
Chad Rosier2ff37b82016-12-27 16:58:09 +00002428 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002429 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2430 Operands.push_back(
2431 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2432 return MatchOperand_Success;
2433 }
2434
Chad Rosier2ff37b82016-12-27 16:58:09 +00002435 // Make sure we do actually have a number, identifier or a parenthesized
2436 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002437 SMLoc E = Parser.getTok().getLoc();
2438 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002439 !Parser.getTok().is(AsmToken::LParen) &&
2440 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002441 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002442 return MatchOperand_ParseFail;
2443 }
2444
2445 const MCExpr *ImmVal;
2446 if (getParser().parseExpression(ImmVal))
2447 return MatchOperand_ParseFail;
2448
2449 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2450 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002451 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002452 return MatchOperand_ParseFail;
2453 }
2454
Jim Grosbach57fd2622014-09-23 22:16:02 +00002455 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002456 Operands.push_back(AArch64Operand::CreateShiftExtend(
2457 ShOp, MCE->getValue(), true, S, E, getContext()));
2458 return MatchOperand_Success;
2459}
2460
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002461static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2462 if (FBS[AArch64::HasV8_1aOps])
2463 Str += "ARMv8.1a";
2464 else if (FBS[AArch64::HasV8_2aOps])
2465 Str += "ARMv8.2a";
2466 else
2467 Str += "(unknown)";
2468}
2469
2470void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2471 SMLoc S) {
2472 const uint16_t Op2 = Encoding & 7;
2473 const uint16_t Cm = (Encoding & 0x78) >> 3;
2474 const uint16_t Cn = (Encoding & 0x780) >> 7;
2475 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2476
2477 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2478
2479 Operands.push_back(
2480 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2481 Operands.push_back(
2482 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2483 Operands.push_back(
2484 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2485 Expr = MCConstantExpr::create(Op2, getContext());
2486 Operands.push_back(
2487 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2488}
2489
Tim Northover3b0846e2014-05-24 12:50:23 +00002490/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2491/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2492bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2493 OperandVector &Operands) {
2494 if (Name.find('.') != StringRef::npos)
2495 return TokError("invalid operand");
2496
2497 Mnemonic = Name;
2498 Operands.push_back(
2499 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2500
Rafael Espindola961d4692014-11-11 05:18:41 +00002501 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002502 const AsmToken &Tok = Parser.getTok();
2503 StringRef Op = Tok.getString();
2504 SMLoc S = Tok.getLoc();
2505
Tim Northover3b0846e2014-05-24 12:50:23 +00002506 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002507 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2508 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002509 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002510 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2511 std::string Str("IC " + std::string(IC->Name) + " requires ");
2512 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2513 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002514 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002515 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002516 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002517 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2518 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002519 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002520 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2521 std::string Str("DC " + std::string(DC->Name) + " requires ");
2522 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2523 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002524 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002525 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002526 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002527 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2528 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002529 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002530 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2531 std::string Str("AT " + std::string(AT->Name) + " requires ");
2532 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2533 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002534 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002535 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002536 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002537 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2538 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002539 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002540 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2541 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2542 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2543 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002544 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002545 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002546 }
2547
Tim Northover3b0846e2014-05-24 12:50:23 +00002548 Parser.Lex(); // Eat operand.
2549
2550 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2551 bool HasRegister = false;
2552
2553 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002554 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002555 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2556 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002557 HasRegister = true;
2558 }
2559
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002560 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002561 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002562 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002563 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002564
Nirav Davee833c6c2016-11-08 18:31:04 +00002565 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2566 return true;
2567
Tim Northover3b0846e2014-05-24 12:50:23 +00002568 return false;
2569}
2570
Alex Bradbury58eba092016-11-01 16:32:05 +00002571OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002572AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002573 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002574 const AsmToken &Tok = Parser.getTok();
2575
2576 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002577 if (parseOptionalToken(AsmToken::Hash) ||
2578 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002579 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002580 const MCExpr *ImmVal;
2581 SMLoc ExprLoc = getLoc();
2582 if (getParser().parseExpression(ImmVal))
2583 return MatchOperand_ParseFail;
2584 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2585 if (!MCE) {
2586 Error(ExprLoc, "immediate value expected for barrier operand");
2587 return MatchOperand_ParseFail;
2588 }
2589 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2590 Error(ExprLoc, "barrier operand out of range");
2591 return MatchOperand_ParseFail;
2592 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002593 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2594 Operands.push_back(AArch64Operand::CreateBarrier(
2595 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002596 return MatchOperand_Success;
2597 }
2598
2599 if (Tok.isNot(AsmToken::Identifier)) {
2600 TokError("invalid operand for instruction");
2601 return MatchOperand_ParseFail;
2602 }
2603
Tim Northover3b0846e2014-05-24 12:50:23 +00002604 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002605 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2606 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002607 TokError("'sy' or #imm operand expected");
2608 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002609 } else if (!DB) {
2610 TokError("invalid barrier option name");
2611 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002612 }
2613
Tim Northovere6ae6762016-07-05 21:23:04 +00002614 Operands.push_back(AArch64Operand::CreateBarrier(
2615 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002616 Parser.Lex(); // Consume the option
2617
2618 return MatchOperand_Success;
2619}
2620
Alex Bradbury58eba092016-11-01 16:32:05 +00002621OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002622AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002623 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002624 const AsmToken &Tok = Parser.getTok();
2625
2626 if (Tok.isNot(AsmToken::Identifier))
2627 return MatchOperand_NoMatch;
2628
Tim Northovere6ae6762016-07-05 21:23:04 +00002629 int MRSReg, MSRReg;
2630 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2631 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2632 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2633 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2634 } else
2635 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002636
Tim Northovere6ae6762016-07-05 21:23:04 +00002637 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2638 unsigned PStateImm = -1;
2639 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2640 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002641
Tim Northovere6ae6762016-07-05 21:23:04 +00002642 Operands.push_back(
2643 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2644 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002645 Parser.Lex(); // Eat identifier
2646
2647 return MatchOperand_Success;
2648}
2649
Florian Hahnc4422242017-11-07 13:07:50 +00002650/// tryParseNeonVectorRegister - Parse a vector register operand.
2651bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002652 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002653 if (Parser.getTok().isNot(AsmToken::Identifier))
2654 return true;
2655
2656 SMLoc S = getLoc();
2657 // Check for a vector register specifier first.
2658 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002659 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002660 OperandMatchResultTy Res =
2661 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2662 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002663 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002664
2665 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2666 if (!KindRes)
2667 return true;
2668
2669 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002670 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002671 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2672 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002673
Tim Northover3b0846e2014-05-24 12:50:23 +00002674 // If there was an explicit qualifier, that goes on as a literal text
2675 // operand.
2676 if (!Kind.empty())
2677 Operands.push_back(
2678 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2679
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002680 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2681}
2682
2683OperandMatchResultTy
2684AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002685 SMLoc SIdx = getLoc();
2686 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002687 const MCExpr *ImmVal;
2688 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002689 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002690 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2691 if (!MCE) {
2692 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002693 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002694 }
2695
2696 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002697
Nirav Davee833c6c2016-11-08 18:31:04 +00002698 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002699 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002700
2701 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2702 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002703 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002704 }
2705
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002706 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002707}
2708
Sander de Smalen73937b72018-04-11 07:36:10 +00002709// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002710// optional kind specifier. If it is a register specifier, eat the token
2711// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002712OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002713AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002714 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002715 MCAsmParser &Parser = getParser();
2716 const AsmToken &Tok = Parser.getTok();
2717
Florian Hahn91f11e52017-11-07 16:45:48 +00002718 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002719 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002720
2721 StringRef Name = Tok.getString();
2722 // If there is a kind specifier, it's separated from the register name by
2723 // a '.'.
2724 size_t Start = 0, Next = Name.find('.');
2725 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002726 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002727
2728 if (RegNum) {
2729 if (Next != StringRef::npos) {
2730 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002731 if (!isValidVectorKind(Kind, MatchKind)) {
2732 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002733 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002734 }
2735 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002736 Parser.Lex(); // Eat the register token.
2737
2738 Reg = RegNum;
2739 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002740 }
2741
Sander de Smalen8e607342017-11-15 15:44:43 +00002742 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002743}
2744
Sander de Smalencd6be962017-12-20 11:02:42 +00002745/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2746OperandMatchResultTy
2747AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2748 // Check for a SVE predicate register specifier first.
2749 const SMLoc S = getLoc();
2750 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002751 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002752 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002753 if (Res != MatchOperand_Success)
2754 return Res;
2755
Sander de Smalen73937b72018-04-11 07:36:10 +00002756 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2757 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002758 return MatchOperand_NoMatch;
2759
Sander de Smalen73937b72018-04-11 07:36:10 +00002760 unsigned ElementWidth = KindRes->second;
2761 Operands.push_back(AArch64Operand::CreateVectorReg(
2762 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2763 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002764
Sander de Smalen7868e742018-01-09 11:17:06 +00002765 // Not all predicates are followed by a '/m' or '/z'.
2766 MCAsmParser &Parser = getParser();
2767 if (Parser.getTok().isNot(AsmToken::Slash))
2768 return MatchOperand_Success;
2769
2770 // But when they do they shouldn't have an element type suffix.
2771 if (!Kind.empty()) {
2772 Error(S, "not expecting size suffix");
2773 return MatchOperand_ParseFail;
2774 }
2775
2776 // Add a literal slash as operand
2777 Operands.push_back(
2778 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2779
2780 Parser.Lex(); // Eat the slash.
2781
2782 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002783 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002784 if (Pred != "z" && Pred != "m") {
2785 Error(getLoc(), "expecting 'm' or 'z' predication");
2786 return MatchOperand_ParseFail;
2787 }
2788
2789 // Add zero/merge token.
2790 const char *ZM = Pred == "z" ? "z" : "m";
2791 Operands.push_back(
2792 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2793
2794 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002795 return MatchOperand_Success;
2796}
2797
Sander de Smalen50d87022018-04-19 07:35:08 +00002798/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002799bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002800 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002801 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002802 return false;
2803
Sander de Smalen149916d2018-04-20 07:24:20 +00002804 // Otherwise try for a scalar register.
2805 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
2806 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002807
Sander de Smalen149916d2018-04-20 07:24:20 +00002808 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002809}
2810
2811bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002812 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002813 bool HasELFModifier = false;
2814 AArch64MCExpr::VariantKind RefKind;
2815
Nirav Davee833c6c2016-11-08 18:31:04 +00002816 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002817 HasELFModifier = true;
2818
Nirav Davee833c6c2016-11-08 18:31:04 +00002819 if (Parser.getTok().isNot(AsmToken::Identifier))
2820 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002821
2822 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2823 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2824 .Case("lo12", AArch64MCExpr::VK_LO12)
2825 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2826 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2827 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2828 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2829 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2830 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2831 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2832 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2833 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2834 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2835 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2836 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2837 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2838 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2839 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2840 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2841 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2842 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2843 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2844 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2845 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2846 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2847 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2848 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2849 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2850 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2851 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2852 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2853 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2854 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2855 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2856 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2857 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2858 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002859 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2860 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002861 .Default(AArch64MCExpr::VK_INVALID);
2862
Nirav Davee833c6c2016-11-08 18:31:04 +00002863 if (RefKind == AArch64MCExpr::VK_INVALID)
2864 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002865
2866 Parser.Lex(); // Eat identifier
2867
Nirav Davee833c6c2016-11-08 18:31:04 +00002868 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002869 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002870 }
2871
2872 if (getParser().parseExpression(ImmVal))
2873 return true;
2874
2875 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002876 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002877
2878 return false;
2879}
2880
Sander de Smalen650234b2018-04-12 11:40:52 +00002881template <RegKind VectorKind>
2882OperandMatchResultTy
2883AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
2884 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002885 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00002886 if (!Parser.getTok().is(AsmToken::LCurly))
2887 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002888
2889 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00002890 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00002891 bool NoMatchIsError) {
2892 auto RegTok = Parser.getTok();
2893 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
2894 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002895 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00002896 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002897 llvm_unreachable("Expected a valid vector kind");
2898 }
2899
Sander de Smalen650234b2018-04-12 11:40:52 +00002900 if (RegTok.isNot(AsmToken::Identifier) ||
2901 ParseRes == MatchOperand_ParseFail ||
2902 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
2903 Error(Loc, "vector register expected");
2904 return MatchOperand_ParseFail;
2905 }
2906
2907 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002908 };
2909
Tim Northover3b0846e2014-05-24 12:50:23 +00002910 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00002911 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00002912 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00002913
Tim Northover3b0846e2014-05-24 12:50:23 +00002914 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002915 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002916 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
2917
2918 // Put back the original left bracket if there was no match, so that
2919 // different types of list-operands can be matched (e.g. SVE, Neon).
2920 if (ParseRes == MatchOperand_NoMatch)
2921 Parser.getLexer().UnLex(LCurly);
2922
2923 if (ParseRes != MatchOperand_Success)
2924 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002925
Tim Northover3b0846e2014-05-24 12:50:23 +00002926 int64_t PrevReg = FirstReg;
2927 unsigned Count = 1;
2928
Nirav Davee833c6c2016-11-08 18:31:04 +00002929 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002930 SMLoc Loc = getLoc();
2931 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002932
Sander de Smalen50d87022018-04-19 07:35:08 +00002933 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002934 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2935 if (ParseRes != MatchOperand_Success)
2936 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002937
Tim Northover3b0846e2014-05-24 12:50:23 +00002938 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002939 if (Kind != NextKind) {
2940 Error(Loc, "mismatched register size suffix");
2941 return MatchOperand_ParseFail;
2942 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002943
2944 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2945
2946 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002947 Error(Loc, "invalid number of vectors");
2948 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002949 }
2950
2951 Count += Space;
2952 }
2953 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002954 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002955 SMLoc Loc = getLoc();
2956 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002957 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002958 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2959 if (ParseRes != MatchOperand_Success)
2960 return ParseRes;
2961
Tim Northover3b0846e2014-05-24 12:50:23 +00002962 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002963 if (Kind != NextKind) {
2964 Error(Loc, "mismatched register size suffix");
2965 return MatchOperand_ParseFail;
2966 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002967
2968 // Registers must be incremental (with wraparound at 31)
2969 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00002970 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
2971 Error(Loc, "registers must be sequential");
2972 return MatchOperand_ParseFail;
2973 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002974
2975 PrevReg = Reg;
2976 ++Count;
2977 }
2978 }
2979
Nirav Davee833c6c2016-11-08 18:31:04 +00002980 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00002981 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002982
Sander de Smalen650234b2018-04-12 11:40:52 +00002983 if (Count > 4) {
2984 Error(S, "invalid number of vectors");
2985 return MatchOperand_ParseFail;
2986 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002987
2988 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00002989 unsigned ElementWidth = 0;
2990 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002991 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00002992 std::tie(NumElements, ElementWidth) = *VK;
2993 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002994
2995 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00002996 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
2997 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002998
Sander de Smalen650234b2018-04-12 11:40:52 +00002999 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003000}
3001
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003002/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3003bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003004 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3005 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003006 return true;
3007
3008 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3009}
3010
Alex Bradbury58eba092016-11-01 16:32:05 +00003011OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003012AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003013 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003014
Sander de Smalen50d87022018-04-19 07:35:08 +00003015 unsigned RegNum;
3016 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3017 if (Res != MatchOperand_Success)
3018 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003019
Nirav Davee833c6c2016-11-08 18:31:04 +00003020 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003021 Operands.push_back(AArch64Operand::CreateReg(
3022 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003023 return MatchOperand_Success;
3024 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003025
Nirav Davee833c6c2016-11-08 18:31:04 +00003026 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003027
Sander de Smalen50d87022018-04-19 07:35:08 +00003028 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003029 Error(getLoc(), "index must be absent or #0");
3030 return MatchOperand_ParseFail;
3031 }
3032
3033 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003034 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003035 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3036 Error(getLoc(), "index must be absent or #0");
3037 return MatchOperand_ParseFail;
3038 }
3039
Sander de Smalen50d87022018-04-19 07:35:08 +00003040 Operands.push_back(AArch64Operand::CreateReg(
3041 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003042 return MatchOperand_Success;
3043}
3044
Sander de Smalen149916d2018-04-20 07:24:20 +00003045template <bool ParseShiftExtend>
3046OperandMatchResultTy
3047AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3048 SMLoc StartLoc = getLoc();
3049
3050 unsigned RegNum;
3051 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3052 if (Res != MatchOperand_Success)
3053 return Res;
3054
3055 // No shift/extend is the default.
3056 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3057 Operands.push_back(AArch64Operand::CreateReg(
3058 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
3059 return MatchOperand_Success;
3060 }
3061
3062 // Eat the comma
3063 getParser().Lex();
3064
3065 // Match the shift
3066 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3067 Res = tryParseOptionalShiftExtend(ExtOpnd);
3068 if (Res != MatchOperand_Success)
3069 return Res;
3070
3071 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
3072 Operands.push_back(AArch64Operand::CreateReg(RegNum, RegKind::Scalar,
3073 StartLoc, Ext->getEndLoc(), getContext(),
3074 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3075 Ext->hasShiftExtendAmount()));
3076
3077 return MatchOperand_Success;
3078}
3079
Sander de Smalen5c625982018-04-13 12:56:14 +00003080bool AArch64AsmParser::parseOptionalMulVl(OperandVector &Operands) {
3081 MCAsmParser &Parser = getParser();
3082
3083 // Some SVE instructions have a decoration after the immediate, i.e.
3084 // "mul vl". We parse them here and add tokens, which must be present in the
3085 // asm string in the tablegen instruction.
3086 if (!Parser.getTok().getString().equals_lower("mul") ||
3087 !Parser.getLexer().peekTok().getString().equals_lower("vl"))
3088 return true;
3089
3090 SMLoc S = getLoc();
3091 Operands.push_back(
3092 AArch64Operand::CreateToken("mul", false, S, getContext()));
3093 Parser.Lex(); // Eat the "mul"
3094
3095 S = getLoc();
3096 Operands.push_back(
3097 AArch64Operand::CreateToken("vl", false, S, getContext()));
3098 Parser.Lex(); // Eat the "vl"
3099
3100 return false;
3101}
3102
Tim Northover3b0846e2014-05-24 12:50:23 +00003103/// parseOperand - Parse a arm instruction operand. For now this parses the
3104/// operand regardless of the mnemonic.
3105bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3106 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003107 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003108
3109 OperandMatchResultTy ResTy =
3110 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3111
Tim Northover3b0846e2014-05-24 12:50:23 +00003112 // Check if the current operand has a custom associated parser, if so, try to
3113 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003114 if (ResTy == MatchOperand_Success)
3115 return false;
3116 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3117 // there was a match, but an error occurred, in which case, just return that
3118 // the operand parsing failed.
3119 if (ResTy == MatchOperand_ParseFail)
3120 return true;
3121
3122 // Nothing custom, so do general case parsing.
3123 SMLoc S, E;
3124 switch (getLexer().getKind()) {
3125 default: {
3126 SMLoc S = getLoc();
3127 const MCExpr *Expr;
3128 if (parseSymbolicImmVal(Expr))
3129 return Error(S, "invalid operand");
3130
3131 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3132 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3133 return false;
3134 }
3135 case AsmToken::LBrac: {
3136 SMLoc Loc = Parser.getTok().getLoc();
3137 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3138 getContext()));
3139 Parser.Lex(); // Eat '['
3140
3141 // There's no comma after a '[', so we can parse the next operand
3142 // immediately.
3143 return parseOperand(Operands, false, false);
3144 }
3145 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003146 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003147 case AsmToken::Identifier: {
3148 // If we're expecting a Condition Code operand, then just parse that.
3149 if (isCondCode)
3150 return parseCondCode(Operands, invertCondCode);
3151
3152 // If it's a register name, parse it.
3153 if (!parseRegister(Operands))
3154 return false;
3155
Sander de Smalen5c625982018-04-13 12:56:14 +00003156 // See if this is a "mul vl" decoration used by SVE instructions.
3157 if (!parseOptionalMulVl(Operands))
3158 return false;
3159
Tim Northover3b0846e2014-05-24 12:50:23 +00003160 // This could be an optional "shift" or "extend" operand.
3161 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3162 // We can only continue if no tokens were eaten.
3163 if (GotShift != MatchOperand_NoMatch)
3164 return GotShift;
3165
3166 // This was not a register so parse other operands that start with an
3167 // identifier (like labels) as expressions and create them as immediates.
3168 const MCExpr *IdVal;
3169 S = getLoc();
3170 if (getParser().parseExpression(IdVal))
3171 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003172 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3173 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3174 return false;
3175 }
3176 case AsmToken::Integer:
3177 case AsmToken::Real:
3178 case AsmToken::Hash: {
3179 // #42 -> immediate.
3180 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003181
3182 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003183
3184 // Parse a negative sign
3185 bool isNegative = false;
3186 if (Parser.getTok().is(AsmToken::Minus)) {
3187 isNegative = true;
3188 // We need to consume this token only when we have a Real, otherwise
3189 // we let parseSymbolicImmVal take care of it
3190 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3191 Parser.Lex();
3192 }
3193
3194 // The only Real that should come through here is a literal #0.0 for
3195 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3196 // so convert the value.
3197 const AsmToken &Tok = Parser.getTok();
3198 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003199 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003200 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3201 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3202 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3203 Mnemonic != "fcmlt")
3204 return TokError("unexpected floating point literal");
3205 else if (IntVal != 0 || isNegative)
3206 return TokError("expected floating-point constant #0.0");
3207 Parser.Lex(); // Eat the token.
3208
3209 Operands.push_back(
3210 AArch64Operand::CreateToken("#0", false, S, getContext()));
3211 Operands.push_back(
3212 AArch64Operand::CreateToken(".0", false, S, getContext()));
3213 return false;
3214 }
3215
3216 const MCExpr *ImmVal;
3217 if (parseSymbolicImmVal(ImmVal))
3218 return true;
3219
3220 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3221 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3222 return false;
3223 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003224 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003225 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003226 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003227 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003228 Parser.Lex(); // Eat '='
3229 const MCExpr *SubExprVal;
3230 if (getParser().parseExpression(SubExprVal))
3231 return true;
3232
David Peixottoae5ba762014-07-18 16:05:14 +00003233 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003234 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003235 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003236
3237 bool IsXReg =
3238 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3239 Operands[1]->getReg());
3240
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003241 MCContext& Ctx = getContext();
3242 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3243 // 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 +00003244 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003245 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3246 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3247 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3248 ShiftAmt += 16;
3249 Imm >>= 16;
3250 }
3251 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3252 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3253 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003254 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003255 if (ShiftAmt)
3256 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3257 ShiftAmt, true, S, E, Ctx));
3258 return false;
3259 }
David Peixottoae5ba762014-07-18 16:05:14 +00003260 APInt Simm = APInt(64, Imm << ShiftAmt);
3261 // check if the immediate is an unsigned or signed 32-bit int for W regs
3262 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3263 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003264 }
3265 // 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 +00003266 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003267 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003268 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3269 return false;
3270 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003271 }
3272}
3273
3274/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3275/// operands.
3276bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3277 StringRef Name, SMLoc NameLoc,
3278 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003279 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003280 Name = StringSwitch<StringRef>(Name.lower())
3281 .Case("beq", "b.eq")
3282 .Case("bne", "b.ne")
3283 .Case("bhs", "b.hs")
3284 .Case("bcs", "b.cs")
3285 .Case("blo", "b.lo")
3286 .Case("bcc", "b.cc")
3287 .Case("bmi", "b.mi")
3288 .Case("bpl", "b.pl")
3289 .Case("bvs", "b.vs")
3290 .Case("bvc", "b.vc")
3291 .Case("bhi", "b.hi")
3292 .Case("bls", "b.ls")
3293 .Case("bge", "b.ge")
3294 .Case("blt", "b.lt")
3295 .Case("bgt", "b.gt")
3296 .Case("ble", "b.le")
3297 .Case("bal", "b.al")
3298 .Case("bnv", "b.nv")
3299 .Default(Name);
3300
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003301 // First check for the AArch64-specific .req directive.
3302 if (Parser.getTok().is(AsmToken::Identifier) &&
3303 Parser.getTok().getIdentifier() == ".req") {
3304 parseDirectiveReq(Name, NameLoc);
3305 // We always return 'error' for this, as we're done with this
3306 // statement and don't need to match the 'instruction."
3307 return true;
3308 }
3309
Tim Northover3b0846e2014-05-24 12:50:23 +00003310 // Create the leading tokens for the mnemonic, split by '.' characters.
3311 size_t Start = 0, Next = Name.find('.');
3312 StringRef Head = Name.slice(Start, Next);
3313
3314 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003315 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3316 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003317
3318 Operands.push_back(
3319 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3320 Mnemonic = Head;
3321
3322 // Handle condition codes for a branch mnemonic
3323 if (Head == "b" && Next != StringRef::npos) {
3324 Start = Next;
3325 Next = Name.find('.', Start + 1);
3326 Head = Name.slice(Start + 1, Next);
3327
3328 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3329 (Head.data() - Name.data()));
3330 AArch64CC::CondCode CC = parseCondCodeString(Head);
3331 if (CC == AArch64CC::Invalid)
3332 return Error(SuffixLoc, "invalid condition code");
3333 Operands.push_back(
3334 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3335 Operands.push_back(
3336 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3337 }
3338
3339 // Add the remaining tokens in the mnemonic.
3340 while (Next != StringRef::npos) {
3341 Start = Next;
3342 Next = Name.find('.', Start + 1);
3343 Head = Name.slice(Start, Next);
3344 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3345 (Head.data() - Name.data()) + 1);
3346 Operands.push_back(
3347 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3348 }
3349
3350 // Conditional compare instructions have a Condition Code operand, which needs
3351 // to be parsed and an immediate operand created.
3352 bool condCodeFourthOperand =
3353 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3354 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3355 Head == "csinc" || Head == "csinv" || Head == "csneg");
3356
3357 // These instructions are aliases to some of the conditional select
3358 // instructions. However, the condition code is inverted in the aliased
3359 // instruction.
3360 //
3361 // FIXME: Is this the correct way to handle these? Or should the parser
3362 // generate the aliased instructions directly?
3363 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3364 bool condCodeThirdOperand =
3365 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3366
3367 // Read the remaining operands.
3368 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3369 // Read the first operand.
3370 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003371 return true;
3372 }
3373
3374 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003375 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003376 // Parse and remember the operand.
3377 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3378 (N == 3 && condCodeThirdOperand) ||
3379 (N == 2 && condCodeSecondOperand),
3380 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003381 return true;
3382 }
3383
3384 // After successfully parsing some operands there are two special cases to
3385 // consider (i.e. notional operands not separated by commas). Both are due
3386 // to memory specifiers:
3387 // + An RBrac will end an address for load/store/prefetch
3388 // + An '!' will indicate a pre-indexed operation.
3389 //
3390 // It's someone else's responsibility to make sure these tokens are sane
3391 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003392
Nirav Davee833c6c2016-11-08 18:31:04 +00003393 SMLoc RLoc = Parser.getTok().getLoc();
3394 if (parseOptionalToken(AsmToken::RBrac))
3395 Operands.push_back(
3396 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3397 SMLoc ELoc = Parser.getTok().getLoc();
3398 if (parseOptionalToken(AsmToken::Exclaim))
3399 Operands.push_back(
3400 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003401
3402 ++N;
3403 }
3404 }
3405
Nirav Davee833c6c2016-11-08 18:31:04 +00003406 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3407 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003408
Tim Northover3b0846e2014-05-24 12:50:23 +00003409 return false;
3410}
3411
3412// FIXME: This entire function is a giant hack to provide us with decent
3413// operand range validation/diagnostics until TableGen/MC can be extended
3414// to support autogeneration of this kind of validation.
3415bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3416 SmallVectorImpl<SMLoc> &Loc) {
3417 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3418 // Check for indexed addressing modes w/ the base register being the
3419 // same as a destination/source register or pair load where
3420 // the Rt == Rt2. All of those are undefined behaviour.
3421 switch (Inst.getOpcode()) {
3422 case AArch64::LDPSWpre:
3423 case AArch64::LDPWpost:
3424 case AArch64::LDPWpre:
3425 case AArch64::LDPXpost:
3426 case AArch64::LDPXpre: {
3427 unsigned Rt = Inst.getOperand(1).getReg();
3428 unsigned Rt2 = Inst.getOperand(2).getReg();
3429 unsigned Rn = Inst.getOperand(3).getReg();
3430 if (RI->isSubRegisterEq(Rn, Rt))
3431 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3432 "is also a destination");
3433 if (RI->isSubRegisterEq(Rn, Rt2))
3434 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3435 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003436 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003437 }
3438 case AArch64::LDPDi:
3439 case AArch64::LDPQi:
3440 case AArch64::LDPSi:
3441 case AArch64::LDPSWi:
3442 case AArch64::LDPWi:
3443 case AArch64::LDPXi: {
3444 unsigned Rt = Inst.getOperand(0).getReg();
3445 unsigned Rt2 = Inst.getOperand(1).getReg();
3446 if (Rt == Rt2)
3447 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3448 break;
3449 }
3450 case AArch64::LDPDpost:
3451 case AArch64::LDPDpre:
3452 case AArch64::LDPQpost:
3453 case AArch64::LDPQpre:
3454 case AArch64::LDPSpost:
3455 case AArch64::LDPSpre:
3456 case AArch64::LDPSWpost: {
3457 unsigned Rt = Inst.getOperand(1).getReg();
3458 unsigned Rt2 = Inst.getOperand(2).getReg();
3459 if (Rt == Rt2)
3460 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3461 break;
3462 }
3463 case AArch64::STPDpost:
3464 case AArch64::STPDpre:
3465 case AArch64::STPQpost:
3466 case AArch64::STPQpre:
3467 case AArch64::STPSpost:
3468 case AArch64::STPSpre:
3469 case AArch64::STPWpost:
3470 case AArch64::STPWpre:
3471 case AArch64::STPXpost:
3472 case AArch64::STPXpre: {
3473 unsigned Rt = Inst.getOperand(1).getReg();
3474 unsigned Rt2 = Inst.getOperand(2).getReg();
3475 unsigned Rn = Inst.getOperand(3).getReg();
3476 if (RI->isSubRegisterEq(Rn, Rt))
3477 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3478 "is also a source");
3479 if (RI->isSubRegisterEq(Rn, Rt2))
3480 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3481 "is also a source");
3482 break;
3483 }
3484 case AArch64::LDRBBpre:
3485 case AArch64::LDRBpre:
3486 case AArch64::LDRHHpre:
3487 case AArch64::LDRHpre:
3488 case AArch64::LDRSBWpre:
3489 case AArch64::LDRSBXpre:
3490 case AArch64::LDRSHWpre:
3491 case AArch64::LDRSHXpre:
3492 case AArch64::LDRSWpre:
3493 case AArch64::LDRWpre:
3494 case AArch64::LDRXpre:
3495 case AArch64::LDRBBpost:
3496 case AArch64::LDRBpost:
3497 case AArch64::LDRHHpost:
3498 case AArch64::LDRHpost:
3499 case AArch64::LDRSBWpost:
3500 case AArch64::LDRSBXpost:
3501 case AArch64::LDRSHWpost:
3502 case AArch64::LDRSHXpost:
3503 case AArch64::LDRSWpost:
3504 case AArch64::LDRWpost:
3505 case AArch64::LDRXpost: {
3506 unsigned Rt = Inst.getOperand(1).getReg();
3507 unsigned Rn = Inst.getOperand(2).getReg();
3508 if (RI->isSubRegisterEq(Rn, Rt))
3509 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3510 "is also a source");
3511 break;
3512 }
3513 case AArch64::STRBBpost:
3514 case AArch64::STRBpost:
3515 case AArch64::STRHHpost:
3516 case AArch64::STRHpost:
3517 case AArch64::STRWpost:
3518 case AArch64::STRXpost:
3519 case AArch64::STRBBpre:
3520 case AArch64::STRBpre:
3521 case AArch64::STRHHpre:
3522 case AArch64::STRHpre:
3523 case AArch64::STRWpre:
3524 case AArch64::STRXpre: {
3525 unsigned Rt = Inst.getOperand(1).getReg();
3526 unsigned Rn = Inst.getOperand(2).getReg();
3527 if (RI->isSubRegisterEq(Rn, Rt))
3528 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3529 "is also a source");
3530 break;
3531 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003532 case AArch64::STXRB:
3533 case AArch64::STXRH:
3534 case AArch64::STXRW:
3535 case AArch64::STXRX:
3536 case AArch64::STLXRB:
3537 case AArch64::STLXRH:
3538 case AArch64::STLXRW:
3539 case AArch64::STLXRX: {
3540 unsigned Rs = Inst.getOperand(0).getReg();
3541 unsigned Rt = Inst.getOperand(1).getReg();
3542 unsigned Rn = Inst.getOperand(2).getReg();
3543 if (RI->isSubRegisterEq(Rt, Rs) ||
3544 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3545 return Error(Loc[0],
3546 "unpredictable STXR instruction, status is also a source");
3547 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003548 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003549 case AArch64::STXPW:
3550 case AArch64::STXPX:
3551 case AArch64::STLXPW:
3552 case AArch64::STLXPX: {
3553 unsigned Rs = Inst.getOperand(0).getReg();
3554 unsigned Rt1 = Inst.getOperand(1).getReg();
3555 unsigned Rt2 = Inst.getOperand(2).getReg();
3556 unsigned Rn = Inst.getOperand(3).getReg();
3557 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3558 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3559 return Error(Loc[0],
3560 "unpredictable STXP instruction, status is also a source");
3561 break;
3562 }
3563 }
3564
Tim Northover3b0846e2014-05-24 12:50:23 +00003565
3566 // Now check immediate ranges. Separate from the above as there is overlap
3567 // in the instructions being checked and this keeps the nested conditionals
3568 // to a minimum.
3569 switch (Inst.getOpcode()) {
3570 case AArch64::ADDSWri:
3571 case AArch64::ADDSXri:
3572 case AArch64::ADDWri:
3573 case AArch64::ADDXri:
3574 case AArch64::SUBSWri:
3575 case AArch64::SUBSXri:
3576 case AArch64::SUBWri:
3577 case AArch64::SUBXri: {
3578 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3579 // some slight duplication here.
3580 if (Inst.getOperand(2).isExpr()) {
3581 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3582 AArch64MCExpr::VariantKind ELFRefKind;
3583 MCSymbolRefExpr::VariantKind DarwinRefKind;
3584 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003585 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3586
3587 // Only allow these with ADDXri.
3588 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3589 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3590 Inst.getOpcode() == AArch64::ADDXri)
3591 return false;
3592
3593 // Only allow these with ADDXri/ADDWri
3594 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3595 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3596 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3597 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3598 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3599 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3600 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003601 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3602 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3603 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003604 (Inst.getOpcode() == AArch64::ADDXri ||
3605 Inst.getOpcode() == AArch64::ADDWri))
3606 return false;
3607
3608 // Don't allow symbol refs in the immediate field otherwise
3609 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3610 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3611 // 'cmp w0, 'borked')
3612 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003613 }
Diana Picusc93518d2016-10-11 09:17:47 +00003614 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003615 }
3616 return false;
3617 }
3618 default:
3619 return false;
3620 }
3621}
3622
Craig Topper05515562017-10-26 06:46:41 +00003623static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3624 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003625
3626bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3627 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003628 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003629 case Match_InvalidTiedOperand:
3630 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003631 case Match_MissingFeature:
3632 return Error(Loc,
3633 "instruction requires a CPU feature not currently enabled");
3634 case Match_InvalidOperand:
3635 return Error(Loc, "invalid operand for instruction");
3636 case Match_InvalidSuffix:
3637 return Error(Loc, "invalid type suffix for instruction");
3638 case Match_InvalidCondCode:
3639 return Error(Loc, "expected AArch64 condition code");
3640 case Match_AddSubRegExtendSmall:
3641 return Error(Loc,
3642 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3643 case Match_AddSubRegExtendLarge:
3644 return Error(Loc,
3645 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3646 case Match_AddSubSecondSource:
3647 return Error(Loc,
3648 "expected compatible register, symbol or integer in range [0, 4095]");
3649 case Match_LogicalSecondSource:
3650 return Error(Loc, "expected compatible register or logical immediate");
3651 case Match_InvalidMovImm32Shift:
3652 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3653 case Match_InvalidMovImm64Shift:
3654 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3655 case Match_AddSubRegShift32:
3656 return Error(Loc,
3657 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3658 case Match_AddSubRegShift64:
3659 return Error(Loc,
3660 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3661 case Match_InvalidFPImm:
3662 return Error(Loc,
3663 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003664 case Match_InvalidMemoryIndexedSImm6:
3665 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003666 case Match_InvalidMemoryIndexedSImm5:
3667 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003668 case Match_InvalidMemoryIndexed1SImm4:
3669 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003670 case Match_InvalidMemoryIndexed2SImm4:
3671 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003672 case Match_InvalidMemoryIndexed3SImm4:
3673 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003674 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00003675 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00003676 case Match_InvalidMemoryIndexed16SImm4:
3677 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00003678 case Match_InvalidMemoryIndexed1SImm6:
3679 return Error(Loc, "index must be an integer in range [-32, 31].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003680 case Match_InvalidMemoryIndexedSImm9:
3681 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00003682 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00003683 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003684 case Match_InvalidMemoryIndexed4SImm7:
3685 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3686 case Match_InvalidMemoryIndexed8SImm7:
3687 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3688 case Match_InvalidMemoryIndexed16SImm7:
3689 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00003690 case Match_InvalidMemoryIndexed8UImm5:
3691 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
3692 case Match_InvalidMemoryIndexed4UImm5:
3693 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
3694 case Match_InvalidMemoryIndexed2UImm5:
3695 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00003696 case Match_InvalidMemoryIndexed8UImm6:
3697 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
3698 case Match_InvalidMemoryIndexed4UImm6:
3699 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
3700 case Match_InvalidMemoryIndexed2UImm6:
3701 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
3702 case Match_InvalidMemoryIndexed1UImm6:
3703 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003704 case Match_InvalidMemoryWExtend8:
3705 return Error(Loc,
3706 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3707 case Match_InvalidMemoryWExtend16:
3708 return Error(Loc,
3709 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3710 case Match_InvalidMemoryWExtend32:
3711 return Error(Loc,
3712 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3713 case Match_InvalidMemoryWExtend64:
3714 return Error(Loc,
3715 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3716 case Match_InvalidMemoryWExtend128:
3717 return Error(Loc,
3718 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3719 case Match_InvalidMemoryXExtend8:
3720 return Error(Loc,
3721 "expected 'lsl' or 'sxtx' with optional shift of #0");
3722 case Match_InvalidMemoryXExtend16:
3723 return Error(Loc,
3724 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3725 case Match_InvalidMemoryXExtend32:
3726 return Error(Loc,
3727 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3728 case Match_InvalidMemoryXExtend64:
3729 return Error(Loc,
3730 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3731 case Match_InvalidMemoryXExtend128:
3732 return Error(Loc,
3733 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3734 case Match_InvalidMemoryIndexed1:
3735 return Error(Loc, "index must be an integer in range [0, 4095].");
3736 case Match_InvalidMemoryIndexed2:
3737 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3738 case Match_InvalidMemoryIndexed4:
3739 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3740 case Match_InvalidMemoryIndexed8:
3741 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3742 case Match_InvalidMemoryIndexed16:
3743 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003744 case Match_InvalidImm0_1:
3745 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003746 case Match_InvalidImm0_7:
3747 return Error(Loc, "immediate must be an integer in range [0, 7].");
3748 case Match_InvalidImm0_15:
3749 return Error(Loc, "immediate must be an integer in range [0, 15].");
3750 case Match_InvalidImm0_31:
3751 return Error(Loc, "immediate must be an integer in range [0, 31].");
3752 case Match_InvalidImm0_63:
3753 return Error(Loc, "immediate must be an integer in range [0, 63].");
3754 case Match_InvalidImm0_127:
3755 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003756 case Match_InvalidImm0_255:
3757 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003758 case Match_InvalidImm0_65535:
3759 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3760 case Match_InvalidImm1_8:
3761 return Error(Loc, "immediate must be an integer in range [1, 8].");
3762 case Match_InvalidImm1_16:
3763 return Error(Loc, "immediate must be an integer in range [1, 16].");
3764 case Match_InvalidImm1_32:
3765 return Error(Loc, "immediate must be an integer in range [1, 32].");
3766 case Match_InvalidImm1_64:
3767 return Error(Loc, "immediate must be an integer in range [1, 64].");
3768 case Match_InvalidIndex1:
3769 return Error(Loc, "expected lane specifier '[1]'");
3770 case Match_InvalidIndexB:
3771 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3772 case Match_InvalidIndexH:
3773 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3774 case Match_InvalidIndexS:
3775 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3776 case Match_InvalidIndexD:
3777 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3778 case Match_InvalidLabel:
3779 return Error(Loc, "expected label or encodable integer pc offset");
3780 case Match_MRS:
3781 return Error(Loc, "expected readable system register");
3782 case Match_MSR:
3783 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003784 case Match_InvalidComplexRotationEven:
3785 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3786 case Match_InvalidComplexRotationOdd:
3787 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003788 case Match_MnemonicFail: {
3789 std::string Suggestion = AArch64MnemonicSpellCheck(
3790 ((AArch64Operand &)*Operands[0]).getToken(),
3791 ComputeAvailableFeatures(STI->getFeatureBits()));
3792 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3793 }
Sander de Smalen367694b2018-04-20 08:54:49 +00003794 case Match_InvalidGPR64shifted8:
3795 return Error(Loc, "register must be x0..x30 or xzr, without shift");
3796 case Match_InvalidGPR64shifted16:
3797 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
3798 case Match_InvalidGPR64shifted32:
3799 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
3800 case Match_InvalidGPR64shifted64:
3801 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
3802 case Match_InvalidGPR64NoXZRshifted8:
3803 return Error(Loc, "register must be x0..x30 without shift");
3804 case Match_InvalidGPR64NoXZRshifted16:
3805 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
3806 case Match_InvalidGPR64NoXZRshifted32:
3807 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
3808 case Match_InvalidGPR64NoXZRshifted64:
3809 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00003810 case Match_InvalidZPR32UXTW8:
3811 case Match_InvalidZPR32SXTW8:
3812 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
3813 case Match_InvalidZPR32UXTW16:
3814 case Match_InvalidZPR32SXTW16:
3815 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
3816 case Match_InvalidZPR32UXTW32:
3817 case Match_InvalidZPR32SXTW32:
3818 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
3819 case Match_InvalidZPR32UXTW64:
3820 case Match_InvalidZPR32SXTW64:
3821 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
3822 case Match_InvalidZPR64UXTW8:
3823 case Match_InvalidZPR64SXTW8:
3824 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
3825 case Match_InvalidZPR64UXTW16:
3826 case Match_InvalidZPR64SXTW16:
3827 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
3828 case Match_InvalidZPR64UXTW32:
3829 case Match_InvalidZPR64SXTW32:
3830 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
3831 case Match_InvalidZPR64UXTW64:
3832 case Match_InvalidZPR64SXTW64:
3833 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
3834 case Match_InvalidZPR64LSL8:
3835 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
3836 case Match_InvalidZPR64LSL16:
3837 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
3838 case Match_InvalidZPR64LSL32:
3839 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
3840 case Match_InvalidZPR64LSL64:
3841 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00003842 case Match_InvalidZPR0:
3843 return Error(Loc, "expected register without element width sufix");
3844 case Match_InvalidZPR8:
3845 case Match_InvalidZPR16:
3846 case Match_InvalidZPR32:
3847 case Match_InvalidZPR64:
3848 case Match_InvalidZPR128:
3849 return Error(Loc, "invalid element width");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003850 case Match_InvalidSVEPattern:
3851 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003852 case Match_InvalidSVEPredicateAnyReg:
3853 case Match_InvalidSVEPredicateBReg:
3854 case Match_InvalidSVEPredicateHReg:
3855 case Match_InvalidSVEPredicateSReg:
3856 case Match_InvalidSVEPredicateDReg:
3857 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003858 case Match_InvalidSVEPredicate3bAnyReg:
3859 case Match_InvalidSVEPredicate3bBReg:
3860 case Match_InvalidSVEPredicate3bHReg:
3861 case Match_InvalidSVEPredicate3bSReg:
3862 case Match_InvalidSVEPredicate3bDReg:
3863 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003864 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003865 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003866 }
3867}
3868
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003869static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003870
3871bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3872 OperandVector &Operands,
3873 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003874 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003875 bool MatchingInlineAsm) {
3876 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003877 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3878 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003879
David Blaikie960ea3f2014-06-08 16:18:35 +00003880 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003881 unsigned NumOperands = Operands.size();
3882
3883 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003884 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3885 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003886 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003887 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003888 if (Op3CE) {
3889 uint64_t Op3Val = Op3CE->getValue();
3890 uint64_t NewOp3Val = 0;
3891 uint64_t NewOp4Val = 0;
3892 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003893 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003894 NewOp3Val = (32 - Op3Val) & 0x1f;
3895 NewOp4Val = 31 - Op3Val;
3896 } else {
3897 NewOp3Val = (64 - Op3Val) & 0x3f;
3898 NewOp4Val = 63 - Op3Val;
3899 }
3900
Jim Grosbach13760bd2015-05-30 01:25:56 +00003901 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3902 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003903
3904 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003905 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003906 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003907 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3908 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3909 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003910 }
3911 }
Tim Northover03b99f62015-04-30 18:28:58 +00003912 } else if (NumOperands == 4 && Tok == "bfc") {
3913 // FIXME: Horrible hack to handle BFC->BFM alias.
3914 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3915 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3916 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3917
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003918 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003919 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3920 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3921
3922 if (LSBCE && WidthCE) {
3923 uint64_t LSB = LSBCE->getValue();
3924 uint64_t Width = WidthCE->getValue();
3925
3926 uint64_t RegWidth = 0;
3927 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3928 Op1.getReg()))
3929 RegWidth = 64;
3930 else
3931 RegWidth = 32;
3932
3933 if (LSB >= RegWidth)
3934 return Error(LSBOp.getStartLoc(),
3935 "expected integer in range [0, 31]");
3936 if (Width < 1 || Width > RegWidth)
3937 return Error(WidthOp.getStartLoc(),
3938 "expected integer in range [1, 32]");
3939
3940 uint64_t ImmR = 0;
3941 if (RegWidth == 32)
3942 ImmR = (32 - LSB) & 0x1f;
3943 else
3944 ImmR = (64 - LSB) & 0x3f;
3945
3946 uint64_t ImmS = Width - 1;
3947
3948 if (ImmR != 0 && ImmS >= ImmR)
3949 return Error(WidthOp.getStartLoc(),
3950 "requested insert overflows register");
3951
Jim Grosbach13760bd2015-05-30 01:25:56 +00003952 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3953 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003954 Operands[0] = AArch64Operand::CreateToken(
3955 "bfm", false, Op.getStartLoc(), getContext());
3956 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003957 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3958 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003959 Operands[3] = AArch64Operand::CreateImm(
3960 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3961 Operands.emplace_back(
3962 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3963 WidthOp.getEndLoc(), getContext()));
3964 }
3965 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003966 } else if (NumOperands == 5) {
3967 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3968 // UBFIZ -> UBFM aliases.
3969 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003970 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3971 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3972 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003973
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003974 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003975 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3976 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003977
3978 if (Op3CE && Op4CE) {
3979 uint64_t Op3Val = Op3CE->getValue();
3980 uint64_t Op4Val = Op4CE->getValue();
3981
3982 uint64_t RegWidth = 0;
3983 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003984 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003985 RegWidth = 64;
3986 else
3987 RegWidth = 32;
3988
3989 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003990 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003991 "expected integer in range [0, 31]");
3992 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003993 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003994 "expected integer in range [1, 32]");
3995
3996 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003997 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003998 NewOp3Val = (32 - Op3Val) & 0x1f;
3999 else
4000 NewOp3Val = (64 - Op3Val) & 0x3f;
4001
4002 uint64_t NewOp4Val = Op4Val - 1;
4003
4004 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004005 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004006 "requested insert overflows register");
4007
4008 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004009 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004010 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004011 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004012 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004013 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004014 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004015 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004016 if (Tok == "bfi")
4017 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004018 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004019 else if (Tok == "sbfiz")
4020 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004021 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004022 else if (Tok == "ubfiz")
4023 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004024 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004025 else
4026 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004027 }
4028 }
4029
4030 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4031 // UBFX -> UBFM aliases.
4032 } else if (NumOperands == 5 &&
4033 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004034 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4035 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4036 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004037
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004038 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004039 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4040 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004041
4042 if (Op3CE && Op4CE) {
4043 uint64_t Op3Val = Op3CE->getValue();
4044 uint64_t Op4Val = Op4CE->getValue();
4045
4046 uint64_t RegWidth = 0;
4047 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004048 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004049 RegWidth = 64;
4050 else
4051 RegWidth = 32;
4052
4053 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004054 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004055 "expected integer in range [0, 31]");
4056 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004057 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004058 "expected integer in range [1, 32]");
4059
4060 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4061
4062 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004063 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004064 "requested extract overflows register");
4065
4066 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004067 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004068 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004069 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004070 if (Tok == "bfxil")
4071 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004072 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004073 else if (Tok == "sbfx")
4074 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004075 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004076 else if (Tok == "ubfx")
4077 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004078 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004079 else
4080 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004081 }
4082 }
4083 }
4084 }
Tim Northover9097a072017-12-18 10:36:00 +00004085
4086 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4087 // instruction for FP registers correctly in some rare circumstances. Convert
4088 // it to a safe instruction and warn (because silently changing someone's
4089 // assembly is rude).
4090 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4091 NumOperands == 4 && Tok == "movi") {
4092 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4093 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4094 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4095 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4096 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4097 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4098 if (Suffix.lower() == ".2d" &&
4099 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4100 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4101 " correctly on this CPU, converting to equivalent movi.16b");
4102 // Switch the suffix to .16b.
4103 unsigned Idx = Op1.isToken() ? 1 : 2;
4104 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4105 getContext());
4106 }
4107 }
4108 }
4109
Tim Northover3b0846e2014-05-24 12:50:23 +00004110 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4111 // InstAlias can't quite handle this since the reg classes aren't
4112 // subclasses.
4113 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4114 // The source register can be Wn here, but the matcher expects a
4115 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004116 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004117 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004118 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004119 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4120 Op.getStartLoc(), Op.getEndLoc(),
4121 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004122 }
4123 }
4124 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4125 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004126 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004127 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004128 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004129 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004130 // The source register can be Wn here, but the matcher expects a
4131 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004132 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004133 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004134 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004135 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4136 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004137 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004138 }
4139 }
4140 }
4141 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4142 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004143 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004144 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004145 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004146 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004147 // The source register can be Wn here, but the matcher expects a
4148 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004149 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004150 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004151 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004152 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4153 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004154 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004155 }
4156 }
4157 }
4158
Tim Northover3b0846e2014-05-24 12:50:23 +00004159 MCInst Inst;
4160 // First try to match against the secondary set of tables containing the
4161 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4162 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004163 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004164
4165 // If that fails, try against the alternate table containing long-form NEON:
4166 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004167 if (MatchResult != Match_Success) {
4168 // But first, save the short-form match result: we can use it in case the
4169 // long-form match also fails.
4170 auto ShortFormNEONErrorInfo = ErrorInfo;
4171 auto ShortFormNEONMatchResult = MatchResult;
4172
Tim Northover3b0846e2014-05-24 12:50:23 +00004173 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004174 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004175
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004176 // Now, both matches failed, and the long-form match failed on the mnemonic
4177 // suffix token operand. The short-form match failure is probably more
4178 // relevant: use it instead.
4179 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004180 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004181 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4182 MatchResult = ShortFormNEONMatchResult;
4183 ErrorInfo = ShortFormNEONErrorInfo;
4184 }
4185 }
4186
Tim Northover3b0846e2014-05-24 12:50:23 +00004187 switch (MatchResult) {
4188 case Match_Success: {
4189 // Perform range checking and other semantic validations
4190 SmallVector<SMLoc, 8> OperandLocs;
4191 NumOperands = Operands.size();
4192 for (unsigned i = 1; i < NumOperands; ++i)
4193 OperandLocs.push_back(Operands[i]->getStartLoc());
4194 if (validateInstruction(Inst, OperandLocs))
4195 return true;
4196
4197 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004198 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004199 return false;
4200 }
4201 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004202 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004203 // Special case the error message for the very common case where only
4204 // a single subtarget feature is missing (neon, e.g.).
4205 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004206 uint64_t Mask = 1;
4207 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4208 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004209 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004210 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004211 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004212 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004213 }
4214 return Error(IDLoc, Msg);
4215 }
4216 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004217 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004218 case Match_InvalidOperand: {
4219 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004220
Tim Northover26bb14e2014-08-18 11:49:42 +00004221 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004222 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004223 return Error(IDLoc, "too few operands for instruction",
4224 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004225
David Blaikie960ea3f2014-06-08 16:18:35 +00004226 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004227 if (ErrorLoc == SMLoc())
4228 ErrorLoc = IDLoc;
4229 }
4230 // If the match failed on a suffix token operand, tweak the diagnostic
4231 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004232 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4233 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004234 MatchResult = Match_InvalidSuffix;
4235
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004236 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004237 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004238 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004239 case Match_InvalidMemoryIndexed1:
4240 case Match_InvalidMemoryIndexed2:
4241 case Match_InvalidMemoryIndexed4:
4242 case Match_InvalidMemoryIndexed8:
4243 case Match_InvalidMemoryIndexed16:
4244 case Match_InvalidCondCode:
4245 case Match_AddSubRegExtendSmall:
4246 case Match_AddSubRegExtendLarge:
4247 case Match_AddSubSecondSource:
4248 case Match_LogicalSecondSource:
4249 case Match_AddSubRegShift32:
4250 case Match_AddSubRegShift64:
4251 case Match_InvalidMovImm32Shift:
4252 case Match_InvalidMovImm64Shift:
4253 case Match_InvalidFPImm:
4254 case Match_InvalidMemoryWExtend8:
4255 case Match_InvalidMemoryWExtend16:
4256 case Match_InvalidMemoryWExtend32:
4257 case Match_InvalidMemoryWExtend64:
4258 case Match_InvalidMemoryWExtend128:
4259 case Match_InvalidMemoryXExtend8:
4260 case Match_InvalidMemoryXExtend16:
4261 case Match_InvalidMemoryXExtend32:
4262 case Match_InvalidMemoryXExtend64:
4263 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004264 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004265 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004266 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004267 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004268 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004269 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004270 case Match_InvalidMemoryIndexed4SImm7:
4271 case Match_InvalidMemoryIndexed8SImm7:
4272 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004273 case Match_InvalidMemoryIndexed8UImm5:
4274 case Match_InvalidMemoryIndexed4UImm5:
4275 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004276 case Match_InvalidMemoryIndexed1UImm6:
4277 case Match_InvalidMemoryIndexed2UImm6:
4278 case Match_InvalidMemoryIndexed4UImm6:
4279 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004280 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004281 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004282 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004283 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004284 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004285 case Match_InvalidImm0_7:
4286 case Match_InvalidImm0_15:
4287 case Match_InvalidImm0_31:
4288 case Match_InvalidImm0_63:
4289 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004290 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004291 case Match_InvalidImm0_65535:
4292 case Match_InvalidImm1_8:
4293 case Match_InvalidImm1_16:
4294 case Match_InvalidImm1_32:
4295 case Match_InvalidImm1_64:
4296 case Match_InvalidIndex1:
4297 case Match_InvalidIndexB:
4298 case Match_InvalidIndexH:
4299 case Match_InvalidIndexS:
4300 case Match_InvalidIndexD:
4301 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004302 case Match_InvalidComplexRotationEven:
4303 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004304 case Match_InvalidGPR64shifted8:
4305 case Match_InvalidGPR64shifted16:
4306 case Match_InvalidGPR64shifted32:
4307 case Match_InvalidGPR64shifted64:
4308 case Match_InvalidGPR64NoXZRshifted8:
4309 case Match_InvalidGPR64NoXZRshifted16:
4310 case Match_InvalidGPR64NoXZRshifted32:
4311 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004312 case Match_InvalidZPR32UXTW8:
4313 case Match_InvalidZPR32UXTW16:
4314 case Match_InvalidZPR32UXTW32:
4315 case Match_InvalidZPR32UXTW64:
4316 case Match_InvalidZPR32SXTW8:
4317 case Match_InvalidZPR32SXTW16:
4318 case Match_InvalidZPR32SXTW32:
4319 case Match_InvalidZPR32SXTW64:
4320 case Match_InvalidZPR64UXTW8:
4321 case Match_InvalidZPR64SXTW8:
4322 case Match_InvalidZPR64UXTW16:
4323 case Match_InvalidZPR64SXTW16:
4324 case Match_InvalidZPR64UXTW32:
4325 case Match_InvalidZPR64SXTW32:
4326 case Match_InvalidZPR64UXTW64:
4327 case Match_InvalidZPR64SXTW64:
4328 case Match_InvalidZPR64LSL8:
4329 case Match_InvalidZPR64LSL16:
4330 case Match_InvalidZPR64LSL32:
4331 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004332 case Match_InvalidZPR0:
4333 case Match_InvalidZPR8:
4334 case Match_InvalidZPR16:
4335 case Match_InvalidZPR32:
4336 case Match_InvalidZPR64:
4337 case Match_InvalidZPR128:
Sander de Smalencd6be962017-12-20 11:02:42 +00004338 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004339 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004340 case Match_InvalidSVEPredicateBReg:
4341 case Match_InvalidSVEPredicateHReg:
4342 case Match_InvalidSVEPredicateSReg:
4343 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004344 case Match_InvalidSVEPredicate3bAnyReg:
4345 case Match_InvalidSVEPredicate3bBReg:
4346 case Match_InvalidSVEPredicate3bHReg:
4347 case Match_InvalidSVEPredicate3bSReg:
4348 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004349 case Match_MSR:
4350 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004351 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004352 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004353 // Any time we get here, there's nothing fancy to do. Just get the
4354 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004355 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004356 if (ErrorLoc == SMLoc())
4357 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004358 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004359 }
4360 }
4361
4362 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004363}
4364
4365/// ParseDirective parses the arm specific directives
4366bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004367 const MCObjectFileInfo::Environment Format =
4368 getContext().getObjectFileInfo()->getObjectFileType();
4369 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4370 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004371
Tim Northover3b0846e2014-05-24 12:50:23 +00004372 StringRef IDVal = DirectiveID.getIdentifier();
4373 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004374 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004375 parseDirectiveArch(Loc);
4376 else if (IDVal == ".cpu")
4377 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00004378 else if (IDVal == ".tlsdesccall")
4379 parseDirectiveTLSDescCall(Loc);
4380 else if (IDVal == ".ltorg" || IDVal == ".pool")
4381 parseDirectiveLtorg(Loc);
4382 else if (IDVal == ".unreq")
4383 parseDirectiveUnreq(Loc);
4384 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004385 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004386 parseDirectiveInst(Loc);
4387 else
4388 return true;
4389 } else if (IDVal == MCLOHDirectiveName())
4390 parseDirectiveLOH(IDVal, Loc);
4391 else
4392 return true;
4393 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004394}
4395
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004396static const struct {
4397 const char *Name;
4398 const FeatureBitset Features;
4399} ExtensionMap[] = {
4400 { "crc", {AArch64::FeatureCRC} },
4401 { "crypto", {AArch64::FeatureCrypto} },
4402 { "fp", {AArch64::FeatureFPARMv8} },
4403 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004404 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004405 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004406
4407 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004408 { "pan", {} },
4409 { "lor", {} },
4410 { "rdma", {} },
4411 { "profile", {} },
4412};
4413
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004414/// parseDirectiveArch
4415/// ::= .arch token
4416bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4417 SMLoc ArchLoc = getLoc();
4418
4419 StringRef Arch, ExtensionString;
4420 std::tie(Arch, ExtensionString) =
4421 getParser().parseStringToEndOfStatement().trim().split('+');
4422
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004423 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4424 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004425 return Error(ArchLoc, "unknown arch name");
4426
4427 if (parseToken(AsmToken::EndOfStatement))
4428 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004429
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004430 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004431 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004432 AArch64::getArchFeatures(ID, AArch64Features);
4433 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4434 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004435
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004436 MCSubtargetInfo &STI = copySTI();
4437 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4438 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4439
4440 SmallVector<StringRef, 4> RequestedExtensions;
4441 if (!ExtensionString.empty())
4442 ExtensionString.split(RequestedExtensions, '+');
4443
4444 FeatureBitset Features = STI.getFeatureBits();
4445 for (auto Name : RequestedExtensions) {
4446 bool EnableFeature = true;
4447
4448 if (Name.startswith_lower("no")) {
4449 EnableFeature = false;
4450 Name = Name.substr(2);
4451 }
4452
4453 for (const auto &Extension : ExtensionMap) {
4454 if (Extension.Name != Name)
4455 continue;
4456
4457 if (Extension.Features.none())
4458 report_fatal_error("unsupported architectural extension: " + Name);
4459
4460 FeatureBitset ToggleFeatures = EnableFeature
4461 ? (~Features & Extension.Features)
4462 : ( Features & Extension.Features);
4463 uint64_t Features =
4464 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4465 setAvailableFeatures(Features);
4466 break;
4467 }
4468 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004469 return false;
4470}
4471
Tim Northover8b96c7e2017-05-15 19:42:15 +00004472static SMLoc incrementLoc(SMLoc L, int Offset) {
4473 return SMLoc::getFromPointer(L.getPointer() + Offset);
4474}
4475
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004476/// parseDirectiveCPU
4477/// ::= .cpu id
4478bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004479 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004480
4481 StringRef CPU, ExtensionString;
4482 std::tie(CPU, ExtensionString) =
4483 getParser().parseStringToEndOfStatement().trim().split('+');
4484
Nirav Davee833c6c2016-11-08 18:31:04 +00004485 if (parseToken(AsmToken::EndOfStatement))
4486 return true;
4487
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004488 SmallVector<StringRef, 4> RequestedExtensions;
4489 if (!ExtensionString.empty())
4490 ExtensionString.split(RequestedExtensions, '+');
4491
4492 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4493 // once that is tablegen'ed
4494 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004495 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004496 return false;
4497 }
4498
4499 MCSubtargetInfo &STI = copySTI();
4500 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004501 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004502
4503 FeatureBitset Features = STI.getFeatureBits();
4504 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004505 // Advance source location past '+'.
4506 CurLoc = incrementLoc(CurLoc, 1);
4507
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004508 bool EnableFeature = true;
4509
4510 if (Name.startswith_lower("no")) {
4511 EnableFeature = false;
4512 Name = Name.substr(2);
4513 }
4514
Tim Northover8b96c7e2017-05-15 19:42:15 +00004515 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004516 for (const auto &Extension : ExtensionMap) {
4517 if (Extension.Name != Name)
4518 continue;
4519
4520 if (Extension.Features.none())
4521 report_fatal_error("unsupported architectural extension: " + Name);
4522
4523 FeatureBitset ToggleFeatures = EnableFeature
4524 ? (~Features & Extension.Features)
4525 : ( Features & Extension.Features);
4526 uint64_t Features =
4527 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4528 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004529 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004530
4531 break;
4532 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004533
4534 if (!FoundExtension)
4535 Error(CurLoc, "unsupported architectural extension");
4536
4537 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004538 }
4539 return false;
4540}
4541
Chad Rosierdcd2a302014-10-22 20:35:57 +00004542/// parseDirectiveInst
4543/// ::= .inst opcode [, ...]
4544bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004545 if (getLexer().is(AsmToken::EndOfStatement))
4546 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004547
Nirav Davee833c6c2016-11-08 18:31:04 +00004548 auto parseOp = [&]() -> bool {
4549 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004550 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004551 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4552 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004553 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004554 if (check(!Value, L, "expected constant expression"))
4555 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004556 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004557 return false;
4558 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004559
Nirav Davee833c6c2016-11-08 18:31:04 +00004560 if (parseMany(parseOp))
4561 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004562 return false;
4563}
4564
Tim Northover3b0846e2014-05-24 12:50:23 +00004565// parseDirectiveTLSDescCall:
4566// ::= .tlsdesccall symbol
4567bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4568 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004569 if (check(getParser().parseIdentifier(Name), L,
4570 "expected symbol after directive") ||
4571 parseToken(AsmToken::EndOfStatement))
4572 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004573
Jim Grosbach6f482002015-05-18 18:43:14 +00004574 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004575 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4576 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004577
4578 MCInst Inst;
4579 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004580 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004581
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004582 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004583 return false;
4584}
4585
4586/// ::= .loh <lohName | lohId> label1, ..., labelN
4587/// The number of arguments depends on the loh identifier.
4588bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004589 MCLOHType Kind;
4590 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4591 if (getParser().getTok().isNot(AsmToken::Integer))
4592 return TokError("expected an identifier or a number in directive");
4593 // We successfully get a numeric value for the identifier.
4594 // Check if it is valid.
4595 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004596 if (Id <= -1U && !isValidMCLOHType(Id))
4597 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004598 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004599 } else {
4600 StringRef Name = getTok().getIdentifier();
4601 // We successfully parse an identifier.
4602 // Check if it is a recognized one.
4603 int Id = MCLOHNameToId(Name);
4604
4605 if (Id == -1)
4606 return TokError("invalid identifier in directive");
4607 Kind = (MCLOHType)Id;
4608 }
4609 // Consume the identifier.
4610 Lex();
4611 // Get the number of arguments of this LOH.
4612 int NbArgs = MCLOHIdToNbArgs(Kind);
4613
4614 assert(NbArgs != -1 && "Invalid number of arguments");
4615
4616 SmallVector<MCSymbol *, 3> Args;
4617 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4618 StringRef Name;
4619 if (getParser().parseIdentifier(Name))
4620 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004621 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004622
4623 if (Idx + 1 == NbArgs)
4624 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004625 if (parseToken(AsmToken::Comma,
4626 "unexpected token in '" + Twine(IDVal) + "' directive"))
4627 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004628 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004629 if (parseToken(AsmToken::EndOfStatement,
4630 "unexpected token in '" + Twine(IDVal) + "' directive"))
4631 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004632
4633 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4634 return false;
4635}
4636
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004637/// parseDirectiveLtorg
4638/// ::= .ltorg | .pool
4639bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004640 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4641 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004642 getTargetStreamer().emitCurrentConstantPool();
4643 return false;
4644}
4645
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004646/// parseDirectiveReq
4647/// ::= name .req registername
4648bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004649 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004650 Parser.Lex(); // Eat the '.req' token.
4651 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004652 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004653 unsigned RegNum;
4654 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004655
Sander de Smalen50d87022018-04-19 07:35:08 +00004656 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004657 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004658 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004659 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004660
Sander de Smalen50d87022018-04-19 07:35:08 +00004661 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004662 return true;
4663
Sander de Smalen50d87022018-04-19 07:35:08 +00004664 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004665 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004666 }
4667
Sander de Smalen50d87022018-04-19 07:35:08 +00004668 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004669 StringRef Kind;
4670 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004671 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004672 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004673
Sander de Smalen50d87022018-04-19 07:35:08 +00004674 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004675 return true;
4676
Sander de Smalen50d87022018-04-19 07:35:08 +00004677 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004678 return Error(SRegLoc,
4679 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004680 }
4681
Sander de Smalen50d87022018-04-19 07:35:08 +00004682 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00004683 StringRef Kind;
4684 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004685 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004686
Sander de Smalen50d87022018-04-19 07:35:08 +00004687 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00004688 return true;
4689
Sander de Smalen50d87022018-04-19 07:35:08 +00004690 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00004691 return Error(SRegLoc,
4692 "sve predicate register without type specifier expected");
4693 }
4694
Sander de Smalen50d87022018-04-19 07:35:08 +00004695 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00004696 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004697
4698 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004699 if (parseToken(AsmToken::EndOfStatement,
4700 "unexpected input in .req directive"))
4701 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004702
Sander de Smalen8e607342017-11-15 15:44:43 +00004703 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004704 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004705 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4706
Nirav Dave2364748a2016-09-16 18:30:20 +00004707 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004708}
4709
4710/// parseDirectiveUneq
4711/// ::= .unreq registername
4712bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004713 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004714 if (getTok().isNot(AsmToken::Identifier))
4715 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004716 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4717 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004718 if (parseToken(AsmToken::EndOfStatement))
4719 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004720 return false;
4721}
4722
Tim Northover3b0846e2014-05-24 12:50:23 +00004723bool
4724AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4725 AArch64MCExpr::VariantKind &ELFRefKind,
4726 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4727 int64_t &Addend) {
4728 ELFRefKind = AArch64MCExpr::VK_INVALID;
4729 DarwinRefKind = MCSymbolRefExpr::VK_None;
4730 Addend = 0;
4731
4732 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4733 ELFRefKind = AE->getKind();
4734 Expr = AE->getSubExpr();
4735 }
4736
4737 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4738 if (SE) {
4739 // It's a simple symbol reference with no addend.
4740 DarwinRefKind = SE->getKind();
4741 return true;
4742 }
4743
4744 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4745 if (!BE)
4746 return false;
4747
4748 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4749 if (!SE)
4750 return false;
4751 DarwinRefKind = SE->getKind();
4752
4753 if (BE->getOpcode() != MCBinaryExpr::Add &&
4754 BE->getOpcode() != MCBinaryExpr::Sub)
4755 return false;
4756
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004757 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004758 // on here than we can deal with.
4759 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4760 if (!AddendExpr)
4761 return false;
4762
4763 Addend = AddendExpr->getValue();
4764 if (BE->getOpcode() == MCBinaryExpr::Sub)
4765 Addend = -Addend;
4766
4767 // It's some symbol reference + a constant addend, but really
4768 // shouldn't use both Darwin and ELF syntax.
4769 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4770 DarwinRefKind == MCSymbolRefExpr::VK_None;
4771}
4772
4773/// Force static initialization.
4774extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004775 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4776 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4777 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004778}
4779
4780#define GET_REGISTER_MATCHER
4781#define GET_SUBTARGET_FEATURE_NAME
4782#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004783#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004784#include "AArch64GenAsmMatcher.inc"
4785
4786// Define this matcher function after the auto-generated include so we
4787// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004788unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004789 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004790 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004791 // If the kind is a token for a literal immediate, check if our asm
4792 // operand matches. This is for InstAliases which have a fixed-value
4793 // immediate in the syntax.
4794 int64_t ExpectedVal;
4795 switch (Kind) {
4796 default:
4797 return Match_InvalidOperand;
4798 case MCK__35_0:
4799 ExpectedVal = 0;
4800 break;
4801 case MCK__35_1:
4802 ExpectedVal = 1;
4803 break;
4804 case MCK__35_12:
4805 ExpectedVal = 12;
4806 break;
4807 case MCK__35_16:
4808 ExpectedVal = 16;
4809 break;
4810 case MCK__35_2:
4811 ExpectedVal = 2;
4812 break;
4813 case MCK__35_24:
4814 ExpectedVal = 24;
4815 break;
4816 case MCK__35_3:
4817 ExpectedVal = 3;
4818 break;
4819 case MCK__35_32:
4820 ExpectedVal = 32;
4821 break;
4822 case MCK__35_4:
4823 ExpectedVal = 4;
4824 break;
4825 case MCK__35_48:
4826 ExpectedVal = 48;
4827 break;
4828 case MCK__35_6:
4829 ExpectedVal = 6;
4830 break;
4831 case MCK__35_64:
4832 ExpectedVal = 64;
4833 break;
4834 case MCK__35_8:
4835 ExpectedVal = 8;
4836 break;
4837 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004838 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004839 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004840 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004841 if (!CE)
4842 return Match_InvalidOperand;
4843 if (CE->getValue() == ExpectedVal)
4844 return Match_Success;
4845 return Match_InvalidOperand;
4846}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004847
Alex Bradbury58eba092016-11-01 16:32:05 +00004848OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004849AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4850
4851 SMLoc S = getLoc();
4852
4853 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4854 Error(S, "expected register");
4855 return MatchOperand_ParseFail;
4856 }
4857
Sander de Smalen50d87022018-04-19 07:35:08 +00004858 unsigned FirstReg;
4859 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
4860 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004861 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00004862
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004863 const MCRegisterClass &WRegClass =
4864 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4865 const MCRegisterClass &XRegClass =
4866 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4867
4868 bool isXReg = XRegClass.contains(FirstReg),
4869 isWReg = WRegClass.contains(FirstReg);
4870 if (!isXReg && !isWReg) {
4871 Error(S, "expected first even register of a "
4872 "consecutive same-size even/odd register pair");
4873 return MatchOperand_ParseFail;
4874 }
4875
4876 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4877 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4878
4879 if (FirstEncoding & 0x1) {
4880 Error(S, "expected first even register of a "
4881 "consecutive same-size even/odd register pair");
4882 return MatchOperand_ParseFail;
4883 }
4884
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004885 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00004886 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004887 return MatchOperand_ParseFail;
4888 }
4889 // Eat the comma
4890 getParser().Lex();
4891
4892 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00004893 unsigned SecondReg;
4894 Res = tryParseScalarRegister(SecondReg);
4895 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004896 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004897
Eugene Zelenko049b0172017-01-06 00:30:53 +00004898 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004899 (isXReg && !XRegClass.contains(SecondReg)) ||
4900 (isWReg && !WRegClass.contains(SecondReg))) {
4901 Error(E,"expected second odd register of a "
4902 "consecutive same-size even/odd register pair");
4903 return MatchOperand_ParseFail;
4904 }
Joel Jones504bf332016-10-24 13:37:13 +00004905
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004906 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004907 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004908 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4909 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4910 } else {
4911 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4912 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4913 }
4914
Florian Hahnc4422242017-11-07 13:07:50 +00004915 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4916 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004917
4918 return MatchOperand_Success;
4919}
Florian Hahn91f11e52017-11-07 16:45:48 +00004920
Sander de Smaleneb896b12018-04-25 09:26:47 +00004921template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00004922OperandMatchResultTy
4923AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004924 const SMLoc S = getLoc();
4925 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00004926 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00004927 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004928
Sander de Smalen8e607342017-11-15 15:44:43 +00004929 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004930 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004931
4932 if (Res != MatchOperand_Success)
4933 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004934
4935 if (ParseSuffix && Kind.empty())
4936 return MatchOperand_NoMatch;
4937
Sander de Smalen73937b72018-04-11 07:36:10 +00004938 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
4939 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00004940 return MatchOperand_NoMatch;
4941
Sander de Smalen73937b72018-04-11 07:36:10 +00004942 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00004943
4944 // No shift/extend is the default.
4945 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
4946 Operands.push_back(AArch64Operand::CreateVectorReg(
4947 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
4948
4949 return MatchOperand_Success;
4950 }
4951
4952 // Eat the comma
4953 getParser().Lex();
4954
4955 // Match the shift
4956 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
4957 Res = tryParseOptionalShiftExtend(ExtOpnd);
4958 if (Res != MatchOperand_Success)
4959 return Res;
4960
4961 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00004962 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00004963 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
4964 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
4965 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00004966
4967 return MatchOperand_Success;
4968}
Sander de Smalen245e0e62018-01-22 10:46:00 +00004969
4970OperandMatchResultTy
4971AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
4972 MCAsmParser &Parser = getParser();
4973
4974 SMLoc SS = getLoc();
4975 const AsmToken &TokE = Parser.getTok();
4976 bool IsHash = TokE.is(AsmToken::Hash);
4977
4978 if (!IsHash && TokE.isNot(AsmToken::Identifier))
4979 return MatchOperand_NoMatch;
4980
4981 int64_t Pattern;
4982 if (IsHash) {
4983 Parser.Lex(); // Eat hash
4984
4985 // Parse the immediate operand.
4986 const MCExpr *ImmVal;
4987 SS = getLoc();
4988 if (Parser.parseExpression(ImmVal))
4989 return MatchOperand_ParseFail;
4990
4991 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4992 if (!MCE)
4993 return MatchOperand_ParseFail;
4994
4995 Pattern = MCE->getValue();
4996 } else {
4997 // Parse the pattern
4998 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
4999 if (!Pat)
5000 return MatchOperand_NoMatch;
5001
5002 Parser.Lex();
5003 Pattern = Pat->Encoding;
5004 assert(Pattern >= 0 && Pattern < 32);
5005 }
5006
5007 Operands.push_back(
5008 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5009 SS, getLoc(), getContext()));
5010
5011 return MatchOperand_Success;
5012}