blob: b6dd39c2a5d7da1e54134100388517482b8c1f67 [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/AArch64AddressingModes.h"
11#include "MCTargetDesc/AArch64MCExpr.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000012#include "MCTargetDesc/AArch64MCTargetDesc.h"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000013#include "MCTargetDesc/AArch64TargetStreamer.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000014#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000015#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000016#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000017#include "llvm/ADT/ArrayRef.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000018#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "llvm/ADT/SmallVector.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000020#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000021#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000023#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000025#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000028#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000029#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000030#include "llvm/MC/MCParser/MCAsmLexer.h"
31#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000032#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000033#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000034#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000035#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSubtargetInfo.h"
38#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000039#include "llvm/MC/MCTargetOptions.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000043#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000044#include "llvm/Support/MathExtras.h"
45#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000046#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000047#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000049#include <cassert>
50#include <cctype>
51#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000052#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000053#include <string>
54#include <tuple>
55#include <utility>
56#include <vector>
57
Tim Northover3b0846e2014-05-24 12:50:23 +000058using namespace llvm;
59
60namespace {
61
Sander de Smalencd6be962017-12-20 11:02:42 +000062enum class RegKind {
63 Scalar,
64 NeonVector,
65 SVEDataVector,
66 SVEPredicateVector
67};
Florian Hahnc4422242017-11-07 13:07:50 +000068
Tim Northover3b0846e2014-05-24 12:50:23 +000069class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000070private:
71 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000072
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000073 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000074 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000075
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000076 AArch64TargetStreamer &getTargetStreamer() {
77 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
78 return static_cast<AArch64TargetStreamer &>(TS);
79 }
80
Rafael Espindola961d4692014-11-11 05:18:41 +000081 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000082
83 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +000084 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +000085 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
86 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +000087 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +000088 bool parseRegister(OperandVector &Operands);
89 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
Sander de Smalenc88f9a12018-04-11 14:10:37 +000090 bool parseNeonVectorList(OperandVector &Operands);
Sander de Smalen5c625982018-04-13 12:56:14 +000091 bool parseOptionalMulVl(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000092 bool parseOperand(OperandVector &Operands, bool isCondCode,
93 bool invertCondCode);
94
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +000095 bool showMatchError(SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000096
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000097 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000098 bool parseDirectiveCPU(SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +000099 bool parseDirectiveInst(SMLoc L);
100
Tim Northover3b0846e2014-05-24 12:50:23 +0000101 bool parseDirectiveTLSDescCall(SMLoc L);
102
103 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000104 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000105
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000106 bool parseDirectiveReq(StringRef Name, SMLoc L);
107 bool parseDirectiveUnreq(SMLoc L);
108
Tim Northover3b0846e2014-05-24 12:50:23 +0000109 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
110 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
111 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000112 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000113 bool MatchingInlineAsm) override;
114/// @name Auto-generated Match Functions
115/// {
116
117#define GET_ASSEMBLER_HEADER
118#include "AArch64GenAsmMatcher.inc"
119
120 /// }
121
Sander de Smalen50d87022018-04-19 07:35:08 +0000122 OperandMatchResultTy tryParseScalarRegister(unsigned &Reg);
123 OperandMatchResultTy tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +0000124 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000125 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
126 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
127 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
128 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
129 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
Sander de Smalen93380372018-05-14 11:54:41 +0000130 template <bool IsSVEPrefetch = false>
Tim Northover3b0846e2014-05-24 12:50:23 +0000131 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000132 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000133 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
134 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
135 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
Sander de Smalen62770792018-05-25 09:47:52 +0000136 OperandMatchResultTy tryParseImmWithOptionalShift(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000137 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000138 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000139 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000140 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Sander de Smalen149916d2018-04-20 07:24:20 +0000141 template <bool ParseShiftExtend>
142 OperandMatchResultTy tryParseGPROperand(OperandVector &Operands);
Sander de Smaleneb896b12018-04-25 09:26:47 +0000143 template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +0000144 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000145 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000146 template <RegKind VectorKind>
147 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
148 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000149 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000150
151public:
152 enum AArch64MatchResultTy {
153 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
154#define GET_OPERAND_DIAGNOSTIC_TYPES
155#include "AArch64GenAsmMatcher.inc"
156 };
Joel Jones504bf332016-10-24 13:37:13 +0000157 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000158
Akira Hatanakab11ef082015-11-14 06:35:56 +0000159 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000160 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000161 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000162 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000163 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000164 MCStreamer &S = getParser().getStreamer();
165 if (S.getTargetStreamer() == nullptr)
166 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000167
Alex Bradbury0a59f182018-05-23 11:17:20 +0000168 // Alias .hword/.word/xword to the target-independent .2byte/.4byte/.8byte
169 // directives as they have the same form and semantics:
170 /// ::= (.hword | .word | .xword ) [ expression (, expression)* ]
171 Parser.addAliasForDirective(".hword", ".2byte");
172 Parser.addAliasForDirective(".word", ".4byte");
173 Parser.addAliasForDirective(".xword", ".8byte");
174
Tim Northover3b0846e2014-05-24 12:50:23 +0000175 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000176 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000177 }
178
179 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
180 SMLoc NameLoc, OperandVector &Operands) override;
181 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
182 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000183 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000184 unsigned Kind) override;
185
186 static bool classifySymbolRef(const MCExpr *Expr,
187 AArch64MCExpr::VariantKind &ELFRefKind,
188 MCSymbolRefExpr::VariantKind &DarwinRefKind,
189 int64_t &Addend);
190};
Tim Northover3b0846e2014-05-24 12:50:23 +0000191
192/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
193/// instruction.
194class AArch64Operand : public MCParsedAsmOperand {
195private:
196 enum KindTy {
197 k_Immediate,
198 k_ShiftedImm,
199 k_CondCode,
200 k_Register,
201 k_VectorList,
202 k_VectorIndex,
203 k_Token,
204 k_SysReg,
205 k_SysCR,
206 k_Prefetch,
207 k_ShiftExtend,
208 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000209 k_Barrier,
210 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000211 } Kind;
212
213 SMLoc StartLoc, EndLoc;
214
215 struct TokOp {
216 const char *Data;
217 unsigned Length;
218 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
219 };
220
Sander de Smalen149916d2018-04-20 07:24:20 +0000221 // Separate shift/extend operand.
222 struct ShiftExtendOp {
223 AArch64_AM::ShiftExtendType Type;
224 unsigned Amount;
225 bool HasExplicitAmount;
226 };
227
Tim Northover3b0846e2014-05-24 12:50:23 +0000228 struct RegOp {
229 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000230 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000231 int ElementWidth;
Sander de Smalen149916d2018-04-20 07:24:20 +0000232
233 // In some cases the shift/extend needs to be explicitly parsed together
234 // with the register, rather than as a separate operand. This is needed
235 // for addressing modes where the instruction as a whole dictates the
236 // scaling/extend, rather than specific bits in the instruction.
237 // By parsing them as a single operand, we avoid the need to pass an
238 // extra operand in all CodeGen patterns (because all operands need to
239 // have an associated value), and we avoid the need to update TableGen to
240 // accept operands that have no associated bits in the instruction.
241 //
242 // An added benefit of parsing them together is that the assembler
243 // can give a sensible diagnostic if the scaling is not correct.
244 //
245 // The default is 'lsl #0' (HasExplicitAmount = false) if no
246 // ShiftExtend is specified.
247 ShiftExtendOp ShiftExtend;
Tim Northover3b0846e2014-05-24 12:50:23 +0000248 };
249
250 struct VectorListOp {
251 unsigned RegNum;
252 unsigned Count;
253 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000254 unsigned ElementWidth;
255 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000256 };
257
258 struct VectorIndexOp {
259 unsigned Val;
260 };
261
262 struct ImmOp {
263 const MCExpr *Val;
264 };
265
266 struct ShiftedImmOp {
267 const MCExpr *Val;
268 unsigned ShiftAmount;
269 };
270
271 struct CondCodeOp {
272 AArch64CC::CondCode Code;
273 };
274
275 struct FPImmOp {
276 unsigned Val; // Encoded 8-bit representation.
277 };
278
279 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000280 const char *Data;
281 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000282 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000283 };
284
285 struct SysRegOp {
286 const char *Data;
287 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000288 uint32_t MRSReg;
289 uint32_t MSRReg;
290 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000291 };
292
293 struct SysCRImmOp {
294 unsigned Val;
295 };
296
297 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000298 const char *Data;
299 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000300 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000301 };
302
Oliver Stannarda34e4702015-12-01 10:48:51 +0000303 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000304 const char *Data;
305 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000306 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000307 };
308
Tim Northover3b0846e2014-05-24 12:50:23 +0000309 struct ExtendOp {
310 unsigned Val;
311 };
312
313 union {
314 struct TokOp Tok;
315 struct RegOp Reg;
316 struct VectorListOp VectorList;
317 struct VectorIndexOp VectorIndex;
318 struct ImmOp Imm;
319 struct ShiftedImmOp ShiftedImm;
320 struct CondCodeOp CondCode;
321 struct FPImmOp FPImm;
322 struct BarrierOp Barrier;
323 struct SysRegOp SysReg;
324 struct SysCRImmOp SysCRImm;
325 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000326 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000327 struct ShiftExtendOp ShiftExtend;
328 };
329
330 // Keep the MCContext around as the MCExprs may need manipulated during
331 // the add<>Operands() calls.
332 MCContext &Ctx;
333
David Blaikie960ea3f2014-06-08 16:18:35 +0000334public:
David Blaikie9f380a32015-03-16 18:06:57 +0000335 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000336
Tim Northover3b0846e2014-05-24 12:50:23 +0000337 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
338 Kind = o.Kind;
339 StartLoc = o.StartLoc;
340 EndLoc = o.EndLoc;
341 switch (Kind) {
342 case k_Token:
343 Tok = o.Tok;
344 break;
345 case k_Immediate:
346 Imm = o.Imm;
347 break;
348 case k_ShiftedImm:
349 ShiftedImm = o.ShiftedImm;
350 break;
351 case k_CondCode:
352 CondCode = o.CondCode;
353 break;
354 case k_FPImm:
355 FPImm = o.FPImm;
356 break;
357 case k_Barrier:
358 Barrier = o.Barrier;
359 break;
360 case k_Register:
361 Reg = o.Reg;
362 break;
363 case k_VectorList:
364 VectorList = o.VectorList;
365 break;
366 case k_VectorIndex:
367 VectorIndex = o.VectorIndex;
368 break;
369 case k_SysReg:
370 SysReg = o.SysReg;
371 break;
372 case k_SysCR:
373 SysCRImm = o.SysCRImm;
374 break;
375 case k_Prefetch:
376 Prefetch = o.Prefetch;
377 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000378 case k_PSBHint:
379 PSBHint = o.PSBHint;
380 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000381 case k_ShiftExtend:
382 ShiftExtend = o.ShiftExtend;
383 break;
384 }
385 }
386
387 /// getStartLoc - Get the location of the first token of this operand.
388 SMLoc getStartLoc() const override { return StartLoc; }
389 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000390 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000391
392 StringRef getToken() const {
393 assert(Kind == k_Token && "Invalid access!");
394 return StringRef(Tok.Data, Tok.Length);
395 }
396
397 bool isTokenSuffix() const {
398 assert(Kind == k_Token && "Invalid access!");
399 return Tok.IsSuffix;
400 }
401
402 const MCExpr *getImm() const {
403 assert(Kind == k_Immediate && "Invalid access!");
404 return Imm.Val;
405 }
406
407 const MCExpr *getShiftedImmVal() const {
408 assert(Kind == k_ShiftedImm && "Invalid access!");
409 return ShiftedImm.Val;
410 }
411
412 unsigned getShiftedImmShift() const {
413 assert(Kind == k_ShiftedImm && "Invalid access!");
414 return ShiftedImm.ShiftAmount;
415 }
416
417 AArch64CC::CondCode getCondCode() const {
418 assert(Kind == k_CondCode && "Invalid access!");
419 return CondCode.Code;
420 }
421
422 unsigned getFPImm() const {
423 assert(Kind == k_FPImm && "Invalid access!");
424 return FPImm.Val;
425 }
426
427 unsigned getBarrier() const {
428 assert(Kind == k_Barrier && "Invalid access!");
429 return Barrier.Val;
430 }
431
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000432 StringRef getBarrierName() const {
433 assert(Kind == k_Barrier && "Invalid access!");
434 return StringRef(Barrier.Data, Barrier.Length);
435 }
436
Tim Northover3b0846e2014-05-24 12:50:23 +0000437 unsigned getReg() const override {
438 assert(Kind == k_Register && "Invalid access!");
439 return Reg.RegNum;
440 }
441
442 unsigned getVectorListStart() const {
443 assert(Kind == k_VectorList && "Invalid access!");
444 return VectorList.RegNum;
445 }
446
447 unsigned getVectorListCount() const {
448 assert(Kind == k_VectorList && "Invalid access!");
449 return VectorList.Count;
450 }
451
452 unsigned getVectorIndex() const {
453 assert(Kind == k_VectorIndex && "Invalid access!");
454 return VectorIndex.Val;
455 }
456
457 StringRef getSysReg() const {
458 assert(Kind == k_SysReg && "Invalid access!");
459 return StringRef(SysReg.Data, SysReg.Length);
460 }
461
Tim Northover3b0846e2014-05-24 12:50:23 +0000462 unsigned getSysCR() const {
463 assert(Kind == k_SysCR && "Invalid access!");
464 return SysCRImm.Val;
465 }
466
467 unsigned getPrefetch() const {
468 assert(Kind == k_Prefetch && "Invalid access!");
469 return Prefetch.Val;
470 }
471
Oliver Stannarda34e4702015-12-01 10:48:51 +0000472 unsigned getPSBHint() const {
473 assert(Kind == k_PSBHint && "Invalid access!");
474 return PSBHint.Val;
475 }
476
477 StringRef getPSBHintName() const {
478 assert(Kind == k_PSBHint && "Invalid access!");
479 return StringRef(PSBHint.Data, PSBHint.Length);
480 }
481
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000482 StringRef getPrefetchName() const {
483 assert(Kind == k_Prefetch && "Invalid access!");
484 return StringRef(Prefetch.Data, Prefetch.Length);
485 }
486
Tim Northover3b0846e2014-05-24 12:50:23 +0000487 AArch64_AM::ShiftExtendType getShiftExtendType() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000488 if (Kind == k_ShiftExtend)
489 return ShiftExtend.Type;
490 if (Kind == k_Register)
491 return Reg.ShiftExtend.Type;
492 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000493 }
494
495 unsigned getShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000496 if (Kind == k_ShiftExtend)
497 return ShiftExtend.Amount;
498 if (Kind == k_Register)
499 return Reg.ShiftExtend.Amount;
500 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000501 }
502
503 bool hasShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000504 if (Kind == k_ShiftExtend)
505 return ShiftExtend.HasExplicitAmount;
506 if (Kind == k_Register)
507 return Reg.ShiftExtend.HasExplicitAmount;
508 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000509 }
510
511 bool isImm() const override { return Kind == k_Immediate; }
512 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000513
514 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
515
Sander de Smalen50ded902018-04-29 17:33:38 +0000516 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
517 return isImmScaled<Bits, Scale>(true);
518 }
519
520 template <int Bits, int Scale> DiagnosticPredicate isUImmScaled() const {
521 return isImmScaled<Bits, Scale>(false);
522 }
523
Sander de Smalenfe17a782018-04-26 12:54:42 +0000524 template <int Bits, int Scale>
Sander de Smalen50ded902018-04-29 17:33:38 +0000525 DiagnosticPredicate isImmScaled(bool Signed) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000526 if (!isImm())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000527 return DiagnosticPredicateTy::NoMatch;
528
Tim Northover3b0846e2014-05-24 12:50:23 +0000529 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
530 if (!MCE)
Sander de Smalenfe17a782018-04-26 12:54:42 +0000531 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000532
Sander de Smalen50ded902018-04-29 17:33:38 +0000533 int64_t MinVal, MaxVal;
534 if (Signed) {
535 int64_t Shift = Bits - 1;
536 MinVal = (int64_t(1) << Shift) * -Scale;
537 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
538 } else {
539 MinVal = 0;
540 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
541 }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000542
Tim Northover3b0846e2014-05-24 12:50:23 +0000543 int64_t Val = MCE->getValue();
Sander de Smalenfe17a782018-04-26 12:54:42 +0000544 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
545 return DiagnosticPredicateTy::Match;
546
547 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +0000548 }
549
Sander de Smalen245e0e62018-01-22 10:46:00 +0000550 bool isSVEPattern() const {
551 if (!isImm())
552 return false;
553 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
554 if (!MCE)
555 return false;
556 int64_t Val = MCE->getValue();
557 return Val >= 0 && Val < 32;
558 }
559
Tim Northover3b0846e2014-05-24 12:50:23 +0000560 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
561 AArch64MCExpr::VariantKind ELFRefKind;
562 MCSymbolRefExpr::VariantKind DarwinRefKind;
563 int64_t Addend;
564 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
565 Addend)) {
566 // If we don't understand the expression, assume the best and
567 // let the fixup and relocation code deal with it.
568 return true;
569 }
570
571 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
572 ELFRefKind == AArch64MCExpr::VK_LO12 ||
573 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
574 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
575 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
576 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
577 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
578 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000579 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
580 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
581 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000582 // Note that we don't range-check the addend. It's adjusted modulo page
583 // size when converted, so there is no "out of range" condition when using
584 // @pageoff.
585 return Addend >= 0 && (Addend % Scale) == 0;
586 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
587 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
588 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
589 return Addend == 0;
590 }
591
592 return false;
593 }
594
595 template <int Scale> bool isUImm12Offset() const {
596 if (!isImm())
597 return false;
598
599 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
600 if (!MCE)
601 return isSymbolicUImm12Offset(getImm(), Scale);
602
603 int64_t Val = MCE->getValue();
604 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
605 }
606
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000607 template <int N, int M>
608 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000609 if (!isImm())
610 return false;
611 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
612 if (!MCE)
613 return false;
614 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000615 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000616 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000617
Sander de Smalena1c259c2018-01-29 13:05:38 +0000618 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
619 // a logical immediate can always be represented when inverted.
620 template <typename T>
621 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000622 if (!isImm())
623 return false;
624 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
625 if (!MCE)
626 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000627
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000628 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000629 int64_t SVal = typename std::make_signed<T>::type(Val);
630 int64_t UVal = typename std::make_unsigned<T>::type(Val);
631 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000632 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000633
Sander de Smalena1c259c2018-01-29 13:05:38 +0000634 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000635 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000636
Tim Northover3b0846e2014-05-24 12:50:23 +0000637 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000638
Sander de Smalen62770792018-05-25 09:47:52 +0000639 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
640 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
641 /// immediate that can be shifted by 'Shift'.
642 template <unsigned Width>
643 Optional<std::pair<int64_t, unsigned> > getShiftedVal() const {
644 if (isShiftedImm() && Width == getShiftedImmShift())
645 if (auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
646 return std::make_pair(CE->getValue(), Width);
647
648 if (isImm())
649 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
650 int64_t Val = CE->getValue();
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000651 if ((Val != 0) && (uint64_t(Val >> Width) << Width) == uint64_t(Val))
Sander de Smalen62770792018-05-25 09:47:52 +0000652 return std::make_pair(Val >> Width, Width);
653 else
654 return std::make_pair(Val, 0u);
655 }
656
657 return {};
658 }
659
Tim Northover3b0846e2014-05-24 12:50:23 +0000660 bool isAddSubImm() const {
661 if (!isShiftedImm() && !isImm())
662 return false;
663
664 const MCExpr *Expr;
665
666 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
667 if (isShiftedImm()) {
668 unsigned Shift = ShiftedImm.ShiftAmount;
669 Expr = ShiftedImm.Val;
670 if (Shift != 0 && Shift != 12)
671 return false;
672 } else {
673 Expr = getImm();
674 }
675
676 AArch64MCExpr::VariantKind ELFRefKind;
677 MCSymbolRefExpr::VariantKind DarwinRefKind;
678 int64_t Addend;
679 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
680 DarwinRefKind, Addend)) {
681 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
682 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
683 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
684 || ELFRefKind == AArch64MCExpr::VK_LO12
685 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
686 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
687 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
688 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
689 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
690 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000691 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
692 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
693 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000694 }
695
Sander de Smalen98686c62018-05-29 10:39:49 +0000696 // If it's a constant, it should be a real immediate in range.
Sander de Smalen62770792018-05-25 09:47:52 +0000697 if (auto ShiftedVal = getShiftedVal<12>())
698 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
Diana Picusc93518d2016-10-11 09:17:47 +0000699
700 // If it's an expression, we hope for the best and let the fixup/relocation
701 // code deal with it.
702 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000703 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000704
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000705 bool isAddSubImmNeg() const {
706 if (!isShiftedImm() && !isImm())
707 return false;
708
Sander de Smalen98686c62018-05-29 10:39:49 +0000709 // Otherwise it should be a real negative immediate in range.
710 if (auto ShiftedVal = getShiftedVal<12>())
711 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000712
Sander de Smalen98686c62018-05-29 10:39:49 +0000713 return false;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000714 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000715
Sander de Smalen62770792018-05-25 09:47:52 +0000716 // Signed value in the range -128 to +127. For element widths of
717 // 16 bits or higher it may also be a signed multiple of 256 in the
718 // range -32768 to +32512.
719 // For element-width of 8 bits a range of -128 to 255 is accepted,
720 // since a copy of a byte can be either signed/unsigned.
721 template <typename T>
722 DiagnosticPredicate isSVECpyImm() const {
723 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
724 return DiagnosticPredicateTy::NoMatch;
725
726 bool IsByte =
727 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
728 if (auto ShiftedImm = getShiftedVal<8>())
729 if (!(IsByte && ShiftedImm->second) &&
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000730 AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
731 << ShiftedImm->second))
Sander de Smalen62770792018-05-25 09:47:52 +0000732 return DiagnosticPredicateTy::Match;
733
734 return DiagnosticPredicateTy::NearMatch;
735 }
736
Sander de Smalen98686c62018-05-29 10:39:49 +0000737 // Unsigned value in the range 0 to 255. For element widths of
738 // 16 bits or higher it may also be a signed multiple of 256 in the
739 // range 0 to 65280.
740 template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
741 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
742 return DiagnosticPredicateTy::NoMatch;
743
744 bool IsByte =
745 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
746 if (auto ShiftedImm = getShiftedVal<8>())
747 if (!(IsByte && ShiftedImm->second) &&
748 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
749 << ShiftedImm->second))
750 return DiagnosticPredicateTy::Match;
751
752 return DiagnosticPredicateTy::NearMatch;
753 }
754
Sander de Smalen97ca6b92018-06-01 07:25:46 +0000755 template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
756 if (isLogicalImm<T>() && !isSVECpyImm<T>())
757 return DiagnosticPredicateTy::Match;
758 return DiagnosticPredicateTy::NoMatch;
759 }
760
Tim Northover3b0846e2014-05-24 12:50:23 +0000761 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000762
Tim Northover3b0846e2014-05-24 12:50:23 +0000763 bool isSIMDImmType10() const {
764 if (!isImm())
765 return false;
766 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
767 if (!MCE)
768 return false;
769 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
770 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000771
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000772 template<int N>
773 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000774 if (!isImm())
775 return false;
776 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
777 if (!MCE)
778 return true;
779 int64_t Val = MCE->getValue();
780 if (Val & 0x3)
781 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000782 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
783 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000784 }
785
786 bool
787 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
788 if (!isImm())
789 return false;
790
791 AArch64MCExpr::VariantKind ELFRefKind;
792 MCSymbolRefExpr::VariantKind DarwinRefKind;
793 int64_t Addend;
794 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
795 DarwinRefKind, Addend)) {
796 return false;
797 }
798 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
799 return false;
800
801 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
802 if (ELFRefKind == AllowedModifiers[i])
803 return Addend == 0;
804 }
805
806 return false;
807 }
808
809 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000810 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000811 }
812
813 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000814 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
815 AArch64MCExpr::VK_TPREL_G2,
816 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000817 }
818
819 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000820 return isMovWSymbol({
821 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000822 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
823 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000824 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000825 }
826
827 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000828 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
829 AArch64MCExpr::VK_TPREL_G0,
830 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000831 }
832
833 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000834 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000835 }
836
837 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000838 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000839 }
840
841 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000842 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
843 AArch64MCExpr::VK_TPREL_G1_NC,
844 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000845 }
846
847 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000848 return isMovWSymbol(
849 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
850 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000851 }
852
853 template<int RegWidth, int Shift>
854 bool isMOVZMovAlias() const {
855 if (!isImm()) return false;
856
857 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
858 if (!CE) return false;
859 uint64_t Value = CE->getValue();
860
Tim Northoverdaa1c012016-06-16 01:42:25 +0000861 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000862 }
863
864 template<int RegWidth, int Shift>
865 bool isMOVNMovAlias() const {
866 if (!isImm()) return false;
867
868 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
869 if (!CE) return false;
870 uint64_t Value = CE->getValue();
871
Tim Northoverdaa1c012016-06-16 01:42:25 +0000872 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000873 }
874
875 bool isFPImm() const { return Kind == k_FPImm; }
876 bool isBarrier() const { return Kind == k_Barrier; }
877 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000878
Tim Northover3b0846e2014-05-24 12:50:23 +0000879 bool isMRSSystemRegister() const {
880 if (!isSysReg()) return false;
881
Tim Northover7cd58932015-01-22 17:23:04 +0000882 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000883 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000884
Tim Northover3b0846e2014-05-24 12:50:23 +0000885 bool isMSRSystemRegister() const {
886 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000887 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000888 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000889
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000890 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000891 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000892 return (SysReg.PStateField == AArch64PState::PAN ||
893 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000894 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000895
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000896 bool isSystemPStateFieldWithImm0_15() const {
897 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000898 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000899 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000900
Florian Hahnc4422242017-11-07 13:07:50 +0000901 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000902 return Kind == k_Register;
903 }
904
905 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000906 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
907 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000908
Florian Hahnc4422242017-11-07 13:07:50 +0000909 bool isNeonVectorReg() const {
910 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
911 }
912
913 bool isNeonVectorRegLo() const {
914 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000915 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
916 Reg.RegNum);
917 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000918
Sander de Smalencd6be962017-12-20 11:02:42 +0000919 template <unsigned Class> bool isSVEVectorReg() const {
920 RegKind RK;
921 switch (Class) {
922 case AArch64::ZPRRegClassID:
923 RK = RegKind::SVEDataVector;
924 break;
925 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000926 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000927 RK = RegKind::SVEPredicateVector;
928 break;
929 default:
930 llvm_unreachable("Unsupport register class");
931 }
932
933 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000934 AArch64MCRegisterClasses[Class].contains(getReg());
935 }
936
Sander de Smalenfd54a782018-06-04 07:07:35 +0000937 template <unsigned Class> bool isFPRasZPR() const {
938 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
939 AArch64MCRegisterClasses[Class].contains(getReg());
940 }
941
Sander de Smalencd6be962017-12-20 11:02:42 +0000942 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +0000943 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
944 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
945 return DiagnosticPredicateTy::NoMatch;
946
947 if (isSVEVectorReg<Class>() &&
948 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
949 return DiagnosticPredicateTy::Match;
950
951 return DiagnosticPredicateTy::NearMatch;
952 }
953
954 template <int ElementWidth, unsigned Class>
955 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
956 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
957 return DiagnosticPredicateTy::NoMatch;
958
959 if (isSVEVectorReg<Class>() &&
960 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
961 return DiagnosticPredicateTy::Match;
962
963 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +0000964 }
965
Sander de Smaleneb896b12018-04-25 09:26:47 +0000966 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +0000967 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
968 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +0000969 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
970 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
971 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000972 return DiagnosticPredicateTy::NoMatch;
973
Sander de Smalen5861c262018-04-30 07:24:38 +0000974 // Give a more specific diagnostic when the user has explicitly typed in
975 // a shift-amount that does not match what is expected, but for which
976 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
977 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
978 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
979 ShiftExtendTy == AArch64_AM::SXTW) &&
980 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
981 return DiagnosticPredicateTy::NoMatch;
982
983 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000984 return DiagnosticPredicateTy::Match;
985
986 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +0000987 }
988
Tim Northover3b0846e2014-05-24 12:50:23 +0000989 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000990 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000991 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
992 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000993
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000994 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000995 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000996 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
997 Reg.RegNum);
998 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000999
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001000 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001001 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001002 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1003 Reg.RegNum);
1004 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001005
Sam Parker5f934642017-08-31 09:27:04 +00001006 template<int64_t Angle, int64_t Remainder>
1007 bool isComplexRotation() const {
1008 if (!isImm()) return false;
1009
1010 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1011 if (!CE) return false;
1012 uint64_t Value = CE->getValue();
1013
1014 return (Value % Angle == Remainder && Value <= 270);
1015 }
1016
Sander de Smalen149916d2018-04-20 07:24:20 +00001017 template <unsigned RegClassID> bool isGPR64() const {
1018 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1019 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1020 }
1021
1022 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001023 DiagnosticPredicate isGPR64WithShiftExtend() const {
1024 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1025 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001026
Sander de Smalenfe17a782018-04-26 12:54:42 +00001027 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1028 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1029 return DiagnosticPredicateTy::Match;
1030 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001031 }
1032
Tim Northover3b0846e2014-05-24 12:50:23 +00001033 /// Is this a vector list with the type implicit (presumably attached to the
1034 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001035 template <RegKind VectorKind, unsigned NumRegs>
1036 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001037 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001038 VectorList.NumElements == 0 &&
1039 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001040 }
1041
Sander de Smalen650234b2018-04-12 11:40:52 +00001042 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1043 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001044 bool isTypedVectorList() const {
1045 if (Kind != k_VectorList)
1046 return false;
1047 if (VectorList.Count != NumRegs)
1048 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001049 if (VectorList.RegisterKind != VectorKind)
1050 return false;
1051 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001052 return false;
1053 return VectorList.NumElements == NumElements;
1054 }
1055
Sander de Smalenc33d6682018-06-04 06:40:55 +00001056 template <int Min, int Max>
1057 DiagnosticPredicate isVectorIndex() const {
1058 if (Kind != k_VectorIndex)
1059 return DiagnosticPredicateTy::NoMatch;
1060 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1061 return DiagnosticPredicateTy::Match;
1062 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001063 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001064
Tim Northover3b0846e2014-05-24 12:50:23 +00001065 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001066
Tim Northover3b0846e2014-05-24 12:50:23 +00001067 bool isTokenEqual(StringRef Str) const {
1068 return Kind == k_Token && getToken() == Str;
1069 }
1070 bool isSysCR() const { return Kind == k_SysCR; }
1071 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001072 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001073 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1074 bool isShifter() const {
1075 if (!isShiftExtend())
1076 return false;
1077
1078 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1079 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1080 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1081 ST == AArch64_AM::MSL);
1082 }
1083 bool isExtend() const {
1084 if (!isShiftExtend())
1085 return false;
1086
1087 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1088 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1089 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1090 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1091 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1092 ET == AArch64_AM::LSL) &&
1093 getShiftExtendAmount() <= 4;
1094 }
1095
1096 bool isExtend64() const {
1097 if (!isExtend())
1098 return false;
1099 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1100 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1101 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1102 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001103
Tim Northover3b0846e2014-05-24 12:50:23 +00001104 bool isExtendLSL64() const {
1105 if (!isExtend())
1106 return false;
1107 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1108 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1109 ET == AArch64_AM::LSL) &&
1110 getShiftExtendAmount() <= 4;
1111 }
1112
1113 template<int Width> bool isMemXExtend() const {
1114 if (!isExtend())
1115 return false;
1116 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1117 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1118 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1119 getShiftExtendAmount() == 0);
1120 }
1121
1122 template<int Width> bool isMemWExtend() const {
1123 if (!isExtend())
1124 return false;
1125 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1126 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1127 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1128 getShiftExtendAmount() == 0);
1129 }
1130
1131 template <unsigned width>
1132 bool isArithmeticShifter() const {
1133 if (!isShifter())
1134 return false;
1135
1136 // An arithmetic shifter is LSL, LSR, or ASR.
1137 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1138 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1139 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1140 }
1141
1142 template <unsigned width>
1143 bool isLogicalShifter() const {
1144 if (!isShifter())
1145 return false;
1146
1147 // A logical shifter is LSL, LSR, ASR or ROR.
1148 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1149 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1150 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1151 getShiftExtendAmount() < width;
1152 }
1153
1154 bool isMovImm32Shifter() const {
1155 if (!isShifter())
1156 return false;
1157
1158 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1159 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1160 if (ST != AArch64_AM::LSL)
1161 return false;
1162 uint64_t Val = getShiftExtendAmount();
1163 return (Val == 0 || Val == 16);
1164 }
1165
1166 bool isMovImm64Shifter() const {
1167 if (!isShifter())
1168 return false;
1169
1170 // A MOVi shifter is LSL of 0 or 16.
1171 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1172 if (ST != AArch64_AM::LSL)
1173 return false;
1174 uint64_t Val = getShiftExtendAmount();
1175 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1176 }
1177
1178 bool isLogicalVecShifter() const {
1179 if (!isShifter())
1180 return false;
1181
1182 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1183 unsigned Shift = getShiftExtendAmount();
1184 return getShiftExtendType() == AArch64_AM::LSL &&
1185 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1186 }
1187
1188 bool isLogicalVecHalfWordShifter() const {
1189 if (!isLogicalVecShifter())
1190 return false;
1191
1192 // A logical vector shifter is a left shift by 0 or 8.
1193 unsigned Shift = getShiftExtendAmount();
1194 return getShiftExtendType() == AArch64_AM::LSL &&
1195 (Shift == 0 || Shift == 8);
1196 }
1197
1198 bool isMoveVecShifter() const {
1199 if (!isShiftExtend())
1200 return false;
1201
1202 // A logical vector shifter is a left shift by 8 or 16.
1203 unsigned Shift = getShiftExtendAmount();
1204 return getShiftExtendType() == AArch64_AM::MSL &&
1205 (Shift == 8 || Shift == 16);
1206 }
1207
1208 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1209 // to LDUR/STUR when the offset is not legal for the former but is for
1210 // the latter. As such, in addition to checking for being a legal unscaled
1211 // address, also check that it is not a legal scaled address. This avoids
1212 // ambiguity in the matcher.
1213 template<int Width>
1214 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001215 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001216 }
1217
1218 bool isAdrpLabel() const {
1219 // Validation was handled during parsing, so we just sanity check that
1220 // something didn't go haywire.
1221 if (!isImm())
1222 return false;
1223
1224 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1225 int64_t Val = CE->getValue();
1226 int64_t Min = - (4096 * (1LL << (21 - 1)));
1227 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1228 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1229 }
1230
1231 return true;
1232 }
1233
1234 bool isAdrLabel() const {
1235 // Validation was handled during parsing, so we just sanity check that
1236 // something didn't go haywire.
1237 if (!isImm())
1238 return false;
1239
1240 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1241 int64_t Val = CE->getValue();
1242 int64_t Min = - (1LL << (21 - 1));
1243 int64_t Max = ((1LL << (21 - 1)) - 1);
1244 return Val >= Min && Val <= Max;
1245 }
1246
1247 return true;
1248 }
1249
1250 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1251 // Add as immediates when possible. Null MCExpr = 0.
1252 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001253 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001254 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001255 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001256 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001257 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001258 }
1259
1260 void addRegOperands(MCInst &Inst, unsigned N) const {
1261 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001262 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001263 }
1264
1265 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1266 assert(N == 1 && "Invalid number of operands!");
1267 assert(
1268 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1269
1270 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1271 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1272 RI->getEncodingValue(getReg()));
1273
Jim Grosbache9119e42015-05-13 18:37:00 +00001274 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001275 }
1276
Sander de Smalenfd54a782018-06-04 07:07:35 +00001277 template <int Width>
1278 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1279 unsigned Base;
1280 switch (Width) {
1281 case 8: Base = AArch64::B0; break;
1282 case 16: Base = AArch64::H0; break;
1283 case 32: Base = AArch64::S0; break;
1284 case 64: Base = AArch64::D0; break;
1285 case 128: Base = AArch64::Q0; break;
1286 default:
1287 llvm_unreachable("Unsupported width");
1288 }
1289 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1290 }
1291
Tim Northover3b0846e2014-05-24 12:50:23 +00001292 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1293 assert(N == 1 && "Invalid number of operands!");
1294 assert(
1295 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001296 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001297 }
1298
1299 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1300 assert(N == 1 && "Invalid number of operands!");
1301 assert(
1302 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001303 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001304 }
1305
1306 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1307 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001308 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001309 }
1310
Sander de Smalen525e3222018-04-12 13:19:32 +00001311 enum VecListIndexType {
1312 VecListIdx_DReg = 0,
1313 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001314 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001315 };
1316
1317 template <VecListIndexType RegTy, unsigned NumRegs>
1318 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001319 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001320 static const unsigned FirstRegs[][5] = {
1321 /* DReg */ { AArch64::Q0,
1322 AArch64::D0, AArch64::D0_D1,
1323 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1324 /* QReg */ { AArch64::Q0,
1325 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001326 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1327 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001328 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001329 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001330 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001331
Sander de Smalen7a210db2018-04-16 10:46:18 +00001332 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1333 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001334
Sander de Smalen525e3222018-04-12 13:19:32 +00001335 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1336 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1337 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001338 }
1339
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001340 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001341 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001342 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001343 }
1344
1345 void addImmOperands(MCInst &Inst, unsigned N) const {
1346 assert(N == 1 && "Invalid number of operands!");
1347 // If this is a pageoff symrefexpr with an addend, adjust the addend
1348 // to be only the page-offset portion. Otherwise, just add the expr
1349 // as-is.
1350 addExpr(Inst, getImm());
1351 }
1352
Sander de Smalen62770792018-05-25 09:47:52 +00001353 template <int Shift>
1354 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001355 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001356 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1357 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1358 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1359 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001360 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001361 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001362 } else {
1363 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001364 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001365 }
1366 }
1367
Sander de Smalen62770792018-05-25 09:47:52 +00001368 template <int Shift>
1369 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001370 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001371 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1372 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1373 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1374 } else
1375 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001376 }
1377
Tim Northover3b0846e2014-05-24 12:50:23 +00001378 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1379 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001380 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001381 }
1382
1383 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1384 assert(N == 1 && "Invalid number of operands!");
1385 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1386 if (!MCE)
1387 addExpr(Inst, getImm());
1388 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001389 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001390 }
1391
1392 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1393 addImmOperands(Inst, N);
1394 }
1395
1396 template<int Scale>
1397 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1398 assert(N == 1 && "Invalid number of operands!");
1399 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1400
1401 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001402 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001403 return;
1404 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001405 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001406 }
1407
Sander de Smalen5c625982018-04-13 12:56:14 +00001408 template <int Scale>
1409 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1410 assert(N == 1 && "Invalid number of operands!");
1411 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1412 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1413 }
1414
Sander de Smalena1c259c2018-01-29 13:05:38 +00001415 template <typename T>
1416 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001417 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001418 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001419 typename std::make_unsigned<T>::type Val = MCE->getValue();
1420 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001421 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001422 }
1423
Sander de Smalena1c259c2018-01-29 13:05:38 +00001424 template <typename T>
1425 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001426 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001427 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001428 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1429 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001430 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001431 }
1432
Tim Northover3b0846e2014-05-24 12:50:23 +00001433 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1434 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001435 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001436 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001437 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001438 }
1439
1440 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1441 // Branch operands don't encode the low bits, so shift them off
1442 // here. If it's a label, however, just put it on directly as there's
1443 // not enough information now to do anything.
1444 assert(N == 1 && "Invalid number of operands!");
1445 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1446 if (!MCE) {
1447 addExpr(Inst, getImm());
1448 return;
1449 }
1450 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001451 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001452 }
1453
1454 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1455 // Branch operands don't encode the low bits, so shift them off
1456 // here. If it's a label, however, just put it on directly as there's
1457 // not enough information now to do anything.
1458 assert(N == 1 && "Invalid number of operands!");
1459 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1460 if (!MCE) {
1461 addExpr(Inst, getImm());
1462 return;
1463 }
1464 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001465 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001466 }
1467
1468 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1469 // Branch operands don't encode the low bits, so shift them off
1470 // here. If it's a label, however, just put it on directly as there's
1471 // not enough information now to do anything.
1472 assert(N == 1 && "Invalid number of operands!");
1473 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1474 if (!MCE) {
1475 addExpr(Inst, getImm());
1476 return;
1477 }
1478 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001479 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001480 }
1481
1482 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1483 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001484 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001485 }
1486
1487 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1488 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001489 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001490 }
1491
1492 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1493 assert(N == 1 && "Invalid number of operands!");
1494
Jim Grosbache9119e42015-05-13 18:37:00 +00001495 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001496 }
1497
1498 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1499 assert(N == 1 && "Invalid number of operands!");
1500
Jim Grosbache9119e42015-05-13 18:37:00 +00001501 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001502 }
1503
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001504 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1505 assert(N == 1 && "Invalid number of operands!");
1506
1507 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1508 }
1509
1510 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001511 assert(N == 1 && "Invalid number of operands!");
1512
Jim Grosbache9119e42015-05-13 18:37:00 +00001513 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001514 }
1515
1516 void addSysCROperands(MCInst &Inst, unsigned N) const {
1517 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001518 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001519 }
1520
1521 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1522 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001523 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001524 }
1525
Oliver Stannarda34e4702015-12-01 10:48:51 +00001526 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1527 assert(N == 1 && "Invalid number of operands!");
1528 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1529 }
1530
Tim Northover3b0846e2014-05-24 12:50:23 +00001531 void addShifterOperands(MCInst &Inst, unsigned N) const {
1532 assert(N == 1 && "Invalid number of operands!");
1533 unsigned Imm =
1534 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001535 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001536 }
1537
1538 void addExtendOperands(MCInst &Inst, unsigned N) const {
1539 assert(N == 1 && "Invalid number of operands!");
1540 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1541 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1542 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001543 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001544 }
1545
1546 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1547 assert(N == 1 && "Invalid number of operands!");
1548 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1549 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1550 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001551 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001552 }
1553
1554 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1555 assert(N == 2 && "Invalid number of operands!");
1556 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1557 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001558 Inst.addOperand(MCOperand::createImm(IsSigned));
1559 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001560 }
1561
1562 // For 8-bit load/store instructions with a register offset, both the
1563 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1564 // they're disambiguated by whether the shift was explicit or implicit rather
1565 // than its size.
1566 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1567 assert(N == 2 && "Invalid number of operands!");
1568 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1569 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001570 Inst.addOperand(MCOperand::createImm(IsSigned));
1571 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001572 }
1573
1574 template<int Shift>
1575 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1576 assert(N == 1 && "Invalid number of operands!");
1577
1578 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1579 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001580 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001581 }
1582
1583 template<int Shift>
1584 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1585 assert(N == 1 && "Invalid number of operands!");
1586
1587 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1588 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001589 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001590 }
1591
Sam Parker5f934642017-08-31 09:27:04 +00001592 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1593 assert(N == 1 && "Invalid number of operands!");
1594 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1595 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1596 }
1597
1598 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1599 assert(N == 1 && "Invalid number of operands!");
1600 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1601 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1602 }
1603
Tim Northover3b0846e2014-05-24 12:50:23 +00001604 void print(raw_ostream &OS) const override;
1605
David Blaikie960ea3f2014-06-08 16:18:35 +00001606 static std::unique_ptr<AArch64Operand>
1607 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1608 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001609 Op->Tok.Data = Str.data();
1610 Op->Tok.Length = Str.size();
1611 Op->Tok.IsSuffix = IsSuffix;
1612 Op->StartLoc = S;
1613 Op->EndLoc = S;
1614 return Op;
1615 }
1616
David Blaikie960ea3f2014-06-08 16:18:35 +00001617 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001618 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
1619 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1620 unsigned ShiftAmount = 0,
1621 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001622 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001623 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001624 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001625 Op->Reg.ElementWidth = 0;
1626 Op->Reg.ShiftExtend.Type = ExtTy;
1627 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1628 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001629 Op->StartLoc = S;
1630 Op->EndLoc = E;
1631 return Op;
1632 }
1633
David Blaikie960ea3f2014-06-08 16:18:35 +00001634 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001635 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001636 SMLoc S, SMLoc E, MCContext &Ctx,
1637 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1638 unsigned ShiftAmount = 0,
1639 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001640 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1641 Kind == RegKind::SVEPredicateVector) &&
1642 "Invalid vector kind");
Sander de Smalen149916d2018-04-20 07:24:20 +00001643 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, ExtTy, ShiftAmount,
1644 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001645 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001646 return Op;
1647 }
1648
1649 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001650 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001651 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1652 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001653 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001654 Op->VectorList.RegNum = RegNum;
1655 Op->VectorList.Count = Count;
1656 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001657 Op->VectorList.ElementWidth = ElementWidth;
1658 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001659 Op->StartLoc = S;
1660 Op->EndLoc = E;
1661 return Op;
1662 }
1663
David Blaikie960ea3f2014-06-08 16:18:35 +00001664 static std::unique_ptr<AArch64Operand>
1665 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1666 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001667 Op->VectorIndex.Val = Idx;
1668 Op->StartLoc = S;
1669 Op->EndLoc = E;
1670 return Op;
1671 }
1672
David Blaikie960ea3f2014-06-08 16:18:35 +00001673 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1674 SMLoc E, MCContext &Ctx) {
1675 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001676 Op->Imm.Val = Val;
1677 Op->StartLoc = S;
1678 Op->EndLoc = E;
1679 return Op;
1680 }
1681
David Blaikie960ea3f2014-06-08 16:18:35 +00001682 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1683 unsigned ShiftAmount,
1684 SMLoc S, SMLoc E,
1685 MCContext &Ctx) {
1686 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001687 Op->ShiftedImm .Val = Val;
1688 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1689 Op->StartLoc = S;
1690 Op->EndLoc = E;
1691 return Op;
1692 }
1693
David Blaikie960ea3f2014-06-08 16:18:35 +00001694 static std::unique_ptr<AArch64Operand>
1695 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1696 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001697 Op->CondCode.Code = Code;
1698 Op->StartLoc = S;
1699 Op->EndLoc = E;
1700 return Op;
1701 }
1702
David Blaikie960ea3f2014-06-08 16:18:35 +00001703 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1704 MCContext &Ctx) {
1705 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001706 Op->FPImm.Val = Val;
1707 Op->StartLoc = S;
1708 Op->EndLoc = S;
1709 return Op;
1710 }
1711
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001712 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1713 StringRef Str,
1714 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001715 MCContext &Ctx) {
1716 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001717 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001718 Op->Barrier.Data = Str.data();
1719 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001720 Op->StartLoc = S;
1721 Op->EndLoc = S;
1722 return Op;
1723 }
1724
Tim Northover7cd58932015-01-22 17:23:04 +00001725 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1726 uint32_t MRSReg,
1727 uint32_t MSRReg,
1728 uint32_t PStateField,
1729 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001730 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001731 Op->SysReg.Data = Str.data();
1732 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001733 Op->SysReg.MRSReg = MRSReg;
1734 Op->SysReg.MSRReg = MSRReg;
1735 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001736 Op->StartLoc = S;
1737 Op->EndLoc = S;
1738 return Op;
1739 }
1740
David Blaikie960ea3f2014-06-08 16:18:35 +00001741 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1742 SMLoc E, MCContext &Ctx) {
1743 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001744 Op->SysCRImm.Val = Val;
1745 Op->StartLoc = S;
1746 Op->EndLoc = E;
1747 return Op;
1748 }
1749
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001750 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1751 StringRef Str,
1752 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001753 MCContext &Ctx) {
1754 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001755 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001756 Op->Barrier.Data = Str.data();
1757 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001758 Op->StartLoc = S;
1759 Op->EndLoc = S;
1760 return Op;
1761 }
1762
Oliver Stannarda34e4702015-12-01 10:48:51 +00001763 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1764 StringRef Str,
1765 SMLoc S,
1766 MCContext &Ctx) {
1767 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1768 Op->PSBHint.Val = Val;
1769 Op->PSBHint.Data = Str.data();
1770 Op->PSBHint.Length = Str.size();
1771 Op->StartLoc = S;
1772 Op->EndLoc = S;
1773 return Op;
1774 }
1775
David Blaikie960ea3f2014-06-08 16:18:35 +00001776 static std::unique_ptr<AArch64Operand>
1777 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1778 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1779 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001780 Op->ShiftExtend.Type = ShOp;
1781 Op->ShiftExtend.Amount = Val;
1782 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1783 Op->StartLoc = S;
1784 Op->EndLoc = E;
1785 return Op;
1786 }
1787};
1788
1789} // end anonymous namespace.
1790
1791void AArch64Operand::print(raw_ostream &OS) const {
1792 switch (Kind) {
1793 case k_FPImm:
1794 OS << "<fpimm " << getFPImm() << "("
1795 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1796 break;
1797 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001798 StringRef Name = getBarrierName();
1799 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001800 OS << "<barrier " << Name << ">";
1801 else
1802 OS << "<barrier invalid #" << getBarrier() << ">";
1803 break;
1804 }
1805 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001806 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001807 break;
1808 case k_ShiftedImm: {
1809 unsigned Shift = getShiftedImmShift();
1810 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001811 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001812 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1813 break;
1814 }
1815 case k_CondCode:
1816 OS << "<condcode " << getCondCode() << ">";
1817 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001818 case k_VectorList: {
1819 OS << "<vectorlist ";
1820 unsigned Reg = getVectorListStart();
1821 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1822 OS << Reg + i << " ";
1823 OS << ">";
1824 break;
1825 }
1826 case k_VectorIndex:
1827 OS << "<vectorindex " << getVectorIndex() << ">";
1828 break;
1829 case k_SysReg:
1830 OS << "<sysreg: " << getSysReg() << '>';
1831 break;
1832 case k_Token:
1833 OS << "'" << getToken() << "'";
1834 break;
1835 case k_SysCR:
1836 OS << "c" << getSysCR();
1837 break;
1838 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001839 StringRef Name = getPrefetchName();
1840 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001841 OS << "<prfop " << Name << ">";
1842 else
1843 OS << "<prfop invalid #" << getPrefetch() << ">";
1844 break;
1845 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001846 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001847 OS << getPSBHintName();
1848 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00001849 case k_Register:
1850 OS << "<register " << getReg() << ">";
1851 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
1852 break;
1853 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001854 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001855 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1856 << getShiftExtendAmount();
1857 if (!hasShiftExtendAmount())
1858 OS << "<imp>";
1859 OS << '>';
1860 break;
1861 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001862}
1863
1864/// @name Auto-generated Match Functions
1865/// {
1866
1867static unsigned MatchRegisterName(StringRef Name);
1868
1869/// }
1870
Florian Hahnc4422242017-11-07 13:07:50 +00001871static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001872 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001873 .Case("v0", AArch64::Q0)
1874 .Case("v1", AArch64::Q1)
1875 .Case("v2", AArch64::Q2)
1876 .Case("v3", AArch64::Q3)
1877 .Case("v4", AArch64::Q4)
1878 .Case("v5", AArch64::Q5)
1879 .Case("v6", AArch64::Q6)
1880 .Case("v7", AArch64::Q7)
1881 .Case("v8", AArch64::Q8)
1882 .Case("v9", AArch64::Q9)
1883 .Case("v10", AArch64::Q10)
1884 .Case("v11", AArch64::Q11)
1885 .Case("v12", AArch64::Q12)
1886 .Case("v13", AArch64::Q13)
1887 .Case("v14", AArch64::Q14)
1888 .Case("v15", AArch64::Q15)
1889 .Case("v16", AArch64::Q16)
1890 .Case("v17", AArch64::Q17)
1891 .Case("v18", AArch64::Q18)
1892 .Case("v19", AArch64::Q19)
1893 .Case("v20", AArch64::Q20)
1894 .Case("v21", AArch64::Q21)
1895 .Case("v22", AArch64::Q22)
1896 .Case("v23", AArch64::Q23)
1897 .Case("v24", AArch64::Q24)
1898 .Case("v25", AArch64::Q25)
1899 .Case("v26", AArch64::Q26)
1900 .Case("v27", AArch64::Q27)
1901 .Case("v28", AArch64::Q28)
1902 .Case("v29", AArch64::Q29)
1903 .Case("v30", AArch64::Q30)
1904 .Case("v31", AArch64::Q31)
1905 .Default(0);
1906}
1907
Sander de Smalen73937b72018-04-11 07:36:10 +00001908/// Returns an optional pair of (#elements, element-width) if Suffix
1909/// is a valid vector kind. Where the number of elements in a vector
1910/// or the vector width is implicit or explicitly unknown (but still a
1911/// valid suffix kind), 0 is used.
1912static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1913 RegKind VectorKind) {
1914 std::pair<int, int> Res = {-1, -1};
1915
1916 switch (VectorKind) {
1917 case RegKind::NeonVector:
1918 Res =
1919 StringSwitch<std::pair<int, int>>(Suffix.lower())
1920 .Case("", {0, 0})
1921 .Case(".1d", {1, 64})
1922 .Case(".1q", {1, 128})
1923 // '.2h' needed for fp16 scalar pairwise reductions
1924 .Case(".2h", {2, 16})
1925 .Case(".2s", {2, 32})
1926 .Case(".2d", {2, 64})
1927 // '.4b' is another special case for the ARMv8.2a dot product
1928 // operand
1929 .Case(".4b", {4, 8})
1930 .Case(".4h", {4, 16})
1931 .Case(".4s", {4, 32})
1932 .Case(".8b", {8, 8})
1933 .Case(".8h", {8, 16})
1934 .Case(".16b", {16, 8})
1935 // Accept the width neutral ones, too, for verbose syntax. If those
1936 // aren't used in the right places, the token operand won't match so
1937 // all will work out.
1938 .Case(".b", {0, 8})
1939 .Case(".h", {0, 16})
1940 .Case(".s", {0, 32})
1941 .Case(".d", {0, 64})
1942 .Default({-1, -1});
1943 break;
1944 case RegKind::SVEPredicateVector:
1945 case RegKind::SVEDataVector:
1946 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1947 .Case("", {0, 0})
1948 .Case(".b", {0, 8})
1949 .Case(".h", {0, 16})
1950 .Case(".s", {0, 32})
1951 .Case(".d", {0, 64})
1952 .Case(".q", {0, 128})
1953 .Default({-1, -1});
1954 break;
1955 default:
1956 llvm_unreachable("Unsupported RegKind");
1957 }
1958
1959 if (Res == std::make_pair(-1, -1))
1960 return Optional<std::pair<int, int>>();
1961
1962 return Optional<std::pair<int, int>>(Res);
1963}
1964
1965static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1966 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001967}
1968
Florian Hahn91f11e52017-11-07 16:45:48 +00001969static unsigned matchSVEDataVectorRegName(StringRef Name) {
1970 return StringSwitch<unsigned>(Name.lower())
1971 .Case("z0", AArch64::Z0)
1972 .Case("z1", AArch64::Z1)
1973 .Case("z2", AArch64::Z2)
1974 .Case("z3", AArch64::Z3)
1975 .Case("z4", AArch64::Z4)
1976 .Case("z5", AArch64::Z5)
1977 .Case("z6", AArch64::Z6)
1978 .Case("z7", AArch64::Z7)
1979 .Case("z8", AArch64::Z8)
1980 .Case("z9", AArch64::Z9)
1981 .Case("z10", AArch64::Z10)
1982 .Case("z11", AArch64::Z11)
1983 .Case("z12", AArch64::Z12)
1984 .Case("z13", AArch64::Z13)
1985 .Case("z14", AArch64::Z14)
1986 .Case("z15", AArch64::Z15)
1987 .Case("z16", AArch64::Z16)
1988 .Case("z17", AArch64::Z17)
1989 .Case("z18", AArch64::Z18)
1990 .Case("z19", AArch64::Z19)
1991 .Case("z20", AArch64::Z20)
1992 .Case("z21", AArch64::Z21)
1993 .Case("z22", AArch64::Z22)
1994 .Case("z23", AArch64::Z23)
1995 .Case("z24", AArch64::Z24)
1996 .Case("z25", AArch64::Z25)
1997 .Case("z26", AArch64::Z26)
1998 .Case("z27", AArch64::Z27)
1999 .Case("z28", AArch64::Z28)
2000 .Case("z29", AArch64::Z29)
2001 .Case("z30", AArch64::Z30)
2002 .Case("z31", AArch64::Z31)
2003 .Default(0);
2004}
2005
Sander de Smalencd6be962017-12-20 11:02:42 +00002006static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2007 return StringSwitch<unsigned>(Name.lower())
2008 .Case("p0", AArch64::P0)
2009 .Case("p1", AArch64::P1)
2010 .Case("p2", AArch64::P2)
2011 .Case("p3", AArch64::P3)
2012 .Case("p4", AArch64::P4)
2013 .Case("p5", AArch64::P5)
2014 .Case("p6", AArch64::P6)
2015 .Case("p7", AArch64::P7)
2016 .Case("p8", AArch64::P8)
2017 .Case("p9", AArch64::P9)
2018 .Case("p10", AArch64::P10)
2019 .Case("p11", AArch64::P11)
2020 .Case("p12", AArch64::P12)
2021 .Case("p13", AArch64::P13)
2022 .Case("p14", AArch64::P14)
2023 .Case("p15", AArch64::P15)
2024 .Default(0);
2025}
2026
Tim Northover3b0846e2014-05-24 12:50:23 +00002027bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2028 SMLoc &EndLoc) {
2029 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002030 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002031 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002032 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002033}
2034
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002035// Matches a register name or register alias previously defined by '.req'
2036unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002037 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002038 unsigned RegNum = 0;
2039 if ((RegNum = matchSVEDataVectorRegName(Name)))
2040 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2041
Sander de Smalencd6be962017-12-20 11:02:42 +00002042 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2043 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2044
Sander de Smalenc067c302017-12-20 09:45:45 +00002045 if ((RegNum = MatchNeonVectorRegName(Name)))
2046 return Kind == RegKind::NeonVector ? RegNum : 0;
2047
2048 // The parsed register must be of RegKind Scalar
2049 if ((RegNum = MatchRegisterName(Name)))
2050 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002051
Florian Hahnc4422242017-11-07 13:07:50 +00002052 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002053 // Handle a few common aliases of registers.
2054 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2055 .Case("fp", AArch64::FP)
2056 .Case("lr", AArch64::LR)
2057 .Case("x31", AArch64::XZR)
2058 .Case("w31", AArch64::WZR)
2059 .Default(0))
2060 return Kind == RegKind::Scalar ? RegNum : 0;
2061
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002062 // Check for aliases registered via .req. Canonicalize to lower case.
2063 // That's more consistent since register names are case insensitive, and
2064 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2065 auto Entry = RegisterReqs.find(Name.lower());
2066 if (Entry == RegisterReqs.end())
2067 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002068
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002069 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002070 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002071 RegNum = Entry->getValue().second;
2072 }
2073 return RegNum;
2074}
2075
Sander de Smalen50d87022018-04-19 07:35:08 +00002076/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002077/// Identifier when called, and if it is a register name the token is eaten and
2078/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002079OperandMatchResultTy
2080AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002081 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002082 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002083 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002084 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002085
2086 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002087 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2088 if (Reg == 0)
2089 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002090
Sander de Smalen50d87022018-04-19 07:35:08 +00002091 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002092 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002093 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002094}
2095
Tim Northover3b0846e2014-05-24 12:50:23 +00002096/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002097OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002098AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002099 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002100 SMLoc S = getLoc();
2101
2102 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2103 Error(S, "Expected cN operand where 0 <= N <= 15");
2104 return MatchOperand_ParseFail;
2105 }
2106
2107 StringRef Tok = Parser.getTok().getIdentifier();
2108 if (Tok[0] != 'c' && Tok[0] != 'C') {
2109 Error(S, "Expected cN operand where 0 <= N <= 15");
2110 return MatchOperand_ParseFail;
2111 }
2112
2113 uint32_t CRNum;
2114 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2115 if (BadNum || CRNum > 15) {
2116 Error(S, "Expected cN operand where 0 <= N <= 15");
2117 return MatchOperand_ParseFail;
2118 }
2119
2120 Parser.Lex(); // Eat identifier token.
2121 Operands.push_back(
2122 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2123 return MatchOperand_Success;
2124}
2125
2126/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002127template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002128OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002129AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002130 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002131 SMLoc S = getLoc();
2132 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002133
2134 auto LookupByName = [](StringRef N) {
2135 if (IsSVEPrefetch) {
2136 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2137 return Optional<unsigned>(Res->Encoding);
2138 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2139 return Optional<unsigned>(Res->Encoding);
2140 return Optional<unsigned>();
2141 };
2142
2143 auto LookupByEncoding = [](unsigned E) {
2144 if (IsSVEPrefetch) {
2145 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2146 return Optional<StringRef>(Res->Name);
2147 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2148 return Optional<StringRef>(Res->Name);
2149 return Optional<StringRef>();
2150 };
2151 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2152
Tim Northover3b0846e2014-05-24 12:50:23 +00002153 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002154 // Eat optional hash.
2155 if (parseOptionalToken(AsmToken::Hash) ||
2156 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002157 const MCExpr *ImmVal;
2158 if (getParser().parseExpression(ImmVal))
2159 return MatchOperand_ParseFail;
2160
2161 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2162 if (!MCE) {
2163 TokError("immediate value expected for prefetch operand");
2164 return MatchOperand_ParseFail;
2165 }
2166 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002167 if (prfop > MaxVal) {
2168 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2169 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002170 return MatchOperand_ParseFail;
2171 }
2172
Sander de Smalen93380372018-05-14 11:54:41 +00002173 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002174 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002175 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002176 return MatchOperand_Success;
2177 }
2178
2179 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002180 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002181 return MatchOperand_ParseFail;
2182 }
2183
Sander de Smalen93380372018-05-14 11:54:41 +00002184 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002185 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002186 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002187 return MatchOperand_ParseFail;
2188 }
2189
2190 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002191 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002192 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002193 return MatchOperand_Success;
2194}
2195
Oliver Stannarda34e4702015-12-01 10:48:51 +00002196/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002197OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002198AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2199 MCAsmParser &Parser = getParser();
2200 SMLoc S = getLoc();
2201 const AsmToken &Tok = Parser.getTok();
2202 if (Tok.isNot(AsmToken::Identifier)) {
2203 TokError("invalid operand for instruction");
2204 return MatchOperand_ParseFail;
2205 }
2206
Tim Northovere6ae6762016-07-05 21:23:04 +00002207 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2208 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002209 TokError("invalid operand for instruction");
2210 return MatchOperand_ParseFail;
2211 }
2212
2213 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002214 Operands.push_back(AArch64Operand::CreatePSBHint(
2215 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002216 return MatchOperand_Success;
2217}
2218
Tim Northover3b0846e2014-05-24 12:50:23 +00002219/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2220/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002221OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002222AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002223 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002224 SMLoc S = getLoc();
2225 const MCExpr *Expr;
2226
2227 if (Parser.getTok().is(AsmToken::Hash)) {
2228 Parser.Lex(); // Eat hash token.
2229 }
2230
2231 if (parseSymbolicImmVal(Expr))
2232 return MatchOperand_ParseFail;
2233
2234 AArch64MCExpr::VariantKind ELFRefKind;
2235 MCSymbolRefExpr::VariantKind DarwinRefKind;
2236 int64_t Addend;
2237 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2238 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2239 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2240 // No modifier was specified at all; this is the syntax for an ELF basic
2241 // ADRP relocation (unfortunately).
2242 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002243 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002244 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2245 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2246 Addend != 0) {
2247 Error(S, "gotpage label reference not allowed an addend");
2248 return MatchOperand_ParseFail;
2249 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2250 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2251 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2252 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2253 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2254 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2255 // The operand must be an @page or @gotpage qualified symbolref.
2256 Error(S, "page or gotpage label reference expected");
2257 return MatchOperand_ParseFail;
2258 }
2259 }
2260
2261 // We have either a label reference possibly with addend or an immediate. The
2262 // addend is a raw value here. The linker will adjust it to only reference the
2263 // page.
2264 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2265 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2266
2267 return MatchOperand_Success;
2268}
2269
2270/// tryParseAdrLabel - Parse and validate a source label for the ADR
2271/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002272OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002273AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2274 SMLoc S = getLoc();
2275 const MCExpr *Expr;
2276
Nirav Davee833c6c2016-11-08 18:31:04 +00002277 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002278 if (getParser().parseExpression(Expr))
2279 return MatchOperand_ParseFail;
2280
2281 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2282 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2283
2284 return MatchOperand_Success;
2285}
2286
2287/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002288OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002289AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002290 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002291 SMLoc S = getLoc();
2292
Nirav Davee833c6c2016-11-08 18:31:04 +00002293 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002294
2295 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002296 bool isNegative = parseOptionalToken(AsmToken::Minus);
2297
Tim Northover3b0846e2014-05-24 12:50:23 +00002298 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002299 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002300 int64_t Val;
Sander de Smalenbdf09fe2018-05-30 09:54:19 +00002301 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002302 Val = Tok.getIntVal();
Sander de Smalenbdf09fe2018-05-30 09:54:19 +00002303 if (Val > 255 || isNegative) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002304 TokError("encoded floating point value out of range");
2305 return MatchOperand_ParseFail;
2306 }
2307 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002308 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002309 if (isNegative)
2310 RealVal.changeSign();
2311
Tim Northover3b0846e2014-05-24 12:50:23 +00002312 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002313 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002314
John Brawn5ca5daa2017-04-20 10:13:54 +00002315 // Check for out of range values. As an exception we let Zero through,
2316 // but as tokens instead of an FPImm so that it can be matched by the
2317 // appropriate alias if one exists.
2318 if (RealVal.isPosZero()) {
2319 Parser.Lex(); // Eat the token.
2320 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2321 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2322 return MatchOperand_Success;
2323 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002324 TokError("expected compatible register or floating-point constant");
2325 return MatchOperand_ParseFail;
2326 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002327 }
2328 Parser.Lex(); // Eat the token.
2329 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2330 return MatchOperand_Success;
2331 }
2332
2333 if (!Hash)
2334 return MatchOperand_NoMatch;
2335
2336 TokError("invalid floating point immediate");
2337 return MatchOperand_ParseFail;
2338}
2339
Sander de Smalen62770792018-05-25 09:47:52 +00002340/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2341/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002342OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002343AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002344 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002345 SMLoc S = getLoc();
2346
2347 if (Parser.getTok().is(AsmToken::Hash))
2348 Parser.Lex(); // Eat '#'
2349 else if (Parser.getTok().isNot(AsmToken::Integer))
2350 // Operand should start from # or should be integer, emit error otherwise.
2351 return MatchOperand_NoMatch;
2352
2353 const MCExpr *Imm;
2354 if (parseSymbolicImmVal(Imm))
2355 return MatchOperand_ParseFail;
2356 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002357 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002358 Operands.push_back(
2359 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002360 return MatchOperand_Success;
2361 }
2362
2363 // Eat ','
2364 Parser.Lex();
2365
2366 // The optional operand must be "lsl #N" where N is non-negative.
2367 if (!Parser.getTok().is(AsmToken::Identifier) ||
2368 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2369 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2370 return MatchOperand_ParseFail;
2371 }
2372
2373 // Eat 'lsl'
2374 Parser.Lex();
2375
Nirav Davee833c6c2016-11-08 18:31:04 +00002376 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002377
2378 if (Parser.getTok().isNot(AsmToken::Integer)) {
2379 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2380 return MatchOperand_ParseFail;
2381 }
2382
2383 int64_t ShiftAmount = Parser.getTok().getIntVal();
2384
2385 if (ShiftAmount < 0) {
2386 Error(Parser.getTok().getLoc(), "positive shift amount required");
2387 return MatchOperand_ParseFail;
2388 }
2389 Parser.Lex(); // Eat the number
2390
Sander de Smalen62770792018-05-25 09:47:52 +00002391 // Just in case the optional lsl #0 is used for immediates other than zero.
2392 if (ShiftAmount == 0 && Imm != 0) {
2393 SMLoc E = Parser.getTok().getLoc();
2394 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2395 return MatchOperand_Success;
2396 }
2397
Tim Northover3b0846e2014-05-24 12:50:23 +00002398 SMLoc E = Parser.getTok().getLoc();
2399 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2400 S, E, getContext()));
2401 return MatchOperand_Success;
2402}
2403
2404/// parseCondCodeString - Parse a Condition Code string.
2405AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2406 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2407 .Case("eq", AArch64CC::EQ)
2408 .Case("ne", AArch64CC::NE)
2409 .Case("cs", AArch64CC::HS)
2410 .Case("hs", AArch64CC::HS)
2411 .Case("cc", AArch64CC::LO)
2412 .Case("lo", AArch64CC::LO)
2413 .Case("mi", AArch64CC::MI)
2414 .Case("pl", AArch64CC::PL)
2415 .Case("vs", AArch64CC::VS)
2416 .Case("vc", AArch64CC::VC)
2417 .Case("hi", AArch64CC::HI)
2418 .Case("ls", AArch64CC::LS)
2419 .Case("ge", AArch64CC::GE)
2420 .Case("lt", AArch64CC::LT)
2421 .Case("gt", AArch64CC::GT)
2422 .Case("le", AArch64CC::LE)
2423 .Case("al", AArch64CC::AL)
2424 .Case("nv", AArch64CC::NV)
2425 .Default(AArch64CC::Invalid);
2426 return CC;
2427}
2428
2429/// parseCondCode - Parse a Condition Code operand.
2430bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2431 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002432 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002433 SMLoc S = getLoc();
2434 const AsmToken &Tok = Parser.getTok();
2435 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2436
2437 StringRef Cond = Tok.getString();
2438 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2439 if (CC == AArch64CC::Invalid)
2440 return TokError("invalid condition code");
2441 Parser.Lex(); // Eat identifier token.
2442
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002443 if (invertCondCode) {
2444 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2445 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002446 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002447 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002448
2449 Operands.push_back(
2450 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2451 return false;
2452}
2453
2454/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2455/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002456OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002457AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002458 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002459 const AsmToken &Tok = Parser.getTok();
2460 std::string LowerID = Tok.getString().lower();
2461 AArch64_AM::ShiftExtendType ShOp =
2462 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2463 .Case("lsl", AArch64_AM::LSL)
2464 .Case("lsr", AArch64_AM::LSR)
2465 .Case("asr", AArch64_AM::ASR)
2466 .Case("ror", AArch64_AM::ROR)
2467 .Case("msl", AArch64_AM::MSL)
2468 .Case("uxtb", AArch64_AM::UXTB)
2469 .Case("uxth", AArch64_AM::UXTH)
2470 .Case("uxtw", AArch64_AM::UXTW)
2471 .Case("uxtx", AArch64_AM::UXTX)
2472 .Case("sxtb", AArch64_AM::SXTB)
2473 .Case("sxth", AArch64_AM::SXTH)
2474 .Case("sxtw", AArch64_AM::SXTW)
2475 .Case("sxtx", AArch64_AM::SXTX)
2476 .Default(AArch64_AM::InvalidShiftExtend);
2477
2478 if (ShOp == AArch64_AM::InvalidShiftExtend)
2479 return MatchOperand_NoMatch;
2480
2481 SMLoc S = Tok.getLoc();
2482 Parser.Lex();
2483
Nirav Davee833c6c2016-11-08 18:31:04 +00002484 bool Hash = parseOptionalToken(AsmToken::Hash);
2485
Tim Northover3b0846e2014-05-24 12:50:23 +00002486 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2487 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2488 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2489 ShOp == AArch64_AM::MSL) {
2490 // We expect a number here.
2491 TokError("expected #imm after shift specifier");
2492 return MatchOperand_ParseFail;
2493 }
2494
Chad Rosier2ff37b82016-12-27 16:58:09 +00002495 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002496 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2497 Operands.push_back(
2498 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2499 return MatchOperand_Success;
2500 }
2501
Chad Rosier2ff37b82016-12-27 16:58:09 +00002502 // Make sure we do actually have a number, identifier or a parenthesized
2503 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002504 SMLoc E = Parser.getTok().getLoc();
2505 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002506 !Parser.getTok().is(AsmToken::LParen) &&
2507 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002508 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002509 return MatchOperand_ParseFail;
2510 }
2511
2512 const MCExpr *ImmVal;
2513 if (getParser().parseExpression(ImmVal))
2514 return MatchOperand_ParseFail;
2515
2516 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2517 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002518 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002519 return MatchOperand_ParseFail;
2520 }
2521
Jim Grosbach57fd2622014-09-23 22:16:02 +00002522 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002523 Operands.push_back(AArch64Operand::CreateShiftExtend(
2524 ShOp, MCE->getValue(), true, S, E, getContext()));
2525 return MatchOperand_Success;
2526}
2527
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002528static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2529 if (FBS[AArch64::HasV8_1aOps])
2530 Str += "ARMv8.1a";
2531 else if (FBS[AArch64::HasV8_2aOps])
2532 Str += "ARMv8.2a";
2533 else
2534 Str += "(unknown)";
2535}
2536
2537void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2538 SMLoc S) {
2539 const uint16_t Op2 = Encoding & 7;
2540 const uint16_t Cm = (Encoding & 0x78) >> 3;
2541 const uint16_t Cn = (Encoding & 0x780) >> 7;
2542 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2543
2544 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2545
2546 Operands.push_back(
2547 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2548 Operands.push_back(
2549 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2550 Operands.push_back(
2551 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2552 Expr = MCConstantExpr::create(Op2, getContext());
2553 Operands.push_back(
2554 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2555}
2556
Tim Northover3b0846e2014-05-24 12:50:23 +00002557/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2558/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2559bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2560 OperandVector &Operands) {
2561 if (Name.find('.') != StringRef::npos)
2562 return TokError("invalid operand");
2563
2564 Mnemonic = Name;
2565 Operands.push_back(
2566 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2567
Rafael Espindola961d4692014-11-11 05:18:41 +00002568 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002569 const AsmToken &Tok = Parser.getTok();
2570 StringRef Op = Tok.getString();
2571 SMLoc S = Tok.getLoc();
2572
Tim Northover3b0846e2014-05-24 12:50:23 +00002573 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002574 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2575 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002576 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002577 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2578 std::string Str("IC " + std::string(IC->Name) + " requires ");
2579 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2580 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002581 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002582 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002583 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002584 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2585 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002586 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002587 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2588 std::string Str("DC " + std::string(DC->Name) + " requires ");
2589 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2590 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002591 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002592 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002593 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002594 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2595 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002596 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002597 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2598 std::string Str("AT " + std::string(AT->Name) + " requires ");
2599 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2600 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002601 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002602 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002603 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002604 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2605 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002606 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002607 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2608 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2609 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2610 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002611 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002612 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002613 }
2614
Tim Northover3b0846e2014-05-24 12:50:23 +00002615 Parser.Lex(); // Eat operand.
2616
2617 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2618 bool HasRegister = false;
2619
2620 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002621 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002622 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2623 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002624 HasRegister = true;
2625 }
2626
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002627 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002628 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002629 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002630 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002631
Nirav Davee833c6c2016-11-08 18:31:04 +00002632 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2633 return true;
2634
Tim Northover3b0846e2014-05-24 12:50:23 +00002635 return false;
2636}
2637
Alex Bradbury58eba092016-11-01 16:32:05 +00002638OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002639AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002640 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002641 const AsmToken &Tok = Parser.getTok();
2642
2643 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002644 if (parseOptionalToken(AsmToken::Hash) ||
2645 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002646 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002647 const MCExpr *ImmVal;
2648 SMLoc ExprLoc = getLoc();
2649 if (getParser().parseExpression(ImmVal))
2650 return MatchOperand_ParseFail;
2651 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2652 if (!MCE) {
2653 Error(ExprLoc, "immediate value expected for barrier operand");
2654 return MatchOperand_ParseFail;
2655 }
2656 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2657 Error(ExprLoc, "barrier operand out of range");
2658 return MatchOperand_ParseFail;
2659 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002660 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2661 Operands.push_back(AArch64Operand::CreateBarrier(
2662 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002663 return MatchOperand_Success;
2664 }
2665
2666 if (Tok.isNot(AsmToken::Identifier)) {
2667 TokError("invalid operand for instruction");
2668 return MatchOperand_ParseFail;
2669 }
2670
Tim Northover3b0846e2014-05-24 12:50:23 +00002671 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002672 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2673 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002674 TokError("'sy' or #imm operand expected");
2675 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002676 } else if (!DB) {
2677 TokError("invalid barrier option name");
2678 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002679 }
2680
Tim Northovere6ae6762016-07-05 21:23:04 +00002681 Operands.push_back(AArch64Operand::CreateBarrier(
2682 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002683 Parser.Lex(); // Consume the option
2684
2685 return MatchOperand_Success;
2686}
2687
Alex Bradbury58eba092016-11-01 16:32:05 +00002688OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002689AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002690 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002691 const AsmToken &Tok = Parser.getTok();
2692
2693 if (Tok.isNot(AsmToken::Identifier))
2694 return MatchOperand_NoMatch;
2695
Tim Northovere6ae6762016-07-05 21:23:04 +00002696 int MRSReg, MSRReg;
2697 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2698 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2699 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2700 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2701 } else
2702 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002703
Tim Northovere6ae6762016-07-05 21:23:04 +00002704 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2705 unsigned PStateImm = -1;
2706 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2707 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002708
Tim Northovere6ae6762016-07-05 21:23:04 +00002709 Operands.push_back(
2710 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2711 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002712 Parser.Lex(); // Eat identifier
2713
2714 return MatchOperand_Success;
2715}
2716
Florian Hahnc4422242017-11-07 13:07:50 +00002717/// tryParseNeonVectorRegister - Parse a vector register operand.
2718bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002719 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002720 if (Parser.getTok().isNot(AsmToken::Identifier))
2721 return true;
2722
2723 SMLoc S = getLoc();
2724 // Check for a vector register specifier first.
2725 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002726 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002727 OperandMatchResultTy Res =
2728 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2729 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002730 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002731
2732 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2733 if (!KindRes)
2734 return true;
2735
2736 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002737 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002738 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2739 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002740
Tim Northover3b0846e2014-05-24 12:50:23 +00002741 // If there was an explicit qualifier, that goes on as a literal text
2742 // operand.
2743 if (!Kind.empty())
2744 Operands.push_back(
2745 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2746
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002747 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2748}
2749
2750OperandMatchResultTy
2751AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002752 SMLoc SIdx = getLoc();
2753 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002754 const MCExpr *ImmVal;
2755 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002756 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002757 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2758 if (!MCE) {
2759 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002760 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002761 }
2762
2763 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002764
Nirav Davee833c6c2016-11-08 18:31:04 +00002765 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002766 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002767
2768 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2769 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002770 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002771 }
2772
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002773 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002774}
2775
Sander de Smalen73937b72018-04-11 07:36:10 +00002776// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002777// optional kind specifier. If it is a register specifier, eat the token
2778// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002779OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002780AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002781 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002782 MCAsmParser &Parser = getParser();
2783 const AsmToken &Tok = Parser.getTok();
2784
Florian Hahn91f11e52017-11-07 16:45:48 +00002785 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002786 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002787
2788 StringRef Name = Tok.getString();
2789 // If there is a kind specifier, it's separated from the register name by
2790 // a '.'.
2791 size_t Start = 0, Next = Name.find('.');
2792 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002793 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002794
2795 if (RegNum) {
2796 if (Next != StringRef::npos) {
2797 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002798 if (!isValidVectorKind(Kind, MatchKind)) {
2799 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002800 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002801 }
2802 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002803 Parser.Lex(); // Eat the register token.
2804
2805 Reg = RegNum;
2806 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002807 }
2808
Sander de Smalen8e607342017-11-15 15:44:43 +00002809 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002810}
2811
Sander de Smalencd6be962017-12-20 11:02:42 +00002812/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2813OperandMatchResultTy
2814AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2815 // Check for a SVE predicate register specifier first.
2816 const SMLoc S = getLoc();
2817 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002818 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002819 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002820 if (Res != MatchOperand_Success)
2821 return Res;
2822
Sander de Smalen73937b72018-04-11 07:36:10 +00002823 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2824 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002825 return MatchOperand_NoMatch;
2826
Sander de Smalen73937b72018-04-11 07:36:10 +00002827 unsigned ElementWidth = KindRes->second;
2828 Operands.push_back(AArch64Operand::CreateVectorReg(
2829 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2830 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002831
Sander de Smalen7868e742018-01-09 11:17:06 +00002832 // Not all predicates are followed by a '/m' or '/z'.
2833 MCAsmParser &Parser = getParser();
2834 if (Parser.getTok().isNot(AsmToken::Slash))
2835 return MatchOperand_Success;
2836
2837 // But when they do they shouldn't have an element type suffix.
2838 if (!Kind.empty()) {
2839 Error(S, "not expecting size suffix");
2840 return MatchOperand_ParseFail;
2841 }
2842
2843 // Add a literal slash as operand
2844 Operands.push_back(
2845 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2846
2847 Parser.Lex(); // Eat the slash.
2848
2849 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002850 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002851 if (Pred != "z" && Pred != "m") {
2852 Error(getLoc(), "expecting 'm' or 'z' predication");
2853 return MatchOperand_ParseFail;
2854 }
2855
2856 // Add zero/merge token.
2857 const char *ZM = Pred == "z" ? "z" : "m";
2858 Operands.push_back(
2859 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2860
2861 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002862 return MatchOperand_Success;
2863}
2864
Sander de Smalen50d87022018-04-19 07:35:08 +00002865/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002866bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002867 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002868 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002869 return false;
2870
Sander de Smalen149916d2018-04-20 07:24:20 +00002871 // Otherwise try for a scalar register.
2872 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
2873 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002874
Sander de Smalen149916d2018-04-20 07:24:20 +00002875 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002876}
2877
2878bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002879 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002880 bool HasELFModifier = false;
2881 AArch64MCExpr::VariantKind RefKind;
2882
Nirav Davee833c6c2016-11-08 18:31:04 +00002883 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002884 HasELFModifier = true;
2885
Nirav Davee833c6c2016-11-08 18:31:04 +00002886 if (Parser.getTok().isNot(AsmToken::Identifier))
2887 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002888
2889 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2890 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2891 .Case("lo12", AArch64MCExpr::VK_LO12)
2892 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2893 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2894 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2895 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2896 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2897 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2898 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2899 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2900 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2901 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2902 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2903 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2904 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2905 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2906 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2907 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2908 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2909 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2910 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2911 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2912 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2913 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2914 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2915 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2916 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2917 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2918 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2919 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2920 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2921 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2922 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2923 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2924 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2925 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002926 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2927 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002928 .Default(AArch64MCExpr::VK_INVALID);
2929
Nirav Davee833c6c2016-11-08 18:31:04 +00002930 if (RefKind == AArch64MCExpr::VK_INVALID)
2931 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002932
2933 Parser.Lex(); // Eat identifier
2934
Nirav Davee833c6c2016-11-08 18:31:04 +00002935 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002936 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002937 }
2938
2939 if (getParser().parseExpression(ImmVal))
2940 return true;
2941
2942 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002943 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002944
2945 return false;
2946}
2947
Sander de Smalen650234b2018-04-12 11:40:52 +00002948template <RegKind VectorKind>
2949OperandMatchResultTy
2950AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
2951 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002952 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00002953 if (!Parser.getTok().is(AsmToken::LCurly))
2954 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002955
2956 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00002957 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00002958 bool NoMatchIsError) {
2959 auto RegTok = Parser.getTok();
2960 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
2961 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002962 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00002963 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002964 llvm_unreachable("Expected a valid vector kind");
2965 }
2966
Sander de Smalen650234b2018-04-12 11:40:52 +00002967 if (RegTok.isNot(AsmToken::Identifier) ||
2968 ParseRes == MatchOperand_ParseFail ||
2969 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
2970 Error(Loc, "vector register expected");
2971 return MatchOperand_ParseFail;
2972 }
2973
2974 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002975 };
2976
Tim Northover3b0846e2014-05-24 12:50:23 +00002977 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00002978 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00002979 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00002980
Tim Northover3b0846e2014-05-24 12:50:23 +00002981 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002982 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002983 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
2984
2985 // Put back the original left bracket if there was no match, so that
2986 // different types of list-operands can be matched (e.g. SVE, Neon).
2987 if (ParseRes == MatchOperand_NoMatch)
2988 Parser.getLexer().UnLex(LCurly);
2989
2990 if (ParseRes != MatchOperand_Success)
2991 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002992
Tim Northover3b0846e2014-05-24 12:50:23 +00002993 int64_t PrevReg = FirstReg;
2994 unsigned Count = 1;
2995
Nirav Davee833c6c2016-11-08 18:31:04 +00002996 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002997 SMLoc Loc = getLoc();
2998 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002999
Sander de Smalen50d87022018-04-19 07:35:08 +00003000 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003001 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3002 if (ParseRes != MatchOperand_Success)
3003 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003004
Tim Northover3b0846e2014-05-24 12:50:23 +00003005 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003006 if (Kind != NextKind) {
3007 Error(Loc, "mismatched register size suffix");
3008 return MatchOperand_ParseFail;
3009 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003010
3011 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3012
3013 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003014 Error(Loc, "invalid number of vectors");
3015 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003016 }
3017
3018 Count += Space;
3019 }
3020 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003021 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003022 SMLoc Loc = getLoc();
3023 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003024 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003025 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3026 if (ParseRes != MatchOperand_Success)
3027 return ParseRes;
3028
Tim Northover3b0846e2014-05-24 12:50:23 +00003029 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003030 if (Kind != NextKind) {
3031 Error(Loc, "mismatched register size suffix");
3032 return MatchOperand_ParseFail;
3033 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003034
3035 // Registers must be incremental (with wraparound at 31)
3036 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003037 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3038 Error(Loc, "registers must be sequential");
3039 return MatchOperand_ParseFail;
3040 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003041
3042 PrevReg = Reg;
3043 ++Count;
3044 }
3045 }
3046
Nirav Davee833c6c2016-11-08 18:31:04 +00003047 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003048 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003049
Sander de Smalen650234b2018-04-12 11:40:52 +00003050 if (Count > 4) {
3051 Error(S, "invalid number of vectors");
3052 return MatchOperand_ParseFail;
3053 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003054
3055 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003056 unsigned ElementWidth = 0;
3057 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003058 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003059 std::tie(NumElements, ElementWidth) = *VK;
3060 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003061
3062 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003063 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3064 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003065
Sander de Smalen650234b2018-04-12 11:40:52 +00003066 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003067}
3068
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003069/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3070bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003071 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3072 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003073 return true;
3074
3075 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3076}
3077
Alex Bradbury58eba092016-11-01 16:32:05 +00003078OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003079AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003080 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003081
Sander de Smalen50d87022018-04-19 07:35:08 +00003082 unsigned RegNum;
3083 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3084 if (Res != MatchOperand_Success)
3085 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003086
Nirav Davee833c6c2016-11-08 18:31:04 +00003087 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003088 Operands.push_back(AArch64Operand::CreateReg(
3089 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003090 return MatchOperand_Success;
3091 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003092
Nirav Davee833c6c2016-11-08 18:31:04 +00003093 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003094
Sander de Smalen50d87022018-04-19 07:35:08 +00003095 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003096 Error(getLoc(), "index must be absent or #0");
3097 return MatchOperand_ParseFail;
3098 }
3099
3100 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003101 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003102 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3103 Error(getLoc(), "index must be absent or #0");
3104 return MatchOperand_ParseFail;
3105 }
3106
Sander de Smalen50d87022018-04-19 07:35:08 +00003107 Operands.push_back(AArch64Operand::CreateReg(
3108 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003109 return MatchOperand_Success;
3110}
3111
Sander de Smalen149916d2018-04-20 07:24:20 +00003112template <bool ParseShiftExtend>
3113OperandMatchResultTy
3114AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3115 SMLoc StartLoc = getLoc();
3116
3117 unsigned RegNum;
3118 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3119 if (Res != MatchOperand_Success)
3120 return Res;
3121
3122 // No shift/extend is the default.
3123 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3124 Operands.push_back(AArch64Operand::CreateReg(
3125 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
3126 return MatchOperand_Success;
3127 }
3128
3129 // Eat the comma
3130 getParser().Lex();
3131
3132 // Match the shift
3133 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3134 Res = tryParseOptionalShiftExtend(ExtOpnd);
3135 if (Res != MatchOperand_Success)
3136 return Res;
3137
3138 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
3139 Operands.push_back(AArch64Operand::CreateReg(RegNum, RegKind::Scalar,
3140 StartLoc, Ext->getEndLoc(), getContext(),
3141 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3142 Ext->hasShiftExtendAmount()));
3143
3144 return MatchOperand_Success;
3145}
3146
Sander de Smalen5c625982018-04-13 12:56:14 +00003147bool AArch64AsmParser::parseOptionalMulVl(OperandVector &Operands) {
3148 MCAsmParser &Parser = getParser();
3149
3150 // Some SVE instructions have a decoration after the immediate, i.e.
3151 // "mul vl". We parse them here and add tokens, which must be present in the
3152 // asm string in the tablegen instruction.
3153 if (!Parser.getTok().getString().equals_lower("mul") ||
3154 !Parser.getLexer().peekTok().getString().equals_lower("vl"))
3155 return true;
3156
3157 SMLoc S = getLoc();
3158 Operands.push_back(
3159 AArch64Operand::CreateToken("mul", false, S, getContext()));
3160 Parser.Lex(); // Eat the "mul"
3161
3162 S = getLoc();
3163 Operands.push_back(
3164 AArch64Operand::CreateToken("vl", false, S, getContext()));
3165 Parser.Lex(); // Eat the "vl"
3166
3167 return false;
3168}
3169
Tim Northover3b0846e2014-05-24 12:50:23 +00003170/// parseOperand - Parse a arm instruction operand. For now this parses the
3171/// operand regardless of the mnemonic.
3172bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3173 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003174 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003175
3176 OperandMatchResultTy ResTy =
3177 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3178
Tim Northover3b0846e2014-05-24 12:50:23 +00003179 // Check if the current operand has a custom associated parser, if so, try to
3180 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003181 if (ResTy == MatchOperand_Success)
3182 return false;
3183 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3184 // there was a match, but an error occurred, in which case, just return that
3185 // the operand parsing failed.
3186 if (ResTy == MatchOperand_ParseFail)
3187 return true;
3188
3189 // Nothing custom, so do general case parsing.
3190 SMLoc S, E;
3191 switch (getLexer().getKind()) {
3192 default: {
3193 SMLoc S = getLoc();
3194 const MCExpr *Expr;
3195 if (parseSymbolicImmVal(Expr))
3196 return Error(S, "invalid operand");
3197
3198 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3199 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3200 return false;
3201 }
3202 case AsmToken::LBrac: {
3203 SMLoc Loc = Parser.getTok().getLoc();
3204 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3205 getContext()));
3206 Parser.Lex(); // Eat '['
3207
3208 // There's no comma after a '[', so we can parse the next operand
3209 // immediately.
3210 return parseOperand(Operands, false, false);
3211 }
3212 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003213 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003214 case AsmToken::Identifier: {
3215 // If we're expecting a Condition Code operand, then just parse that.
3216 if (isCondCode)
3217 return parseCondCode(Operands, invertCondCode);
3218
3219 // If it's a register name, parse it.
3220 if (!parseRegister(Operands))
3221 return false;
3222
Sander de Smalen5c625982018-04-13 12:56:14 +00003223 // See if this is a "mul vl" decoration used by SVE instructions.
3224 if (!parseOptionalMulVl(Operands))
3225 return false;
3226
Tim Northover3b0846e2014-05-24 12:50:23 +00003227 // This could be an optional "shift" or "extend" operand.
3228 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3229 // We can only continue if no tokens were eaten.
3230 if (GotShift != MatchOperand_NoMatch)
3231 return GotShift;
3232
3233 // This was not a register so parse other operands that start with an
3234 // identifier (like labels) as expressions and create them as immediates.
3235 const MCExpr *IdVal;
3236 S = getLoc();
3237 if (getParser().parseExpression(IdVal))
3238 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003239 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3240 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3241 return false;
3242 }
3243 case AsmToken::Integer:
3244 case AsmToken::Real:
3245 case AsmToken::Hash: {
3246 // #42 -> immediate.
3247 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003248
3249 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003250
3251 // Parse a negative sign
3252 bool isNegative = false;
3253 if (Parser.getTok().is(AsmToken::Minus)) {
3254 isNegative = true;
3255 // We need to consume this token only when we have a Real, otherwise
3256 // we let parseSymbolicImmVal take care of it
3257 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3258 Parser.Lex();
3259 }
3260
3261 // The only Real that should come through here is a literal #0.0 for
3262 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3263 // so convert the value.
3264 const AsmToken &Tok = Parser.getTok();
3265 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003266 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003267 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3268 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3269 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3270 Mnemonic != "fcmlt")
3271 return TokError("unexpected floating point literal");
3272 else if (IntVal != 0 || isNegative)
3273 return TokError("expected floating-point constant #0.0");
3274 Parser.Lex(); // Eat the token.
3275
3276 Operands.push_back(
3277 AArch64Operand::CreateToken("#0", false, S, getContext()));
3278 Operands.push_back(
3279 AArch64Operand::CreateToken(".0", false, S, getContext()));
3280 return false;
3281 }
3282
3283 const MCExpr *ImmVal;
3284 if (parseSymbolicImmVal(ImmVal))
3285 return true;
3286
3287 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3288 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3289 return false;
3290 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003291 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003292 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003293 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003294 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003295 Parser.Lex(); // Eat '='
3296 const MCExpr *SubExprVal;
3297 if (getParser().parseExpression(SubExprVal))
3298 return true;
3299
David Peixottoae5ba762014-07-18 16:05:14 +00003300 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003301 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003302 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003303
3304 bool IsXReg =
3305 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3306 Operands[1]->getReg());
3307
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003308 MCContext& Ctx = getContext();
3309 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3310 // 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 +00003311 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003312 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3313 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3314 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3315 ShiftAmt += 16;
3316 Imm >>= 16;
3317 }
3318 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3319 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3320 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003321 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003322 if (ShiftAmt)
3323 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3324 ShiftAmt, true, S, E, Ctx));
3325 return false;
3326 }
David Peixottoae5ba762014-07-18 16:05:14 +00003327 APInt Simm = APInt(64, Imm << ShiftAmt);
3328 // check if the immediate is an unsigned or signed 32-bit int for W regs
3329 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3330 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003331 }
3332 // 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 +00003333 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003334 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003335 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3336 return false;
3337 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003338 }
3339}
3340
3341/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3342/// operands.
3343bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3344 StringRef Name, SMLoc NameLoc,
3345 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003346 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003347 Name = StringSwitch<StringRef>(Name.lower())
3348 .Case("beq", "b.eq")
3349 .Case("bne", "b.ne")
3350 .Case("bhs", "b.hs")
3351 .Case("bcs", "b.cs")
3352 .Case("blo", "b.lo")
3353 .Case("bcc", "b.cc")
3354 .Case("bmi", "b.mi")
3355 .Case("bpl", "b.pl")
3356 .Case("bvs", "b.vs")
3357 .Case("bvc", "b.vc")
3358 .Case("bhi", "b.hi")
3359 .Case("bls", "b.ls")
3360 .Case("bge", "b.ge")
3361 .Case("blt", "b.lt")
3362 .Case("bgt", "b.gt")
3363 .Case("ble", "b.le")
3364 .Case("bal", "b.al")
3365 .Case("bnv", "b.nv")
3366 .Default(Name);
3367
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003368 // First check for the AArch64-specific .req directive.
3369 if (Parser.getTok().is(AsmToken::Identifier) &&
3370 Parser.getTok().getIdentifier() == ".req") {
3371 parseDirectiveReq(Name, NameLoc);
3372 // We always return 'error' for this, as we're done with this
3373 // statement and don't need to match the 'instruction."
3374 return true;
3375 }
3376
Tim Northover3b0846e2014-05-24 12:50:23 +00003377 // Create the leading tokens for the mnemonic, split by '.' characters.
3378 size_t Start = 0, Next = Name.find('.');
3379 StringRef Head = Name.slice(Start, Next);
3380
3381 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003382 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3383 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003384
3385 Operands.push_back(
3386 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3387 Mnemonic = Head;
3388
3389 // Handle condition codes for a branch mnemonic
3390 if (Head == "b" && Next != StringRef::npos) {
3391 Start = Next;
3392 Next = Name.find('.', Start + 1);
3393 Head = Name.slice(Start + 1, Next);
3394
3395 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3396 (Head.data() - Name.data()));
3397 AArch64CC::CondCode CC = parseCondCodeString(Head);
3398 if (CC == AArch64CC::Invalid)
3399 return Error(SuffixLoc, "invalid condition code");
3400 Operands.push_back(
3401 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3402 Operands.push_back(
3403 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3404 }
3405
3406 // Add the remaining tokens in the mnemonic.
3407 while (Next != StringRef::npos) {
3408 Start = Next;
3409 Next = Name.find('.', Start + 1);
3410 Head = Name.slice(Start, Next);
3411 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3412 (Head.data() - Name.data()) + 1);
3413 Operands.push_back(
3414 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3415 }
3416
3417 // Conditional compare instructions have a Condition Code operand, which needs
3418 // to be parsed and an immediate operand created.
3419 bool condCodeFourthOperand =
3420 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3421 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3422 Head == "csinc" || Head == "csinv" || Head == "csneg");
3423
3424 // These instructions are aliases to some of the conditional select
3425 // instructions. However, the condition code is inverted in the aliased
3426 // instruction.
3427 //
3428 // FIXME: Is this the correct way to handle these? Or should the parser
3429 // generate the aliased instructions directly?
3430 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3431 bool condCodeThirdOperand =
3432 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3433
3434 // Read the remaining operands.
3435 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3436 // Read the first operand.
3437 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003438 return true;
3439 }
3440
3441 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003442 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003443 // Parse and remember the operand.
3444 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3445 (N == 3 && condCodeThirdOperand) ||
3446 (N == 2 && condCodeSecondOperand),
3447 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003448 return true;
3449 }
3450
3451 // After successfully parsing some operands there are two special cases to
3452 // consider (i.e. notional operands not separated by commas). Both are due
3453 // to memory specifiers:
3454 // + An RBrac will end an address for load/store/prefetch
3455 // + An '!' will indicate a pre-indexed operation.
3456 //
3457 // It's someone else's responsibility to make sure these tokens are sane
3458 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003459
Nirav Davee833c6c2016-11-08 18:31:04 +00003460 SMLoc RLoc = Parser.getTok().getLoc();
3461 if (parseOptionalToken(AsmToken::RBrac))
3462 Operands.push_back(
3463 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3464 SMLoc ELoc = Parser.getTok().getLoc();
3465 if (parseOptionalToken(AsmToken::Exclaim))
3466 Operands.push_back(
3467 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003468
3469 ++N;
3470 }
3471 }
3472
Nirav Davee833c6c2016-11-08 18:31:04 +00003473 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3474 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003475
Tim Northover3b0846e2014-05-24 12:50:23 +00003476 return false;
3477}
3478
3479// FIXME: This entire function is a giant hack to provide us with decent
3480// operand range validation/diagnostics until TableGen/MC can be extended
3481// to support autogeneration of this kind of validation.
3482bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3483 SmallVectorImpl<SMLoc> &Loc) {
3484 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3485 // Check for indexed addressing modes w/ the base register being the
3486 // same as a destination/source register or pair load where
3487 // the Rt == Rt2. All of those are undefined behaviour.
3488 switch (Inst.getOpcode()) {
3489 case AArch64::LDPSWpre:
3490 case AArch64::LDPWpost:
3491 case AArch64::LDPWpre:
3492 case AArch64::LDPXpost:
3493 case AArch64::LDPXpre: {
3494 unsigned Rt = Inst.getOperand(1).getReg();
3495 unsigned Rt2 = Inst.getOperand(2).getReg();
3496 unsigned Rn = Inst.getOperand(3).getReg();
3497 if (RI->isSubRegisterEq(Rn, Rt))
3498 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3499 "is also a destination");
3500 if (RI->isSubRegisterEq(Rn, Rt2))
3501 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3502 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003503 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003504 }
3505 case AArch64::LDPDi:
3506 case AArch64::LDPQi:
3507 case AArch64::LDPSi:
3508 case AArch64::LDPSWi:
3509 case AArch64::LDPWi:
3510 case AArch64::LDPXi: {
3511 unsigned Rt = Inst.getOperand(0).getReg();
3512 unsigned Rt2 = Inst.getOperand(1).getReg();
3513 if (Rt == Rt2)
3514 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3515 break;
3516 }
3517 case AArch64::LDPDpost:
3518 case AArch64::LDPDpre:
3519 case AArch64::LDPQpost:
3520 case AArch64::LDPQpre:
3521 case AArch64::LDPSpost:
3522 case AArch64::LDPSpre:
3523 case AArch64::LDPSWpost: {
3524 unsigned Rt = Inst.getOperand(1).getReg();
3525 unsigned Rt2 = Inst.getOperand(2).getReg();
3526 if (Rt == Rt2)
3527 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3528 break;
3529 }
3530 case AArch64::STPDpost:
3531 case AArch64::STPDpre:
3532 case AArch64::STPQpost:
3533 case AArch64::STPQpre:
3534 case AArch64::STPSpost:
3535 case AArch64::STPSpre:
3536 case AArch64::STPWpost:
3537 case AArch64::STPWpre:
3538 case AArch64::STPXpost:
3539 case AArch64::STPXpre: {
3540 unsigned Rt = Inst.getOperand(1).getReg();
3541 unsigned Rt2 = Inst.getOperand(2).getReg();
3542 unsigned Rn = Inst.getOperand(3).getReg();
3543 if (RI->isSubRegisterEq(Rn, Rt))
3544 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3545 "is also a source");
3546 if (RI->isSubRegisterEq(Rn, Rt2))
3547 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3548 "is also a source");
3549 break;
3550 }
3551 case AArch64::LDRBBpre:
3552 case AArch64::LDRBpre:
3553 case AArch64::LDRHHpre:
3554 case AArch64::LDRHpre:
3555 case AArch64::LDRSBWpre:
3556 case AArch64::LDRSBXpre:
3557 case AArch64::LDRSHWpre:
3558 case AArch64::LDRSHXpre:
3559 case AArch64::LDRSWpre:
3560 case AArch64::LDRWpre:
3561 case AArch64::LDRXpre:
3562 case AArch64::LDRBBpost:
3563 case AArch64::LDRBpost:
3564 case AArch64::LDRHHpost:
3565 case AArch64::LDRHpost:
3566 case AArch64::LDRSBWpost:
3567 case AArch64::LDRSBXpost:
3568 case AArch64::LDRSHWpost:
3569 case AArch64::LDRSHXpost:
3570 case AArch64::LDRSWpost:
3571 case AArch64::LDRWpost:
3572 case AArch64::LDRXpost: {
3573 unsigned Rt = Inst.getOperand(1).getReg();
3574 unsigned Rn = Inst.getOperand(2).getReg();
3575 if (RI->isSubRegisterEq(Rn, Rt))
3576 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3577 "is also a source");
3578 break;
3579 }
3580 case AArch64::STRBBpost:
3581 case AArch64::STRBpost:
3582 case AArch64::STRHHpost:
3583 case AArch64::STRHpost:
3584 case AArch64::STRWpost:
3585 case AArch64::STRXpost:
3586 case AArch64::STRBBpre:
3587 case AArch64::STRBpre:
3588 case AArch64::STRHHpre:
3589 case AArch64::STRHpre:
3590 case AArch64::STRWpre:
3591 case AArch64::STRXpre: {
3592 unsigned Rt = Inst.getOperand(1).getReg();
3593 unsigned Rn = Inst.getOperand(2).getReg();
3594 if (RI->isSubRegisterEq(Rn, Rt))
3595 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3596 "is also a source");
3597 break;
3598 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003599 case AArch64::STXRB:
3600 case AArch64::STXRH:
3601 case AArch64::STXRW:
3602 case AArch64::STXRX:
3603 case AArch64::STLXRB:
3604 case AArch64::STLXRH:
3605 case AArch64::STLXRW:
3606 case AArch64::STLXRX: {
3607 unsigned Rs = Inst.getOperand(0).getReg();
3608 unsigned Rt = Inst.getOperand(1).getReg();
3609 unsigned Rn = Inst.getOperand(2).getReg();
3610 if (RI->isSubRegisterEq(Rt, Rs) ||
3611 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3612 return Error(Loc[0],
3613 "unpredictable STXR instruction, status is also a source");
3614 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003615 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003616 case AArch64::STXPW:
3617 case AArch64::STXPX:
3618 case AArch64::STLXPW:
3619 case AArch64::STLXPX: {
3620 unsigned Rs = Inst.getOperand(0).getReg();
3621 unsigned Rt1 = Inst.getOperand(1).getReg();
3622 unsigned Rt2 = Inst.getOperand(2).getReg();
3623 unsigned Rn = Inst.getOperand(3).getReg();
3624 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3625 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3626 return Error(Loc[0],
3627 "unpredictable STXP instruction, status is also a source");
3628 break;
3629 }
3630 }
3631
Tim Northover3b0846e2014-05-24 12:50:23 +00003632
3633 // Now check immediate ranges. Separate from the above as there is overlap
3634 // in the instructions being checked and this keeps the nested conditionals
3635 // to a minimum.
3636 switch (Inst.getOpcode()) {
3637 case AArch64::ADDSWri:
3638 case AArch64::ADDSXri:
3639 case AArch64::ADDWri:
3640 case AArch64::ADDXri:
3641 case AArch64::SUBSWri:
3642 case AArch64::SUBSXri:
3643 case AArch64::SUBWri:
3644 case AArch64::SUBXri: {
3645 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3646 // some slight duplication here.
3647 if (Inst.getOperand(2).isExpr()) {
3648 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3649 AArch64MCExpr::VariantKind ELFRefKind;
3650 MCSymbolRefExpr::VariantKind DarwinRefKind;
3651 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003652 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3653
3654 // Only allow these with ADDXri.
3655 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3656 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3657 Inst.getOpcode() == AArch64::ADDXri)
3658 return false;
3659
3660 // Only allow these with ADDXri/ADDWri
3661 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3662 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3663 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3664 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3665 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3666 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3667 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003668 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3669 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3670 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003671 (Inst.getOpcode() == AArch64::ADDXri ||
3672 Inst.getOpcode() == AArch64::ADDWri))
3673 return false;
3674
3675 // Don't allow symbol refs in the immediate field otherwise
3676 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3677 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3678 // 'cmp w0, 'borked')
3679 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003680 }
Diana Picusc93518d2016-10-11 09:17:47 +00003681 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003682 }
3683 return false;
3684 }
3685 default:
3686 return false;
3687 }
3688}
3689
Craig Topper05515562017-10-26 06:46:41 +00003690static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3691 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003692
3693bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3694 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003695 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003696 case Match_InvalidTiedOperand:
3697 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003698 case Match_MissingFeature:
3699 return Error(Loc,
3700 "instruction requires a CPU feature not currently enabled");
3701 case Match_InvalidOperand:
3702 return Error(Loc, "invalid operand for instruction");
3703 case Match_InvalidSuffix:
3704 return Error(Loc, "invalid type suffix for instruction");
3705 case Match_InvalidCondCode:
3706 return Error(Loc, "expected AArch64 condition code");
3707 case Match_AddSubRegExtendSmall:
3708 return Error(Loc,
3709 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3710 case Match_AddSubRegExtendLarge:
3711 return Error(Loc,
3712 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3713 case Match_AddSubSecondSource:
3714 return Error(Loc,
3715 "expected compatible register, symbol or integer in range [0, 4095]");
3716 case Match_LogicalSecondSource:
3717 return Error(Loc, "expected compatible register or logical immediate");
3718 case Match_InvalidMovImm32Shift:
3719 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3720 case Match_InvalidMovImm64Shift:
3721 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3722 case Match_AddSubRegShift32:
3723 return Error(Loc,
3724 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3725 case Match_AddSubRegShift64:
3726 return Error(Loc,
3727 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3728 case Match_InvalidFPImm:
3729 return Error(Loc,
3730 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003731 case Match_InvalidMemoryIndexedSImm6:
3732 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003733 case Match_InvalidMemoryIndexedSImm5:
3734 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003735 case Match_InvalidMemoryIndexed1SImm4:
3736 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003737 case Match_InvalidMemoryIndexed2SImm4:
3738 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003739 case Match_InvalidMemoryIndexed3SImm4:
3740 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003741 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00003742 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00003743 case Match_InvalidMemoryIndexed16SImm4:
3744 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00003745 case Match_InvalidMemoryIndexed1SImm6:
3746 return Error(Loc, "index must be an integer in range [-32, 31].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003747 case Match_InvalidMemoryIndexedSImm9:
3748 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00003749 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00003750 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003751 case Match_InvalidMemoryIndexed4SImm7:
3752 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3753 case Match_InvalidMemoryIndexed8SImm7:
3754 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3755 case Match_InvalidMemoryIndexed16SImm7:
3756 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00003757 case Match_InvalidMemoryIndexed8UImm5:
3758 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
3759 case Match_InvalidMemoryIndexed4UImm5:
3760 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
3761 case Match_InvalidMemoryIndexed2UImm5:
3762 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00003763 case Match_InvalidMemoryIndexed8UImm6:
3764 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
3765 case Match_InvalidMemoryIndexed4UImm6:
3766 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
3767 case Match_InvalidMemoryIndexed2UImm6:
3768 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
3769 case Match_InvalidMemoryIndexed1UImm6:
3770 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003771 case Match_InvalidMemoryWExtend8:
3772 return Error(Loc,
3773 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3774 case Match_InvalidMemoryWExtend16:
3775 return Error(Loc,
3776 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3777 case Match_InvalidMemoryWExtend32:
3778 return Error(Loc,
3779 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3780 case Match_InvalidMemoryWExtend64:
3781 return Error(Loc,
3782 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3783 case Match_InvalidMemoryWExtend128:
3784 return Error(Loc,
3785 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3786 case Match_InvalidMemoryXExtend8:
3787 return Error(Loc,
3788 "expected 'lsl' or 'sxtx' with optional shift of #0");
3789 case Match_InvalidMemoryXExtend16:
3790 return Error(Loc,
3791 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3792 case Match_InvalidMemoryXExtend32:
3793 return Error(Loc,
3794 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3795 case Match_InvalidMemoryXExtend64:
3796 return Error(Loc,
3797 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3798 case Match_InvalidMemoryXExtend128:
3799 return Error(Loc,
3800 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3801 case Match_InvalidMemoryIndexed1:
3802 return Error(Loc, "index must be an integer in range [0, 4095].");
3803 case Match_InvalidMemoryIndexed2:
3804 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3805 case Match_InvalidMemoryIndexed4:
3806 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3807 case Match_InvalidMemoryIndexed8:
3808 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3809 case Match_InvalidMemoryIndexed16:
3810 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003811 case Match_InvalidImm0_1:
3812 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003813 case Match_InvalidImm0_7:
3814 return Error(Loc, "immediate must be an integer in range [0, 7].");
3815 case Match_InvalidImm0_15:
3816 return Error(Loc, "immediate must be an integer in range [0, 15].");
3817 case Match_InvalidImm0_31:
3818 return Error(Loc, "immediate must be an integer in range [0, 31].");
3819 case Match_InvalidImm0_63:
3820 return Error(Loc, "immediate must be an integer in range [0, 63].");
3821 case Match_InvalidImm0_127:
3822 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003823 case Match_InvalidImm0_255:
3824 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003825 case Match_InvalidImm0_65535:
3826 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3827 case Match_InvalidImm1_8:
3828 return Error(Loc, "immediate must be an integer in range [1, 8].");
3829 case Match_InvalidImm1_16:
3830 return Error(Loc, "immediate must be an integer in range [1, 16].");
3831 case Match_InvalidImm1_32:
3832 return Error(Loc, "immediate must be an integer in range [1, 32].");
3833 case Match_InvalidImm1_64:
3834 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00003835 case Match_InvalidSVEAddSubImm8:
3836 return Error(Loc, "immediate must be an integer in range [0, 255]"
3837 " with a shift amount of 0");
3838 case Match_InvalidSVEAddSubImm16:
3839 case Match_InvalidSVEAddSubImm32:
3840 case Match_InvalidSVEAddSubImm64:
3841 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
3842 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00003843 case Match_InvalidSVECpyImm8:
3844 return Error(Loc, "immediate must be an integer in range [-128, 255]"
3845 " with a shift amount of 0");
3846 case Match_InvalidSVECpyImm16:
3847 case Match_InvalidSVECpyImm32:
3848 case Match_InvalidSVECpyImm64:
3849 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
3850 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003851 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00003852 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003853 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00003854 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003855 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00003856 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003857 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00003858 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003859 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00003860 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003861 case Match_InvalidSVEIndexRange0_63:
3862 return Error(Loc, "vector lane must be an integer in range [0, 63].");
3863 case Match_InvalidSVEIndexRange0_31:
3864 return Error(Loc, "vector lane must be an integer in range [0, 31].");
3865 case Match_InvalidSVEIndexRange0_15:
3866 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3867 case Match_InvalidSVEIndexRange0_7:
3868 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3869 case Match_InvalidSVEIndexRange0_3:
3870 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003871 case Match_InvalidLabel:
3872 return Error(Loc, "expected label or encodable integer pc offset");
3873 case Match_MRS:
3874 return Error(Loc, "expected readable system register");
3875 case Match_MSR:
3876 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003877 case Match_InvalidComplexRotationEven:
3878 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3879 case Match_InvalidComplexRotationOdd:
3880 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003881 case Match_MnemonicFail: {
3882 std::string Suggestion = AArch64MnemonicSpellCheck(
3883 ((AArch64Operand &)*Operands[0]).getToken(),
3884 ComputeAvailableFeatures(STI->getFeatureBits()));
3885 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3886 }
Sander de Smalen367694b2018-04-20 08:54:49 +00003887 case Match_InvalidGPR64shifted8:
3888 return Error(Loc, "register must be x0..x30 or xzr, without shift");
3889 case Match_InvalidGPR64shifted16:
3890 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
3891 case Match_InvalidGPR64shifted32:
3892 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
3893 case Match_InvalidGPR64shifted64:
3894 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
3895 case Match_InvalidGPR64NoXZRshifted8:
3896 return Error(Loc, "register must be x0..x30 without shift");
3897 case Match_InvalidGPR64NoXZRshifted16:
3898 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
3899 case Match_InvalidGPR64NoXZRshifted32:
3900 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
3901 case Match_InvalidGPR64NoXZRshifted64:
3902 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00003903 case Match_InvalidZPR32UXTW8:
3904 case Match_InvalidZPR32SXTW8:
3905 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
3906 case Match_InvalidZPR32UXTW16:
3907 case Match_InvalidZPR32SXTW16:
3908 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
3909 case Match_InvalidZPR32UXTW32:
3910 case Match_InvalidZPR32SXTW32:
3911 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
3912 case Match_InvalidZPR32UXTW64:
3913 case Match_InvalidZPR32SXTW64:
3914 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
3915 case Match_InvalidZPR64UXTW8:
3916 case Match_InvalidZPR64SXTW8:
3917 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
3918 case Match_InvalidZPR64UXTW16:
3919 case Match_InvalidZPR64SXTW16:
3920 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
3921 case Match_InvalidZPR64UXTW32:
3922 case Match_InvalidZPR64SXTW32:
3923 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
3924 case Match_InvalidZPR64UXTW64:
3925 case Match_InvalidZPR64SXTW64:
3926 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
3927 case Match_InvalidZPR64LSL8:
3928 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
3929 case Match_InvalidZPR64LSL16:
3930 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
3931 case Match_InvalidZPR64LSL32:
3932 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
3933 case Match_InvalidZPR64LSL64:
3934 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00003935 case Match_InvalidZPR0:
3936 return Error(Loc, "expected register without element width sufix");
3937 case Match_InvalidZPR8:
3938 case Match_InvalidZPR16:
3939 case Match_InvalidZPR32:
3940 case Match_InvalidZPR64:
3941 case Match_InvalidZPR128:
3942 return Error(Loc, "invalid element width");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003943 case Match_InvalidSVEPattern:
3944 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003945 case Match_InvalidSVEPredicateAnyReg:
3946 case Match_InvalidSVEPredicateBReg:
3947 case Match_InvalidSVEPredicateHReg:
3948 case Match_InvalidSVEPredicateSReg:
3949 case Match_InvalidSVEPredicateDReg:
3950 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003951 case Match_InvalidSVEPredicate3bAnyReg:
3952 case Match_InvalidSVEPredicate3bBReg:
3953 case Match_InvalidSVEPredicate3bHReg:
3954 case Match_InvalidSVEPredicate3bSReg:
3955 case Match_InvalidSVEPredicate3bDReg:
3956 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003957 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003958 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003959 }
3960}
3961
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003962static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003963
3964bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3965 OperandVector &Operands,
3966 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003967 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003968 bool MatchingInlineAsm) {
3969 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003970 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3971 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003972
David Blaikie960ea3f2014-06-08 16:18:35 +00003973 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003974 unsigned NumOperands = Operands.size();
3975
3976 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003977 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3978 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003979 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003980 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003981 if (Op3CE) {
3982 uint64_t Op3Val = Op3CE->getValue();
3983 uint64_t NewOp3Val = 0;
3984 uint64_t NewOp4Val = 0;
3985 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003986 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003987 NewOp3Val = (32 - Op3Val) & 0x1f;
3988 NewOp4Val = 31 - Op3Val;
3989 } else {
3990 NewOp3Val = (64 - Op3Val) & 0x3f;
3991 NewOp4Val = 63 - Op3Val;
3992 }
3993
Jim Grosbach13760bd2015-05-30 01:25:56 +00003994 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3995 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003996
3997 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003998 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003999 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004000 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4001 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4002 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004003 }
4004 }
Tim Northover03b99f62015-04-30 18:28:58 +00004005 } else if (NumOperands == 4 && Tok == "bfc") {
4006 // FIXME: Horrible hack to handle BFC->BFM alias.
4007 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4008 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4009 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4010
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004011 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004012 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4013 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4014
4015 if (LSBCE && WidthCE) {
4016 uint64_t LSB = LSBCE->getValue();
4017 uint64_t Width = WidthCE->getValue();
4018
4019 uint64_t RegWidth = 0;
4020 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4021 Op1.getReg()))
4022 RegWidth = 64;
4023 else
4024 RegWidth = 32;
4025
4026 if (LSB >= RegWidth)
4027 return Error(LSBOp.getStartLoc(),
4028 "expected integer in range [0, 31]");
4029 if (Width < 1 || Width > RegWidth)
4030 return Error(WidthOp.getStartLoc(),
4031 "expected integer in range [1, 32]");
4032
4033 uint64_t ImmR = 0;
4034 if (RegWidth == 32)
4035 ImmR = (32 - LSB) & 0x1f;
4036 else
4037 ImmR = (64 - LSB) & 0x3f;
4038
4039 uint64_t ImmS = Width - 1;
4040
4041 if (ImmR != 0 && ImmS >= ImmR)
4042 return Error(WidthOp.getStartLoc(),
4043 "requested insert overflows register");
4044
Jim Grosbach13760bd2015-05-30 01:25:56 +00004045 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4046 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004047 Operands[0] = AArch64Operand::CreateToken(
4048 "bfm", false, Op.getStartLoc(), getContext());
4049 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004050 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4051 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004052 Operands[3] = AArch64Operand::CreateImm(
4053 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4054 Operands.emplace_back(
4055 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4056 WidthOp.getEndLoc(), getContext()));
4057 }
4058 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004059 } else if (NumOperands == 5) {
4060 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4061 // UBFIZ -> UBFM aliases.
4062 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004063 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4064 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4065 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004066
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004067 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004068 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4069 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004070
4071 if (Op3CE && Op4CE) {
4072 uint64_t Op3Val = Op3CE->getValue();
4073 uint64_t Op4Val = Op4CE->getValue();
4074
4075 uint64_t RegWidth = 0;
4076 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004077 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004078 RegWidth = 64;
4079 else
4080 RegWidth = 32;
4081
4082 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004083 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004084 "expected integer in range [0, 31]");
4085 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004086 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004087 "expected integer in range [1, 32]");
4088
4089 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004090 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004091 NewOp3Val = (32 - Op3Val) & 0x1f;
4092 else
4093 NewOp3Val = (64 - Op3Val) & 0x3f;
4094
4095 uint64_t NewOp4Val = Op4Val - 1;
4096
4097 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004098 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004099 "requested insert overflows register");
4100
4101 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004102 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004103 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004104 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004105 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004106 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004107 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004108 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004109 if (Tok == "bfi")
4110 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004111 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004112 else if (Tok == "sbfiz")
4113 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004114 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004115 else if (Tok == "ubfiz")
4116 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004117 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004118 else
4119 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004120 }
4121 }
4122
4123 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4124 // UBFX -> UBFM aliases.
4125 } else if (NumOperands == 5 &&
4126 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004127 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4128 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4129 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004130
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004131 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004132 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4133 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004134
4135 if (Op3CE && Op4CE) {
4136 uint64_t Op3Val = Op3CE->getValue();
4137 uint64_t Op4Val = Op4CE->getValue();
4138
4139 uint64_t RegWidth = 0;
4140 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004141 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004142 RegWidth = 64;
4143 else
4144 RegWidth = 32;
4145
4146 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004147 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004148 "expected integer in range [0, 31]");
4149 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004150 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004151 "expected integer in range [1, 32]");
4152
4153 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4154
4155 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004156 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004157 "requested extract overflows register");
4158
4159 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004160 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004161 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004162 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004163 if (Tok == "bfxil")
4164 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004165 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004166 else if (Tok == "sbfx")
4167 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004168 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004169 else if (Tok == "ubfx")
4170 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004171 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004172 else
4173 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004174 }
4175 }
4176 }
4177 }
Tim Northover9097a072017-12-18 10:36:00 +00004178
4179 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4180 // instruction for FP registers correctly in some rare circumstances. Convert
4181 // it to a safe instruction and warn (because silently changing someone's
4182 // assembly is rude).
4183 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4184 NumOperands == 4 && Tok == "movi") {
4185 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4186 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4187 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4188 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4189 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4190 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4191 if (Suffix.lower() == ".2d" &&
4192 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4193 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4194 " correctly on this CPU, converting to equivalent movi.16b");
4195 // Switch the suffix to .16b.
4196 unsigned Idx = Op1.isToken() ? 1 : 2;
4197 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4198 getContext());
4199 }
4200 }
4201 }
4202
Tim Northover3b0846e2014-05-24 12:50:23 +00004203 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4204 // InstAlias can't quite handle this since the reg classes aren't
4205 // subclasses.
4206 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4207 // The source register can be Wn here, but the matcher expects a
4208 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004209 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004210 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004211 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004212 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4213 Op.getStartLoc(), Op.getEndLoc(),
4214 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004215 }
4216 }
4217 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4218 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004219 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004220 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004221 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004222 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004223 // The source register can be Wn here, but the matcher expects a
4224 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004225 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004226 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004227 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004228 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4229 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004230 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004231 }
4232 }
4233 }
4234 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4235 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004236 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004237 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004238 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004239 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004240 // The source register can be Wn here, but the matcher expects a
4241 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004242 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004243 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004244 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004245 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4246 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004247 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004248 }
4249 }
4250 }
4251
Tim Northover3b0846e2014-05-24 12:50:23 +00004252 MCInst Inst;
4253 // First try to match against the secondary set of tables containing the
4254 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4255 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004256 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004257
4258 // If that fails, try against the alternate table containing long-form NEON:
4259 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004260 if (MatchResult != Match_Success) {
4261 // But first, save the short-form match result: we can use it in case the
4262 // long-form match also fails.
4263 auto ShortFormNEONErrorInfo = ErrorInfo;
4264 auto ShortFormNEONMatchResult = MatchResult;
4265
Tim Northover3b0846e2014-05-24 12:50:23 +00004266 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004267 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004268
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004269 // Now, both matches failed, and the long-form match failed on the mnemonic
4270 // suffix token operand. The short-form match failure is probably more
4271 // relevant: use it instead.
4272 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004273 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004274 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4275 MatchResult = ShortFormNEONMatchResult;
4276 ErrorInfo = ShortFormNEONErrorInfo;
4277 }
4278 }
4279
Tim Northover3b0846e2014-05-24 12:50:23 +00004280 switch (MatchResult) {
4281 case Match_Success: {
4282 // Perform range checking and other semantic validations
4283 SmallVector<SMLoc, 8> OperandLocs;
4284 NumOperands = Operands.size();
4285 for (unsigned i = 1; i < NumOperands; ++i)
4286 OperandLocs.push_back(Operands[i]->getStartLoc());
4287 if (validateInstruction(Inst, OperandLocs))
4288 return true;
4289
4290 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004291 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004292 return false;
4293 }
4294 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004295 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004296 // Special case the error message for the very common case where only
4297 // a single subtarget feature is missing (neon, e.g.).
4298 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004299 uint64_t Mask = 1;
4300 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4301 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004302 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004303 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004304 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004305 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004306 }
4307 return Error(IDLoc, Msg);
4308 }
4309 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004310 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004311 case Match_InvalidOperand: {
4312 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004313
Tim Northover26bb14e2014-08-18 11:49:42 +00004314 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004315 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004316 return Error(IDLoc, "too few operands for instruction",
4317 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004318
David Blaikie960ea3f2014-06-08 16:18:35 +00004319 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004320 if (ErrorLoc == SMLoc())
4321 ErrorLoc = IDLoc;
4322 }
4323 // If the match failed on a suffix token operand, tweak the diagnostic
4324 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004325 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4326 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004327 MatchResult = Match_InvalidSuffix;
4328
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004329 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004330 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004331 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004332 case Match_InvalidMemoryIndexed1:
4333 case Match_InvalidMemoryIndexed2:
4334 case Match_InvalidMemoryIndexed4:
4335 case Match_InvalidMemoryIndexed8:
4336 case Match_InvalidMemoryIndexed16:
4337 case Match_InvalidCondCode:
4338 case Match_AddSubRegExtendSmall:
4339 case Match_AddSubRegExtendLarge:
4340 case Match_AddSubSecondSource:
4341 case Match_LogicalSecondSource:
4342 case Match_AddSubRegShift32:
4343 case Match_AddSubRegShift64:
4344 case Match_InvalidMovImm32Shift:
4345 case Match_InvalidMovImm64Shift:
4346 case Match_InvalidFPImm:
4347 case Match_InvalidMemoryWExtend8:
4348 case Match_InvalidMemoryWExtend16:
4349 case Match_InvalidMemoryWExtend32:
4350 case Match_InvalidMemoryWExtend64:
4351 case Match_InvalidMemoryWExtend128:
4352 case Match_InvalidMemoryXExtend8:
4353 case Match_InvalidMemoryXExtend16:
4354 case Match_InvalidMemoryXExtend32:
4355 case Match_InvalidMemoryXExtend64:
4356 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004357 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004358 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004359 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004360 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004361 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004362 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004363 case Match_InvalidMemoryIndexed4SImm7:
4364 case Match_InvalidMemoryIndexed8SImm7:
4365 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004366 case Match_InvalidMemoryIndexed8UImm5:
4367 case Match_InvalidMemoryIndexed4UImm5:
4368 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004369 case Match_InvalidMemoryIndexed1UImm6:
4370 case Match_InvalidMemoryIndexed2UImm6:
4371 case Match_InvalidMemoryIndexed4UImm6:
4372 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004373 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004374 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004375 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004376 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004377 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004378 case Match_InvalidImm0_7:
4379 case Match_InvalidImm0_15:
4380 case Match_InvalidImm0_31:
4381 case Match_InvalidImm0_63:
4382 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004383 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004384 case Match_InvalidImm0_65535:
4385 case Match_InvalidImm1_8:
4386 case Match_InvalidImm1_16:
4387 case Match_InvalidImm1_32:
4388 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004389 case Match_InvalidSVEAddSubImm8:
4390 case Match_InvalidSVEAddSubImm16:
4391 case Match_InvalidSVEAddSubImm32:
4392 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004393 case Match_InvalidSVECpyImm8:
4394 case Match_InvalidSVECpyImm16:
4395 case Match_InvalidSVECpyImm32:
4396 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004397 case Match_InvalidIndexRange1_1:
4398 case Match_InvalidIndexRange0_15:
4399 case Match_InvalidIndexRange0_7:
4400 case Match_InvalidIndexRange0_3:
4401 case Match_InvalidIndexRange0_1:
4402 case Match_InvalidSVEIndexRange0_63:
4403 case Match_InvalidSVEIndexRange0_31:
4404 case Match_InvalidSVEIndexRange0_15:
4405 case Match_InvalidSVEIndexRange0_7:
4406 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004407 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004408 case Match_InvalidComplexRotationEven:
4409 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004410 case Match_InvalidGPR64shifted8:
4411 case Match_InvalidGPR64shifted16:
4412 case Match_InvalidGPR64shifted32:
4413 case Match_InvalidGPR64shifted64:
4414 case Match_InvalidGPR64NoXZRshifted8:
4415 case Match_InvalidGPR64NoXZRshifted16:
4416 case Match_InvalidGPR64NoXZRshifted32:
4417 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004418 case Match_InvalidZPR32UXTW8:
4419 case Match_InvalidZPR32UXTW16:
4420 case Match_InvalidZPR32UXTW32:
4421 case Match_InvalidZPR32UXTW64:
4422 case Match_InvalidZPR32SXTW8:
4423 case Match_InvalidZPR32SXTW16:
4424 case Match_InvalidZPR32SXTW32:
4425 case Match_InvalidZPR32SXTW64:
4426 case Match_InvalidZPR64UXTW8:
4427 case Match_InvalidZPR64SXTW8:
4428 case Match_InvalidZPR64UXTW16:
4429 case Match_InvalidZPR64SXTW16:
4430 case Match_InvalidZPR64UXTW32:
4431 case Match_InvalidZPR64SXTW32:
4432 case Match_InvalidZPR64UXTW64:
4433 case Match_InvalidZPR64SXTW64:
4434 case Match_InvalidZPR64LSL8:
4435 case Match_InvalidZPR64LSL16:
4436 case Match_InvalidZPR64LSL32:
4437 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004438 case Match_InvalidZPR0:
4439 case Match_InvalidZPR8:
4440 case Match_InvalidZPR16:
4441 case Match_InvalidZPR32:
4442 case Match_InvalidZPR64:
4443 case Match_InvalidZPR128:
Sander de Smalencd6be962017-12-20 11:02:42 +00004444 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004445 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004446 case Match_InvalidSVEPredicateBReg:
4447 case Match_InvalidSVEPredicateHReg:
4448 case Match_InvalidSVEPredicateSReg:
4449 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004450 case Match_InvalidSVEPredicate3bAnyReg:
4451 case Match_InvalidSVEPredicate3bBReg:
4452 case Match_InvalidSVEPredicate3bHReg:
4453 case Match_InvalidSVEPredicate3bSReg:
4454 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004455 case Match_MSR:
4456 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004457 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004458 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004459 // Any time we get here, there's nothing fancy to do. Just get the
4460 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004461 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004462 if (ErrorLoc == SMLoc())
4463 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004464 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004465 }
4466 }
4467
4468 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004469}
4470
4471/// ParseDirective parses the arm specific directives
4472bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004473 const MCObjectFileInfo::Environment Format =
4474 getContext().getObjectFileInfo()->getObjectFileType();
4475 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4476 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004477
Tim Northover3b0846e2014-05-24 12:50:23 +00004478 StringRef IDVal = DirectiveID.getIdentifier();
4479 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004480 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004481 parseDirectiveArch(Loc);
4482 else if (IDVal == ".cpu")
4483 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00004484 else if (IDVal == ".tlsdesccall")
4485 parseDirectiveTLSDescCall(Loc);
4486 else if (IDVal == ".ltorg" || IDVal == ".pool")
4487 parseDirectiveLtorg(Loc);
4488 else if (IDVal == ".unreq")
4489 parseDirectiveUnreq(Loc);
4490 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004491 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004492 parseDirectiveInst(Loc);
4493 else
4494 return true;
4495 } else if (IDVal == MCLOHDirectiveName())
4496 parseDirectiveLOH(IDVal, Loc);
4497 else
4498 return true;
4499 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004500}
4501
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004502static const struct {
4503 const char *Name;
4504 const FeatureBitset Features;
4505} ExtensionMap[] = {
4506 { "crc", {AArch64::FeatureCRC} },
4507 { "crypto", {AArch64::FeatureCrypto} },
4508 { "fp", {AArch64::FeatureFPARMv8} },
4509 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004510 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004511 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004512
4513 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004514 { "pan", {} },
4515 { "lor", {} },
4516 { "rdma", {} },
4517 { "profile", {} },
4518};
4519
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004520/// parseDirectiveArch
4521/// ::= .arch token
4522bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4523 SMLoc ArchLoc = getLoc();
4524
4525 StringRef Arch, ExtensionString;
4526 std::tie(Arch, ExtensionString) =
4527 getParser().parseStringToEndOfStatement().trim().split('+');
4528
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004529 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4530 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004531 return Error(ArchLoc, "unknown arch name");
4532
4533 if (parseToken(AsmToken::EndOfStatement))
4534 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004535
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004536 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004537 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004538 AArch64::getArchFeatures(ID, AArch64Features);
4539 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4540 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004541
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004542 MCSubtargetInfo &STI = copySTI();
4543 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4544 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4545
4546 SmallVector<StringRef, 4> RequestedExtensions;
4547 if (!ExtensionString.empty())
4548 ExtensionString.split(RequestedExtensions, '+');
4549
4550 FeatureBitset Features = STI.getFeatureBits();
4551 for (auto Name : RequestedExtensions) {
4552 bool EnableFeature = true;
4553
4554 if (Name.startswith_lower("no")) {
4555 EnableFeature = false;
4556 Name = Name.substr(2);
4557 }
4558
4559 for (const auto &Extension : ExtensionMap) {
4560 if (Extension.Name != Name)
4561 continue;
4562
4563 if (Extension.Features.none())
4564 report_fatal_error("unsupported architectural extension: " + Name);
4565
4566 FeatureBitset ToggleFeatures = EnableFeature
4567 ? (~Features & Extension.Features)
4568 : ( Features & Extension.Features);
4569 uint64_t Features =
4570 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4571 setAvailableFeatures(Features);
4572 break;
4573 }
4574 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004575 return false;
4576}
4577
Tim Northover8b96c7e2017-05-15 19:42:15 +00004578static SMLoc incrementLoc(SMLoc L, int Offset) {
4579 return SMLoc::getFromPointer(L.getPointer() + Offset);
4580}
4581
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004582/// parseDirectiveCPU
4583/// ::= .cpu id
4584bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004585 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004586
4587 StringRef CPU, ExtensionString;
4588 std::tie(CPU, ExtensionString) =
4589 getParser().parseStringToEndOfStatement().trim().split('+');
4590
Nirav Davee833c6c2016-11-08 18:31:04 +00004591 if (parseToken(AsmToken::EndOfStatement))
4592 return true;
4593
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004594 SmallVector<StringRef, 4> RequestedExtensions;
4595 if (!ExtensionString.empty())
4596 ExtensionString.split(RequestedExtensions, '+');
4597
4598 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4599 // once that is tablegen'ed
4600 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004601 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004602 return false;
4603 }
4604
4605 MCSubtargetInfo &STI = copySTI();
4606 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004607 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004608
4609 FeatureBitset Features = STI.getFeatureBits();
4610 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004611 // Advance source location past '+'.
4612 CurLoc = incrementLoc(CurLoc, 1);
4613
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004614 bool EnableFeature = true;
4615
4616 if (Name.startswith_lower("no")) {
4617 EnableFeature = false;
4618 Name = Name.substr(2);
4619 }
4620
Tim Northover8b96c7e2017-05-15 19:42:15 +00004621 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004622 for (const auto &Extension : ExtensionMap) {
4623 if (Extension.Name != Name)
4624 continue;
4625
4626 if (Extension.Features.none())
4627 report_fatal_error("unsupported architectural extension: " + Name);
4628
4629 FeatureBitset ToggleFeatures = EnableFeature
4630 ? (~Features & Extension.Features)
4631 : ( Features & Extension.Features);
4632 uint64_t Features =
4633 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4634 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004635 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004636
4637 break;
4638 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004639
4640 if (!FoundExtension)
4641 Error(CurLoc, "unsupported architectural extension");
4642
4643 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004644 }
4645 return false;
4646}
4647
Chad Rosierdcd2a302014-10-22 20:35:57 +00004648/// parseDirectiveInst
4649/// ::= .inst opcode [, ...]
4650bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004651 if (getLexer().is(AsmToken::EndOfStatement))
4652 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004653
Nirav Davee833c6c2016-11-08 18:31:04 +00004654 auto parseOp = [&]() -> bool {
4655 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004656 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004657 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4658 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004659 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004660 if (check(!Value, L, "expected constant expression"))
4661 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004662 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004663 return false;
4664 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004665
Nirav Davee833c6c2016-11-08 18:31:04 +00004666 if (parseMany(parseOp))
4667 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004668 return false;
4669}
4670
Tim Northover3b0846e2014-05-24 12:50:23 +00004671// parseDirectiveTLSDescCall:
4672// ::= .tlsdesccall symbol
4673bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4674 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004675 if (check(getParser().parseIdentifier(Name), L,
4676 "expected symbol after directive") ||
4677 parseToken(AsmToken::EndOfStatement))
4678 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004679
Jim Grosbach6f482002015-05-18 18:43:14 +00004680 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004681 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4682 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004683
4684 MCInst Inst;
4685 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004686 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004687
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004688 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004689 return false;
4690}
4691
4692/// ::= .loh <lohName | lohId> label1, ..., labelN
4693/// The number of arguments depends on the loh identifier.
4694bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004695 MCLOHType Kind;
4696 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4697 if (getParser().getTok().isNot(AsmToken::Integer))
4698 return TokError("expected an identifier or a number in directive");
4699 // We successfully get a numeric value for the identifier.
4700 // Check if it is valid.
4701 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004702 if (Id <= -1U && !isValidMCLOHType(Id))
4703 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004704 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004705 } else {
4706 StringRef Name = getTok().getIdentifier();
4707 // We successfully parse an identifier.
4708 // Check if it is a recognized one.
4709 int Id = MCLOHNameToId(Name);
4710
4711 if (Id == -1)
4712 return TokError("invalid identifier in directive");
4713 Kind = (MCLOHType)Id;
4714 }
4715 // Consume the identifier.
4716 Lex();
4717 // Get the number of arguments of this LOH.
4718 int NbArgs = MCLOHIdToNbArgs(Kind);
4719
4720 assert(NbArgs != -1 && "Invalid number of arguments");
4721
4722 SmallVector<MCSymbol *, 3> Args;
4723 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4724 StringRef Name;
4725 if (getParser().parseIdentifier(Name))
4726 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004727 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004728
4729 if (Idx + 1 == NbArgs)
4730 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004731 if (parseToken(AsmToken::Comma,
4732 "unexpected token in '" + Twine(IDVal) + "' directive"))
4733 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004734 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004735 if (parseToken(AsmToken::EndOfStatement,
4736 "unexpected token in '" + Twine(IDVal) + "' directive"))
4737 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004738
4739 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4740 return false;
4741}
4742
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004743/// parseDirectiveLtorg
4744/// ::= .ltorg | .pool
4745bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004746 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4747 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004748 getTargetStreamer().emitCurrentConstantPool();
4749 return false;
4750}
4751
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004752/// parseDirectiveReq
4753/// ::= name .req registername
4754bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004755 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004756 Parser.Lex(); // Eat the '.req' token.
4757 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004758 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004759 unsigned RegNum;
4760 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004761
Sander de Smalen50d87022018-04-19 07:35:08 +00004762 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004763 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004764 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004765 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004766
Sander de Smalen50d87022018-04-19 07:35:08 +00004767 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004768 return true;
4769
Sander de Smalen50d87022018-04-19 07:35:08 +00004770 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004771 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004772 }
4773
Sander de Smalen50d87022018-04-19 07:35:08 +00004774 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004775 StringRef Kind;
4776 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004777 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004778 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004779
Sander de Smalen50d87022018-04-19 07:35:08 +00004780 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004781 return true;
4782
Sander de Smalen50d87022018-04-19 07:35:08 +00004783 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004784 return Error(SRegLoc,
4785 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004786 }
4787
Sander de Smalen50d87022018-04-19 07:35:08 +00004788 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00004789 StringRef Kind;
4790 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004791 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004792
Sander de Smalen50d87022018-04-19 07:35:08 +00004793 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00004794 return true;
4795
Sander de Smalen50d87022018-04-19 07:35:08 +00004796 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00004797 return Error(SRegLoc,
4798 "sve predicate register without type specifier expected");
4799 }
4800
Sander de Smalen50d87022018-04-19 07:35:08 +00004801 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00004802 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004803
4804 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004805 if (parseToken(AsmToken::EndOfStatement,
4806 "unexpected input in .req directive"))
4807 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004808
Sander de Smalen8e607342017-11-15 15:44:43 +00004809 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004810 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004811 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4812
Nirav Dave2364748a2016-09-16 18:30:20 +00004813 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004814}
4815
4816/// parseDirectiveUneq
4817/// ::= .unreq registername
4818bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004819 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004820 if (getTok().isNot(AsmToken::Identifier))
4821 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004822 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4823 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004824 if (parseToken(AsmToken::EndOfStatement))
4825 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004826 return false;
4827}
4828
Tim Northover3b0846e2014-05-24 12:50:23 +00004829bool
4830AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4831 AArch64MCExpr::VariantKind &ELFRefKind,
4832 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4833 int64_t &Addend) {
4834 ELFRefKind = AArch64MCExpr::VK_INVALID;
4835 DarwinRefKind = MCSymbolRefExpr::VK_None;
4836 Addend = 0;
4837
4838 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4839 ELFRefKind = AE->getKind();
4840 Expr = AE->getSubExpr();
4841 }
4842
4843 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4844 if (SE) {
4845 // It's a simple symbol reference with no addend.
4846 DarwinRefKind = SE->getKind();
4847 return true;
4848 }
4849
4850 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4851 if (!BE)
4852 return false;
4853
4854 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4855 if (!SE)
4856 return false;
4857 DarwinRefKind = SE->getKind();
4858
4859 if (BE->getOpcode() != MCBinaryExpr::Add &&
4860 BE->getOpcode() != MCBinaryExpr::Sub)
4861 return false;
4862
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004863 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004864 // on here than we can deal with.
4865 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4866 if (!AddendExpr)
4867 return false;
4868
4869 Addend = AddendExpr->getValue();
4870 if (BE->getOpcode() == MCBinaryExpr::Sub)
4871 Addend = -Addend;
4872
4873 // It's some symbol reference + a constant addend, but really
4874 // shouldn't use both Darwin and ELF syntax.
4875 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4876 DarwinRefKind == MCSymbolRefExpr::VK_None;
4877}
4878
4879/// Force static initialization.
4880extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004881 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4882 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4883 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004884}
4885
4886#define GET_REGISTER_MATCHER
4887#define GET_SUBTARGET_FEATURE_NAME
4888#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004889#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004890#include "AArch64GenAsmMatcher.inc"
4891
4892// Define this matcher function after the auto-generated include so we
4893// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004894unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004895 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004896 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004897 // If the kind is a token for a literal immediate, check if our asm
4898 // operand matches. This is for InstAliases which have a fixed-value
4899 // immediate in the syntax.
4900 int64_t ExpectedVal;
4901 switch (Kind) {
4902 default:
4903 return Match_InvalidOperand;
4904 case MCK__35_0:
4905 ExpectedVal = 0;
4906 break;
4907 case MCK__35_1:
4908 ExpectedVal = 1;
4909 break;
4910 case MCK__35_12:
4911 ExpectedVal = 12;
4912 break;
4913 case MCK__35_16:
4914 ExpectedVal = 16;
4915 break;
4916 case MCK__35_2:
4917 ExpectedVal = 2;
4918 break;
4919 case MCK__35_24:
4920 ExpectedVal = 24;
4921 break;
4922 case MCK__35_3:
4923 ExpectedVal = 3;
4924 break;
4925 case MCK__35_32:
4926 ExpectedVal = 32;
4927 break;
4928 case MCK__35_4:
4929 ExpectedVal = 4;
4930 break;
4931 case MCK__35_48:
4932 ExpectedVal = 48;
4933 break;
4934 case MCK__35_6:
4935 ExpectedVal = 6;
4936 break;
4937 case MCK__35_64:
4938 ExpectedVal = 64;
4939 break;
4940 case MCK__35_8:
4941 ExpectedVal = 8;
4942 break;
4943 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004944 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004945 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004946 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004947 if (!CE)
4948 return Match_InvalidOperand;
4949 if (CE->getValue() == ExpectedVal)
4950 return Match_Success;
4951 return Match_InvalidOperand;
4952}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004953
Alex Bradbury58eba092016-11-01 16:32:05 +00004954OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004955AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4956
4957 SMLoc S = getLoc();
4958
4959 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4960 Error(S, "expected register");
4961 return MatchOperand_ParseFail;
4962 }
4963
Sander de Smalen50d87022018-04-19 07:35:08 +00004964 unsigned FirstReg;
4965 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
4966 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004967 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00004968
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004969 const MCRegisterClass &WRegClass =
4970 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4971 const MCRegisterClass &XRegClass =
4972 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4973
4974 bool isXReg = XRegClass.contains(FirstReg),
4975 isWReg = WRegClass.contains(FirstReg);
4976 if (!isXReg && !isWReg) {
4977 Error(S, "expected first even register of a "
4978 "consecutive same-size even/odd register pair");
4979 return MatchOperand_ParseFail;
4980 }
4981
4982 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4983 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4984
4985 if (FirstEncoding & 0x1) {
4986 Error(S, "expected first even register of a "
4987 "consecutive same-size even/odd register pair");
4988 return MatchOperand_ParseFail;
4989 }
4990
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004991 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00004992 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004993 return MatchOperand_ParseFail;
4994 }
4995 // Eat the comma
4996 getParser().Lex();
4997
4998 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00004999 unsigned SecondReg;
5000 Res = tryParseScalarRegister(SecondReg);
5001 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005002 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005003
Eugene Zelenko049b0172017-01-06 00:30:53 +00005004 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005005 (isXReg && !XRegClass.contains(SecondReg)) ||
5006 (isWReg && !WRegClass.contains(SecondReg))) {
5007 Error(E,"expected second odd register of a "
5008 "consecutive same-size even/odd register pair");
5009 return MatchOperand_ParseFail;
5010 }
Joel Jones504bf332016-10-24 13:37:13 +00005011
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005012 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005013 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005014 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5015 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5016 } else {
5017 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5018 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5019 }
5020
Florian Hahnc4422242017-11-07 13:07:50 +00005021 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5022 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005023
5024 return MatchOperand_Success;
5025}
Florian Hahn91f11e52017-11-07 16:45:48 +00005026
Sander de Smaleneb896b12018-04-25 09:26:47 +00005027template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005028OperandMatchResultTy
5029AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005030 const SMLoc S = getLoc();
5031 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005032 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005033 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005034
Sander de Smalen8e607342017-11-15 15:44:43 +00005035 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005036 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005037
5038 if (Res != MatchOperand_Success)
5039 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005040
5041 if (ParseSuffix && Kind.empty())
5042 return MatchOperand_NoMatch;
5043
Sander de Smalen73937b72018-04-11 07:36:10 +00005044 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5045 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005046 return MatchOperand_NoMatch;
5047
Sander de Smalen73937b72018-04-11 07:36:10 +00005048 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005049
5050 // No shift/extend is the default.
5051 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5052 Operands.push_back(AArch64Operand::CreateVectorReg(
5053 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5054
Sander de Smalenc33d6682018-06-04 06:40:55 +00005055 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5056 if (Res == MatchOperand_ParseFail)
5057 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005058 return MatchOperand_Success;
5059 }
5060
5061 // Eat the comma
5062 getParser().Lex();
5063
5064 // Match the shift
5065 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5066 Res = tryParseOptionalShiftExtend(ExtOpnd);
5067 if (Res != MatchOperand_Success)
5068 return Res;
5069
5070 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005071 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005072 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5073 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5074 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005075
5076 return MatchOperand_Success;
5077}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005078
5079OperandMatchResultTy
5080AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5081 MCAsmParser &Parser = getParser();
5082
5083 SMLoc SS = getLoc();
5084 const AsmToken &TokE = Parser.getTok();
5085 bool IsHash = TokE.is(AsmToken::Hash);
5086
5087 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5088 return MatchOperand_NoMatch;
5089
5090 int64_t Pattern;
5091 if (IsHash) {
5092 Parser.Lex(); // Eat hash
5093
5094 // Parse the immediate operand.
5095 const MCExpr *ImmVal;
5096 SS = getLoc();
5097 if (Parser.parseExpression(ImmVal))
5098 return MatchOperand_ParseFail;
5099
5100 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5101 if (!MCE)
5102 return MatchOperand_ParseFail;
5103
5104 Pattern = MCE->getValue();
5105 } else {
5106 // Parse the pattern
5107 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5108 if (!Pat)
5109 return MatchOperand_NoMatch;
5110
5111 Parser.Lex();
5112 Pattern = Pat->Encoding;
5113 assert(Pattern >= 0 && Pattern < 32);
5114 }
5115
5116 Operands.push_back(
5117 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5118 SS, getLoc(), getContext()));
5119
5120 return MatchOperand_Success;
5121}