blob: 031de490885c5f41890941dbc75679cff891304a [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/AArch64AddressingModes.h"
11#include "MCTargetDesc/AArch64MCExpr.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000012#include "MCTargetDesc/AArch64MCTargetDesc.h"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000013#include "MCTargetDesc/AArch64TargetStreamer.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000014#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000015#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000016#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000017#include "llvm/ADT/ArrayRef.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000018#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "llvm/ADT/SmallVector.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000020#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000021#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000023#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000025#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000028#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000029#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000030#include "llvm/MC/MCParser/MCAsmLexer.h"
31#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000032#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000033#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000034#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000035#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSubtargetInfo.h"
38#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000039#include "llvm/MC/MCTargetOptions.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000043#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000044#include "llvm/Support/MathExtras.h"
45#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000046#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000047#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000049#include <cassert>
50#include <cctype>
51#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000052#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000053#include <string>
54#include <tuple>
55#include <utility>
56#include <vector>
57
Tim Northover3b0846e2014-05-24 12:50:23 +000058using namespace llvm;
59
60namespace {
61
Sander de Smalencd6be962017-12-20 11:02:42 +000062enum class RegKind {
63 Scalar,
64 NeonVector,
65 SVEDataVector,
66 SVEPredicateVector
67};
Florian Hahnc4422242017-11-07 13:07:50 +000068
Tim Northover3b0846e2014-05-24 12:50:23 +000069class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000070private:
71 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000072
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000073 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000074 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000075
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000076 AArch64TargetStreamer &getTargetStreamer() {
77 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
78 return static_cast<AArch64TargetStreamer &>(TS);
79 }
80
Rafael Espindola961d4692014-11-11 05:18:41 +000081 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000082
83 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +000084 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +000085 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
86 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +000087 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +000088 bool parseRegister(OperandVector &Operands);
89 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
Sander de Smalenc88f9a12018-04-11 14:10:37 +000090 bool parseNeonVectorList(OperandVector &Operands);
Sander de Smalen5c625982018-04-13 12:56:14 +000091 bool parseOptionalMulVl(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000092 bool parseOperand(OperandVector &Operands, bool isCondCode,
93 bool invertCondCode);
94
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +000095 bool showMatchError(SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000096
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000097 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000098 bool parseDirectiveCPU(SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +000099 bool parseDirectiveInst(SMLoc L);
100
Tim Northover3b0846e2014-05-24 12:50:23 +0000101 bool parseDirectiveTLSDescCall(SMLoc L);
102
103 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000104 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000105
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000106 bool parseDirectiveReq(StringRef Name, SMLoc L);
107 bool parseDirectiveUnreq(SMLoc L);
108
Tim Northover3b0846e2014-05-24 12:50:23 +0000109 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
110 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
111 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000112 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000113 bool MatchingInlineAsm) override;
114/// @name Auto-generated Match Functions
115/// {
116
117#define GET_ASSEMBLER_HEADER
118#include "AArch64GenAsmMatcher.inc"
119
120 /// }
121
Sander de Smalen50d87022018-04-19 07:35:08 +0000122 OperandMatchResultTy tryParseScalarRegister(unsigned &Reg);
123 OperandMatchResultTy tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +0000124 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000125 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
126 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
127 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
128 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
129 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
Sander de Smalen93380372018-05-14 11:54:41 +0000130 template <bool IsSVEPrefetch = false>
Tim Northover3b0846e2014-05-24 12:50:23 +0000131 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000132 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000133 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
134 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
135 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
Sander de Smalen62770792018-05-25 09:47:52 +0000136 OperandMatchResultTy tryParseImmWithOptionalShift(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000137 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000138 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000139 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000140 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Sander de Smalen149916d2018-04-20 07:24:20 +0000141 template <bool ParseShiftExtend>
142 OperandMatchResultTy tryParseGPROperand(OperandVector &Operands);
Sander de Smaleneb896b12018-04-25 09:26:47 +0000143 template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +0000144 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000145 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000146 template <RegKind VectorKind>
147 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
148 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000149 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000150
151public:
152 enum AArch64MatchResultTy {
153 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
154#define GET_OPERAND_DIAGNOSTIC_TYPES
155#include "AArch64GenAsmMatcher.inc"
156 };
Joel Jones504bf332016-10-24 13:37:13 +0000157 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000158
Akira Hatanakab11ef082015-11-14 06:35:56 +0000159 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000160 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000161 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000162 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000163 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000164 MCStreamer &S = getParser().getStreamer();
165 if (S.getTargetStreamer() == nullptr)
166 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000167
Alex Bradbury0a59f182018-05-23 11:17:20 +0000168 // Alias .hword/.word/xword to the target-independent .2byte/.4byte/.8byte
169 // directives as they have the same form and semantics:
170 /// ::= (.hword | .word | .xword ) [ expression (, expression)* ]
171 Parser.addAliasForDirective(".hword", ".2byte");
172 Parser.addAliasForDirective(".word", ".4byte");
173 Parser.addAliasForDirective(".xword", ".8byte");
174
Tim Northover3b0846e2014-05-24 12:50:23 +0000175 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000176 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000177 }
178
179 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
180 SMLoc NameLoc, OperandVector &Operands) override;
181 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
182 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000183 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000184 unsigned Kind) override;
185
186 static bool classifySymbolRef(const MCExpr *Expr,
187 AArch64MCExpr::VariantKind &ELFRefKind,
188 MCSymbolRefExpr::VariantKind &DarwinRefKind,
189 int64_t &Addend);
190};
Tim Northover3b0846e2014-05-24 12:50:23 +0000191
192/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
193/// instruction.
194class AArch64Operand : public MCParsedAsmOperand {
195private:
196 enum KindTy {
197 k_Immediate,
198 k_ShiftedImm,
199 k_CondCode,
200 k_Register,
201 k_VectorList,
202 k_VectorIndex,
203 k_Token,
204 k_SysReg,
205 k_SysCR,
206 k_Prefetch,
207 k_ShiftExtend,
208 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000209 k_Barrier,
210 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000211 } Kind;
212
213 SMLoc StartLoc, EndLoc;
214
215 struct TokOp {
216 const char *Data;
217 unsigned Length;
218 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
219 };
220
Sander de Smalen149916d2018-04-20 07:24:20 +0000221 // Separate shift/extend operand.
222 struct ShiftExtendOp {
223 AArch64_AM::ShiftExtendType Type;
224 unsigned Amount;
225 bool HasExplicitAmount;
226 };
227
Tim Northover3b0846e2014-05-24 12:50:23 +0000228 struct RegOp {
229 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000230 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000231 int ElementWidth;
Sander de Smalen149916d2018-04-20 07:24:20 +0000232
233 // In some cases the shift/extend needs to be explicitly parsed together
234 // with the register, rather than as a separate operand. This is needed
235 // for addressing modes where the instruction as a whole dictates the
236 // scaling/extend, rather than specific bits in the instruction.
237 // By parsing them as a single operand, we avoid the need to pass an
238 // extra operand in all CodeGen patterns (because all operands need to
239 // have an associated value), and we avoid the need to update TableGen to
240 // accept operands that have no associated bits in the instruction.
241 //
242 // An added benefit of parsing them together is that the assembler
243 // can give a sensible diagnostic if the scaling is not correct.
244 //
245 // The default is 'lsl #0' (HasExplicitAmount = false) if no
246 // ShiftExtend is specified.
247 ShiftExtendOp ShiftExtend;
Tim Northover3b0846e2014-05-24 12:50:23 +0000248 };
249
250 struct VectorListOp {
251 unsigned RegNum;
252 unsigned Count;
253 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000254 unsigned ElementWidth;
255 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000256 };
257
258 struct VectorIndexOp {
259 unsigned Val;
260 };
261
262 struct ImmOp {
263 const MCExpr *Val;
264 };
265
266 struct ShiftedImmOp {
267 const MCExpr *Val;
268 unsigned ShiftAmount;
269 };
270
271 struct CondCodeOp {
272 AArch64CC::CondCode Code;
273 };
274
275 struct FPImmOp {
276 unsigned Val; // Encoded 8-bit representation.
277 };
278
279 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000280 const char *Data;
281 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000282 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000283 };
284
285 struct SysRegOp {
286 const char *Data;
287 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000288 uint32_t MRSReg;
289 uint32_t MSRReg;
290 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000291 };
292
293 struct SysCRImmOp {
294 unsigned Val;
295 };
296
297 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000298 const char *Data;
299 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000300 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000301 };
302
Oliver Stannarda34e4702015-12-01 10:48:51 +0000303 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000304 const char *Data;
305 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000306 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000307 };
308
Tim Northover3b0846e2014-05-24 12:50:23 +0000309 struct ExtendOp {
310 unsigned Val;
311 };
312
313 union {
314 struct TokOp Tok;
315 struct RegOp Reg;
316 struct VectorListOp VectorList;
317 struct VectorIndexOp VectorIndex;
318 struct ImmOp Imm;
319 struct ShiftedImmOp ShiftedImm;
320 struct CondCodeOp CondCode;
321 struct FPImmOp FPImm;
322 struct BarrierOp Barrier;
323 struct SysRegOp SysReg;
324 struct SysCRImmOp SysCRImm;
325 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000326 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000327 struct ShiftExtendOp ShiftExtend;
328 };
329
330 // Keep the MCContext around as the MCExprs may need manipulated during
331 // the add<>Operands() calls.
332 MCContext &Ctx;
333
David Blaikie960ea3f2014-06-08 16:18:35 +0000334public:
David Blaikie9f380a32015-03-16 18:06:57 +0000335 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000336
Tim Northover3b0846e2014-05-24 12:50:23 +0000337 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
338 Kind = o.Kind;
339 StartLoc = o.StartLoc;
340 EndLoc = o.EndLoc;
341 switch (Kind) {
342 case k_Token:
343 Tok = o.Tok;
344 break;
345 case k_Immediate:
346 Imm = o.Imm;
347 break;
348 case k_ShiftedImm:
349 ShiftedImm = o.ShiftedImm;
350 break;
351 case k_CondCode:
352 CondCode = o.CondCode;
353 break;
354 case k_FPImm:
355 FPImm = o.FPImm;
356 break;
357 case k_Barrier:
358 Barrier = o.Barrier;
359 break;
360 case k_Register:
361 Reg = o.Reg;
362 break;
363 case k_VectorList:
364 VectorList = o.VectorList;
365 break;
366 case k_VectorIndex:
367 VectorIndex = o.VectorIndex;
368 break;
369 case k_SysReg:
370 SysReg = o.SysReg;
371 break;
372 case k_SysCR:
373 SysCRImm = o.SysCRImm;
374 break;
375 case k_Prefetch:
376 Prefetch = o.Prefetch;
377 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000378 case k_PSBHint:
379 PSBHint = o.PSBHint;
380 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000381 case k_ShiftExtend:
382 ShiftExtend = o.ShiftExtend;
383 break;
384 }
385 }
386
387 /// getStartLoc - Get the location of the first token of this operand.
388 SMLoc getStartLoc() const override { return StartLoc; }
389 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000390 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000391
392 StringRef getToken() const {
393 assert(Kind == k_Token && "Invalid access!");
394 return StringRef(Tok.Data, Tok.Length);
395 }
396
397 bool isTokenSuffix() const {
398 assert(Kind == k_Token && "Invalid access!");
399 return Tok.IsSuffix;
400 }
401
402 const MCExpr *getImm() const {
403 assert(Kind == k_Immediate && "Invalid access!");
404 return Imm.Val;
405 }
406
407 const MCExpr *getShiftedImmVal() const {
408 assert(Kind == k_ShiftedImm && "Invalid access!");
409 return ShiftedImm.Val;
410 }
411
412 unsigned getShiftedImmShift() const {
413 assert(Kind == k_ShiftedImm && "Invalid access!");
414 return ShiftedImm.ShiftAmount;
415 }
416
417 AArch64CC::CondCode getCondCode() const {
418 assert(Kind == k_CondCode && "Invalid access!");
419 return CondCode.Code;
420 }
421
422 unsigned getFPImm() const {
423 assert(Kind == k_FPImm && "Invalid access!");
424 return FPImm.Val;
425 }
426
427 unsigned getBarrier() const {
428 assert(Kind == k_Barrier && "Invalid access!");
429 return Barrier.Val;
430 }
431
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000432 StringRef getBarrierName() const {
433 assert(Kind == k_Barrier && "Invalid access!");
434 return StringRef(Barrier.Data, Barrier.Length);
435 }
436
Tim Northover3b0846e2014-05-24 12:50:23 +0000437 unsigned getReg() const override {
438 assert(Kind == k_Register && "Invalid access!");
439 return Reg.RegNum;
440 }
441
442 unsigned getVectorListStart() const {
443 assert(Kind == k_VectorList && "Invalid access!");
444 return VectorList.RegNum;
445 }
446
447 unsigned getVectorListCount() const {
448 assert(Kind == k_VectorList && "Invalid access!");
449 return VectorList.Count;
450 }
451
452 unsigned getVectorIndex() const {
453 assert(Kind == k_VectorIndex && "Invalid access!");
454 return VectorIndex.Val;
455 }
456
457 StringRef getSysReg() const {
458 assert(Kind == k_SysReg && "Invalid access!");
459 return StringRef(SysReg.Data, SysReg.Length);
460 }
461
Tim Northover3b0846e2014-05-24 12:50:23 +0000462 unsigned getSysCR() const {
463 assert(Kind == k_SysCR && "Invalid access!");
464 return SysCRImm.Val;
465 }
466
467 unsigned getPrefetch() const {
468 assert(Kind == k_Prefetch && "Invalid access!");
469 return Prefetch.Val;
470 }
471
Oliver Stannarda34e4702015-12-01 10:48:51 +0000472 unsigned getPSBHint() const {
473 assert(Kind == k_PSBHint && "Invalid access!");
474 return PSBHint.Val;
475 }
476
477 StringRef getPSBHintName() const {
478 assert(Kind == k_PSBHint && "Invalid access!");
479 return StringRef(PSBHint.Data, PSBHint.Length);
480 }
481
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000482 StringRef getPrefetchName() const {
483 assert(Kind == k_Prefetch && "Invalid access!");
484 return StringRef(Prefetch.Data, Prefetch.Length);
485 }
486
Tim Northover3b0846e2014-05-24 12:50:23 +0000487 AArch64_AM::ShiftExtendType getShiftExtendType() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000488 if (Kind == k_ShiftExtend)
489 return ShiftExtend.Type;
490 if (Kind == k_Register)
491 return Reg.ShiftExtend.Type;
492 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000493 }
494
495 unsigned getShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000496 if (Kind == k_ShiftExtend)
497 return ShiftExtend.Amount;
498 if (Kind == k_Register)
499 return Reg.ShiftExtend.Amount;
500 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000501 }
502
503 bool hasShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000504 if (Kind == k_ShiftExtend)
505 return ShiftExtend.HasExplicitAmount;
506 if (Kind == k_Register)
507 return Reg.ShiftExtend.HasExplicitAmount;
508 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000509 }
510
511 bool isImm() const override { return Kind == k_Immediate; }
512 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000513
514 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
515
Sander de Smalen50ded902018-04-29 17:33:38 +0000516 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
517 return isImmScaled<Bits, Scale>(true);
518 }
519
520 template <int Bits, int Scale> DiagnosticPredicate isUImmScaled() const {
521 return isImmScaled<Bits, Scale>(false);
522 }
523
Sander de Smalenfe17a782018-04-26 12:54:42 +0000524 template <int Bits, int Scale>
Sander de Smalen50ded902018-04-29 17:33:38 +0000525 DiagnosticPredicate isImmScaled(bool Signed) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000526 if (!isImm())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000527 return DiagnosticPredicateTy::NoMatch;
528
Tim Northover3b0846e2014-05-24 12:50:23 +0000529 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
530 if (!MCE)
Sander de Smalenfe17a782018-04-26 12:54:42 +0000531 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000532
Sander de Smalen50ded902018-04-29 17:33:38 +0000533 int64_t MinVal, MaxVal;
534 if (Signed) {
535 int64_t Shift = Bits - 1;
536 MinVal = (int64_t(1) << Shift) * -Scale;
537 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
538 } else {
539 MinVal = 0;
540 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
541 }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000542
Tim Northover3b0846e2014-05-24 12:50:23 +0000543 int64_t Val = MCE->getValue();
Sander de Smalenfe17a782018-04-26 12:54:42 +0000544 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
545 return DiagnosticPredicateTy::Match;
546
547 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +0000548 }
549
Sander de Smalen245e0e62018-01-22 10:46:00 +0000550 bool isSVEPattern() const {
551 if (!isImm())
552 return false;
553 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
554 if (!MCE)
555 return false;
556 int64_t Val = MCE->getValue();
557 return Val >= 0 && Val < 32;
558 }
559
Tim Northover3b0846e2014-05-24 12:50:23 +0000560 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
561 AArch64MCExpr::VariantKind ELFRefKind;
562 MCSymbolRefExpr::VariantKind DarwinRefKind;
563 int64_t Addend;
564 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
565 Addend)) {
566 // If we don't understand the expression, assume the best and
567 // let the fixup and relocation code deal with it.
568 return true;
569 }
570
571 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
572 ELFRefKind == AArch64MCExpr::VK_LO12 ||
573 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
574 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
575 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
576 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
577 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
578 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000579 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
580 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
581 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000582 // Note that we don't range-check the addend. It's adjusted modulo page
583 // size when converted, so there is no "out of range" condition when using
584 // @pageoff.
585 return Addend >= 0 && (Addend % Scale) == 0;
586 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
587 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
588 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
589 return Addend == 0;
590 }
591
592 return false;
593 }
594
595 template <int Scale> bool isUImm12Offset() const {
596 if (!isImm())
597 return false;
598
599 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
600 if (!MCE)
601 return isSymbolicUImm12Offset(getImm(), Scale);
602
603 int64_t Val = MCE->getValue();
604 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
605 }
606
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000607 template <int N, int M>
608 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000609 if (!isImm())
610 return false;
611 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
612 if (!MCE)
613 return false;
614 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000615 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000616 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000617
Sander de Smalena1c259c2018-01-29 13:05:38 +0000618 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
619 // a logical immediate can always be represented when inverted.
620 template <typename T>
621 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000622 if (!isImm())
623 return false;
624 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
625 if (!MCE)
626 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000627
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000628 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000629 int64_t SVal = typename std::make_signed<T>::type(Val);
630 int64_t UVal = typename std::make_unsigned<T>::type(Val);
631 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000632 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000633
Sander de Smalena1c259c2018-01-29 13:05:38 +0000634 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000635 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000636
Tim Northover3b0846e2014-05-24 12:50:23 +0000637 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000638
Sander de Smalen62770792018-05-25 09:47:52 +0000639 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
640 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
641 /// immediate that can be shifted by 'Shift'.
642 template <unsigned Width>
643 Optional<std::pair<int64_t, unsigned> > getShiftedVal() const {
644 if (isShiftedImm() && Width == getShiftedImmShift())
645 if (auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
646 return std::make_pair(CE->getValue(), Width);
647
648 if (isImm())
649 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
650 int64_t Val = CE->getValue();
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000651 if ((Val != 0) && (uint64_t(Val >> Width) << Width) == uint64_t(Val))
Sander de Smalen62770792018-05-25 09:47:52 +0000652 return std::make_pair(Val >> Width, Width);
653 else
654 return std::make_pair(Val, 0u);
655 }
656
657 return {};
658 }
659
Tim Northover3b0846e2014-05-24 12:50:23 +0000660 bool isAddSubImm() const {
661 if (!isShiftedImm() && !isImm())
662 return false;
663
664 const MCExpr *Expr;
665
666 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
667 if (isShiftedImm()) {
668 unsigned Shift = ShiftedImm.ShiftAmount;
669 Expr = ShiftedImm.Val;
670 if (Shift != 0 && Shift != 12)
671 return false;
672 } else {
673 Expr = getImm();
674 }
675
676 AArch64MCExpr::VariantKind ELFRefKind;
677 MCSymbolRefExpr::VariantKind DarwinRefKind;
678 int64_t Addend;
679 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
680 DarwinRefKind, Addend)) {
681 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
682 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
683 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
684 || ELFRefKind == AArch64MCExpr::VK_LO12
685 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
686 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
687 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
688 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
689 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
690 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000691 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
692 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
693 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000694 }
695
Sander de Smalen98686c62018-05-29 10:39:49 +0000696 // If it's a constant, it should be a real immediate in range.
Sander de Smalen62770792018-05-25 09:47:52 +0000697 if (auto ShiftedVal = getShiftedVal<12>())
698 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
Diana Picusc93518d2016-10-11 09:17:47 +0000699
700 // If it's an expression, we hope for the best and let the fixup/relocation
701 // code deal with it.
702 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000703 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000704
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000705 bool isAddSubImmNeg() const {
706 if (!isShiftedImm() && !isImm())
707 return false;
708
Sander de Smalen98686c62018-05-29 10:39:49 +0000709 // Otherwise it should be a real negative immediate in range.
710 if (auto ShiftedVal = getShiftedVal<12>())
711 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000712
Sander de Smalen98686c62018-05-29 10:39:49 +0000713 return false;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000714 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000715
Sander de Smalen62770792018-05-25 09:47:52 +0000716 // Signed value in the range -128 to +127. For element widths of
717 // 16 bits or higher it may also be a signed multiple of 256 in the
718 // range -32768 to +32512.
719 // For element-width of 8 bits a range of -128 to 255 is accepted,
720 // since a copy of a byte can be either signed/unsigned.
721 template <typename T>
722 DiagnosticPredicate isSVECpyImm() const {
723 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
724 return DiagnosticPredicateTy::NoMatch;
725
726 bool IsByte =
727 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
728 if (auto ShiftedImm = getShiftedVal<8>())
729 if (!(IsByte && ShiftedImm->second) &&
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000730 AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
731 << ShiftedImm->second))
Sander de Smalen62770792018-05-25 09:47:52 +0000732 return DiagnosticPredicateTy::Match;
733
734 return DiagnosticPredicateTy::NearMatch;
735 }
736
Sander de Smalen98686c62018-05-29 10:39:49 +0000737 // Unsigned value in the range 0 to 255. For element widths of
738 // 16 bits or higher it may also be a signed multiple of 256 in the
739 // range 0 to 65280.
740 template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
741 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
742 return DiagnosticPredicateTy::NoMatch;
743
744 bool IsByte =
745 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
746 if (auto ShiftedImm = getShiftedVal<8>())
747 if (!(IsByte && ShiftedImm->second) &&
748 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
749 << ShiftedImm->second))
750 return DiagnosticPredicateTy::Match;
751
752 return DiagnosticPredicateTy::NearMatch;
753 }
754
Sander de Smalen97ca6b92018-06-01 07:25:46 +0000755 template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
756 if (isLogicalImm<T>() && !isSVECpyImm<T>())
757 return DiagnosticPredicateTy::Match;
758 return DiagnosticPredicateTy::NoMatch;
759 }
760
Tim Northover3b0846e2014-05-24 12:50:23 +0000761 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000762
Tim Northover3b0846e2014-05-24 12:50:23 +0000763 bool isSIMDImmType10() const {
764 if (!isImm())
765 return false;
766 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
767 if (!MCE)
768 return false;
769 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
770 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000771
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000772 template<int N>
773 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000774 if (!isImm())
775 return false;
776 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
777 if (!MCE)
778 return true;
779 int64_t Val = MCE->getValue();
780 if (Val & 0x3)
781 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000782 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
783 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000784 }
785
786 bool
787 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
788 if (!isImm())
789 return false;
790
791 AArch64MCExpr::VariantKind ELFRefKind;
792 MCSymbolRefExpr::VariantKind DarwinRefKind;
793 int64_t Addend;
794 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
795 DarwinRefKind, Addend)) {
796 return false;
797 }
798 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
799 return false;
800
801 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
802 if (ELFRefKind == AllowedModifiers[i])
803 return Addend == 0;
804 }
805
806 return false;
807 }
808
809 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000810 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000811 }
812
813 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000814 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
815 AArch64MCExpr::VK_TPREL_G2,
816 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000817 }
818
819 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000820 return isMovWSymbol({
821 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000822 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
823 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000824 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000825 }
826
827 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000828 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
829 AArch64MCExpr::VK_TPREL_G0,
830 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000831 }
832
833 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000834 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000835 }
836
837 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000838 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000839 }
840
841 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000842 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
843 AArch64MCExpr::VK_TPREL_G1_NC,
844 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000845 }
846
847 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000848 return isMovWSymbol(
849 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
850 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000851 }
852
853 template<int RegWidth, int Shift>
854 bool isMOVZMovAlias() const {
855 if (!isImm()) return false;
856
857 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
858 if (!CE) return false;
859 uint64_t Value = CE->getValue();
860
Tim Northoverdaa1c012016-06-16 01:42:25 +0000861 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000862 }
863
864 template<int RegWidth, int Shift>
865 bool isMOVNMovAlias() const {
866 if (!isImm()) return false;
867
868 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
869 if (!CE) return false;
870 uint64_t Value = CE->getValue();
871
Tim Northoverdaa1c012016-06-16 01:42:25 +0000872 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000873 }
874
875 bool isFPImm() const { return Kind == k_FPImm; }
876 bool isBarrier() const { return Kind == k_Barrier; }
877 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000878
Tim Northover3b0846e2014-05-24 12:50:23 +0000879 bool isMRSSystemRegister() const {
880 if (!isSysReg()) return false;
881
Tim Northover7cd58932015-01-22 17:23:04 +0000882 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000883 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000884
Tim Northover3b0846e2014-05-24 12:50:23 +0000885 bool isMSRSystemRegister() const {
886 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000887 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000888 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000889
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000890 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000891 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000892 return (SysReg.PStateField == AArch64PState::PAN ||
893 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000894 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000895
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000896 bool isSystemPStateFieldWithImm0_15() const {
897 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000898 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000899 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000900
Florian Hahnc4422242017-11-07 13:07:50 +0000901 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000902 return Kind == k_Register;
903 }
904
905 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000906 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
907 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000908
Florian Hahnc4422242017-11-07 13:07:50 +0000909 bool isNeonVectorReg() const {
910 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
911 }
912
913 bool isNeonVectorRegLo() const {
914 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000915 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
916 Reg.RegNum);
917 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000918
Sander de Smalencd6be962017-12-20 11:02:42 +0000919 template <unsigned Class> bool isSVEVectorReg() const {
920 RegKind RK;
921 switch (Class) {
922 case AArch64::ZPRRegClassID:
923 RK = RegKind::SVEDataVector;
924 break;
925 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000926 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000927 RK = RegKind::SVEPredicateVector;
928 break;
929 default:
930 llvm_unreachable("Unsupport register class");
931 }
932
933 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000934 AArch64MCRegisterClasses[Class].contains(getReg());
935 }
936
Sander de Smalencd6be962017-12-20 11:02:42 +0000937 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +0000938 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
939 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
940 return DiagnosticPredicateTy::NoMatch;
941
942 if (isSVEVectorReg<Class>() &&
943 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
944 return DiagnosticPredicateTy::Match;
945
946 return DiagnosticPredicateTy::NearMatch;
947 }
948
949 template <int ElementWidth, unsigned Class>
950 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
951 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
952 return DiagnosticPredicateTy::NoMatch;
953
954 if (isSVEVectorReg<Class>() &&
955 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
956 return DiagnosticPredicateTy::Match;
957
958 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +0000959 }
960
Sander de Smaleneb896b12018-04-25 09:26:47 +0000961 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +0000962 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
963 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +0000964 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
965 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
966 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000967 return DiagnosticPredicateTy::NoMatch;
968
Sander de Smalen5861c262018-04-30 07:24:38 +0000969 // Give a more specific diagnostic when the user has explicitly typed in
970 // a shift-amount that does not match what is expected, but for which
971 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
972 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
973 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
974 ShiftExtendTy == AArch64_AM::SXTW) &&
975 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
976 return DiagnosticPredicateTy::NoMatch;
977
978 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000979 return DiagnosticPredicateTy::Match;
980
981 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +0000982 }
983
Tim Northover3b0846e2014-05-24 12:50:23 +0000984 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000985 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000986 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
987 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000988
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000989 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000990 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000991 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
992 Reg.RegNum);
993 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000994
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000995 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000996 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000997 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
998 Reg.RegNum);
999 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001000
Sam Parker5f934642017-08-31 09:27:04 +00001001 template<int64_t Angle, int64_t Remainder>
1002 bool isComplexRotation() const {
1003 if (!isImm()) return false;
1004
1005 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1006 if (!CE) return false;
1007 uint64_t Value = CE->getValue();
1008
1009 return (Value % Angle == Remainder && Value <= 270);
1010 }
1011
Sander de Smalen149916d2018-04-20 07:24:20 +00001012 template <unsigned RegClassID> bool isGPR64() const {
1013 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1014 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1015 }
1016
1017 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001018 DiagnosticPredicate isGPR64WithShiftExtend() const {
1019 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1020 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001021
Sander de Smalenfe17a782018-04-26 12:54:42 +00001022 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1023 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1024 return DiagnosticPredicateTy::Match;
1025 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001026 }
1027
Tim Northover3b0846e2014-05-24 12:50:23 +00001028 /// Is this a vector list with the type implicit (presumably attached to the
1029 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001030 template <RegKind VectorKind, unsigned NumRegs>
1031 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001032 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001033 VectorList.NumElements == 0 &&
1034 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001035 }
1036
Sander de Smalen650234b2018-04-12 11:40:52 +00001037 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1038 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001039 bool isTypedVectorList() const {
1040 if (Kind != k_VectorList)
1041 return false;
1042 if (VectorList.Count != NumRegs)
1043 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001044 if (VectorList.RegisterKind != VectorKind)
1045 return false;
1046 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001047 return false;
1048 return VectorList.NumElements == NumElements;
1049 }
1050
1051 bool isVectorIndex1() const {
1052 return Kind == k_VectorIndex && VectorIndex.Val == 1;
1053 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001054
Tim Northover3b0846e2014-05-24 12:50:23 +00001055 bool isVectorIndexB() const {
1056 return Kind == k_VectorIndex && VectorIndex.Val < 16;
1057 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001058
Tim Northover3b0846e2014-05-24 12:50:23 +00001059 bool isVectorIndexH() const {
1060 return Kind == k_VectorIndex && VectorIndex.Val < 8;
1061 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001062
Tim Northover3b0846e2014-05-24 12:50:23 +00001063 bool isVectorIndexS() const {
1064 return Kind == k_VectorIndex && VectorIndex.Val < 4;
1065 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001066
Tim Northover3b0846e2014-05-24 12:50:23 +00001067 bool isVectorIndexD() const {
1068 return Kind == k_VectorIndex && VectorIndex.Val < 2;
1069 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001070
Tim Northover3b0846e2014-05-24 12:50:23 +00001071 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001072
Tim Northover3b0846e2014-05-24 12:50:23 +00001073 bool isTokenEqual(StringRef Str) const {
1074 return Kind == k_Token && getToken() == Str;
1075 }
1076 bool isSysCR() const { return Kind == k_SysCR; }
1077 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001078 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001079 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1080 bool isShifter() const {
1081 if (!isShiftExtend())
1082 return false;
1083
1084 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1085 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1086 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1087 ST == AArch64_AM::MSL);
1088 }
1089 bool isExtend() const {
1090 if (!isShiftExtend())
1091 return false;
1092
1093 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1094 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1095 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1096 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1097 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1098 ET == AArch64_AM::LSL) &&
1099 getShiftExtendAmount() <= 4;
1100 }
1101
1102 bool isExtend64() const {
1103 if (!isExtend())
1104 return false;
1105 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1106 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1107 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1108 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001109
Tim Northover3b0846e2014-05-24 12:50:23 +00001110 bool isExtendLSL64() const {
1111 if (!isExtend())
1112 return false;
1113 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1114 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1115 ET == AArch64_AM::LSL) &&
1116 getShiftExtendAmount() <= 4;
1117 }
1118
1119 template<int Width> bool isMemXExtend() const {
1120 if (!isExtend())
1121 return false;
1122 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1123 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1124 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1125 getShiftExtendAmount() == 0);
1126 }
1127
1128 template<int Width> bool isMemWExtend() const {
1129 if (!isExtend())
1130 return false;
1131 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1132 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1133 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1134 getShiftExtendAmount() == 0);
1135 }
1136
1137 template <unsigned width>
1138 bool isArithmeticShifter() const {
1139 if (!isShifter())
1140 return false;
1141
1142 // An arithmetic shifter is LSL, LSR, or ASR.
1143 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1144 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1145 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1146 }
1147
1148 template <unsigned width>
1149 bool isLogicalShifter() const {
1150 if (!isShifter())
1151 return false;
1152
1153 // A logical shifter is LSL, LSR, ASR or ROR.
1154 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1155 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1156 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1157 getShiftExtendAmount() < width;
1158 }
1159
1160 bool isMovImm32Shifter() const {
1161 if (!isShifter())
1162 return false;
1163
1164 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1165 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1166 if (ST != AArch64_AM::LSL)
1167 return false;
1168 uint64_t Val = getShiftExtendAmount();
1169 return (Val == 0 || Val == 16);
1170 }
1171
1172 bool isMovImm64Shifter() const {
1173 if (!isShifter())
1174 return false;
1175
1176 // A MOVi shifter is LSL of 0 or 16.
1177 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1178 if (ST != AArch64_AM::LSL)
1179 return false;
1180 uint64_t Val = getShiftExtendAmount();
1181 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1182 }
1183
1184 bool isLogicalVecShifter() const {
1185 if (!isShifter())
1186 return false;
1187
1188 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1189 unsigned Shift = getShiftExtendAmount();
1190 return getShiftExtendType() == AArch64_AM::LSL &&
1191 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1192 }
1193
1194 bool isLogicalVecHalfWordShifter() const {
1195 if (!isLogicalVecShifter())
1196 return false;
1197
1198 // A logical vector shifter is a left shift by 0 or 8.
1199 unsigned Shift = getShiftExtendAmount();
1200 return getShiftExtendType() == AArch64_AM::LSL &&
1201 (Shift == 0 || Shift == 8);
1202 }
1203
1204 bool isMoveVecShifter() const {
1205 if (!isShiftExtend())
1206 return false;
1207
1208 // A logical vector shifter is a left shift by 8 or 16.
1209 unsigned Shift = getShiftExtendAmount();
1210 return getShiftExtendType() == AArch64_AM::MSL &&
1211 (Shift == 8 || Shift == 16);
1212 }
1213
1214 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1215 // to LDUR/STUR when the offset is not legal for the former but is for
1216 // the latter. As such, in addition to checking for being a legal unscaled
1217 // address, also check that it is not a legal scaled address. This avoids
1218 // ambiguity in the matcher.
1219 template<int Width>
1220 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001221 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001222 }
1223
1224 bool isAdrpLabel() const {
1225 // Validation was handled during parsing, so we just sanity check that
1226 // something didn't go haywire.
1227 if (!isImm())
1228 return false;
1229
1230 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1231 int64_t Val = CE->getValue();
1232 int64_t Min = - (4096 * (1LL << (21 - 1)));
1233 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1234 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1235 }
1236
1237 return true;
1238 }
1239
1240 bool isAdrLabel() const {
1241 // Validation was handled during parsing, so we just sanity check that
1242 // something didn't go haywire.
1243 if (!isImm())
1244 return false;
1245
1246 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1247 int64_t Val = CE->getValue();
1248 int64_t Min = - (1LL << (21 - 1));
1249 int64_t Max = ((1LL << (21 - 1)) - 1);
1250 return Val >= Min && Val <= Max;
1251 }
1252
1253 return true;
1254 }
1255
1256 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1257 // Add as immediates when possible. Null MCExpr = 0.
1258 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001259 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001260 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001261 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001262 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001263 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001264 }
1265
1266 void addRegOperands(MCInst &Inst, unsigned N) const {
1267 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001268 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001269 }
1270
1271 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1272 assert(N == 1 && "Invalid number of operands!");
1273 assert(
1274 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1275
1276 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1277 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1278 RI->getEncodingValue(getReg()));
1279
Jim Grosbache9119e42015-05-13 18:37:00 +00001280 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001281 }
1282
1283 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1284 assert(N == 1 && "Invalid number of operands!");
1285 assert(
1286 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001287 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001288 }
1289
1290 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1291 assert(N == 1 && "Invalid number of operands!");
1292 assert(
1293 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001294 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001295 }
1296
1297 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1298 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001299 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001300 }
1301
Sander de Smalen525e3222018-04-12 13:19:32 +00001302 enum VecListIndexType {
1303 VecListIdx_DReg = 0,
1304 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001305 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001306 };
1307
1308 template <VecListIndexType RegTy, unsigned NumRegs>
1309 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001310 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001311 static const unsigned FirstRegs[][5] = {
1312 /* DReg */ { AArch64::Q0,
1313 AArch64::D0, AArch64::D0_D1,
1314 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1315 /* QReg */ { AArch64::Q0,
1316 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001317 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1318 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001319 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001320 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001321 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001322
Sander de Smalen7a210db2018-04-16 10:46:18 +00001323 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1324 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001325
Sander de Smalen525e3222018-04-12 13:19:32 +00001326 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1327 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1328 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001329 }
1330
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001331 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001332 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001333 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001334 }
1335
1336 void addImmOperands(MCInst &Inst, unsigned N) const {
1337 assert(N == 1 && "Invalid number of operands!");
1338 // If this is a pageoff symrefexpr with an addend, adjust the addend
1339 // to be only the page-offset portion. Otherwise, just add the expr
1340 // as-is.
1341 addExpr(Inst, getImm());
1342 }
1343
Sander de Smalen62770792018-05-25 09:47:52 +00001344 template <int Shift>
1345 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001346 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001347 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1348 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1349 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1350 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001351 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001352 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001353 } else {
1354 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001355 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001356 }
1357 }
1358
Sander de Smalen62770792018-05-25 09:47:52 +00001359 template <int Shift>
1360 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001361 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001362 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1363 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1364 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1365 } else
1366 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001367 }
1368
Tim Northover3b0846e2014-05-24 12:50:23 +00001369 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1370 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001371 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001372 }
1373
1374 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1375 assert(N == 1 && "Invalid number of operands!");
1376 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1377 if (!MCE)
1378 addExpr(Inst, getImm());
1379 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001380 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001381 }
1382
1383 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1384 addImmOperands(Inst, N);
1385 }
1386
1387 template<int Scale>
1388 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1389 assert(N == 1 && "Invalid number of operands!");
1390 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1391
1392 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001393 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001394 return;
1395 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001396 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001397 }
1398
Sander de Smalen5c625982018-04-13 12:56:14 +00001399 template <int Scale>
1400 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1401 assert(N == 1 && "Invalid number of operands!");
1402 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1403 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1404 }
1405
Sander de Smalena1c259c2018-01-29 13:05:38 +00001406 template <typename T>
1407 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001408 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001409 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001410 typename std::make_unsigned<T>::type Val = MCE->getValue();
1411 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001412 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001413 }
1414
Sander de Smalena1c259c2018-01-29 13:05:38 +00001415 template <typename T>
1416 void addLogicalImmNotOperands(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));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001422 }
1423
Tim Northover3b0846e2014-05-24 12:50:23 +00001424 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1425 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001426 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001427 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001428 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001429 }
1430
1431 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1432 // Branch operands don't encode the low bits, so shift them off
1433 // here. If it's a label, however, just put it on directly as there's
1434 // not enough information now to do anything.
1435 assert(N == 1 && "Invalid number of operands!");
1436 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1437 if (!MCE) {
1438 addExpr(Inst, getImm());
1439 return;
1440 }
1441 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001442 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001443 }
1444
1445 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1446 // Branch operands don't encode the low bits, so shift them off
1447 // here. If it's a label, however, just put it on directly as there's
1448 // not enough information now to do anything.
1449 assert(N == 1 && "Invalid number of operands!");
1450 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1451 if (!MCE) {
1452 addExpr(Inst, getImm());
1453 return;
1454 }
1455 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001456 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001457 }
1458
1459 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1460 // Branch operands don't encode the low bits, so shift them off
1461 // here. If it's a label, however, just put it on directly as there's
1462 // not enough information now to do anything.
1463 assert(N == 1 && "Invalid number of operands!");
1464 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1465 if (!MCE) {
1466 addExpr(Inst, getImm());
1467 return;
1468 }
1469 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001470 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001471 }
1472
1473 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1474 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001475 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001476 }
1477
1478 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1479 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001480 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001481 }
1482
1483 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1484 assert(N == 1 && "Invalid number of operands!");
1485
Jim Grosbache9119e42015-05-13 18:37:00 +00001486 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001487 }
1488
1489 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1490 assert(N == 1 && "Invalid number of operands!");
1491
Jim Grosbache9119e42015-05-13 18:37:00 +00001492 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001493 }
1494
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001495 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1496 assert(N == 1 && "Invalid number of operands!");
1497
1498 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1499 }
1500
1501 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001502 assert(N == 1 && "Invalid number of operands!");
1503
Jim Grosbache9119e42015-05-13 18:37:00 +00001504 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001505 }
1506
1507 void addSysCROperands(MCInst &Inst, unsigned N) const {
1508 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001509 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001510 }
1511
1512 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1513 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001514 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001515 }
1516
Oliver Stannarda34e4702015-12-01 10:48:51 +00001517 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1518 assert(N == 1 && "Invalid number of operands!");
1519 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1520 }
1521
Tim Northover3b0846e2014-05-24 12:50:23 +00001522 void addShifterOperands(MCInst &Inst, unsigned N) const {
1523 assert(N == 1 && "Invalid number of operands!");
1524 unsigned Imm =
1525 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001526 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001527 }
1528
1529 void addExtendOperands(MCInst &Inst, unsigned N) const {
1530 assert(N == 1 && "Invalid number of operands!");
1531 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1532 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1533 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001534 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001535 }
1536
1537 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1538 assert(N == 1 && "Invalid number of operands!");
1539 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1540 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1541 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001542 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001543 }
1544
1545 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1546 assert(N == 2 && "Invalid number of operands!");
1547 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1548 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001549 Inst.addOperand(MCOperand::createImm(IsSigned));
1550 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001551 }
1552
1553 // For 8-bit load/store instructions with a register offset, both the
1554 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1555 // they're disambiguated by whether the shift was explicit or implicit rather
1556 // than its size.
1557 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1558 assert(N == 2 && "Invalid number of operands!");
1559 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1560 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001561 Inst.addOperand(MCOperand::createImm(IsSigned));
1562 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001563 }
1564
1565 template<int Shift>
1566 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1567 assert(N == 1 && "Invalid number of operands!");
1568
1569 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1570 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001571 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001572 }
1573
1574 template<int Shift>
1575 void addMOVNMovAliasOperands(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
Sam Parker5f934642017-08-31 09:27:04 +00001583 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1584 assert(N == 1 && "Invalid number of operands!");
1585 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1586 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1587 }
1588
1589 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1590 assert(N == 1 && "Invalid number of operands!");
1591 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1592 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1593 }
1594
Tim Northover3b0846e2014-05-24 12:50:23 +00001595 void print(raw_ostream &OS) const override;
1596
David Blaikie960ea3f2014-06-08 16:18:35 +00001597 static std::unique_ptr<AArch64Operand>
1598 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1599 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001600 Op->Tok.Data = Str.data();
1601 Op->Tok.Length = Str.size();
1602 Op->Tok.IsSuffix = IsSuffix;
1603 Op->StartLoc = S;
1604 Op->EndLoc = S;
1605 return Op;
1606 }
1607
David Blaikie960ea3f2014-06-08 16:18:35 +00001608 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001609 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
1610 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1611 unsigned ShiftAmount = 0,
1612 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001613 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001614 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001615 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001616 Op->Reg.ElementWidth = 0;
1617 Op->Reg.ShiftExtend.Type = ExtTy;
1618 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1619 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001620 Op->StartLoc = S;
1621 Op->EndLoc = E;
1622 return Op;
1623 }
1624
David Blaikie960ea3f2014-06-08 16:18:35 +00001625 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001626 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001627 SMLoc S, SMLoc E, MCContext &Ctx,
1628 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1629 unsigned ShiftAmount = 0,
1630 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001631 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1632 Kind == RegKind::SVEPredicateVector) &&
1633 "Invalid vector kind");
Sander de Smalen149916d2018-04-20 07:24:20 +00001634 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, ExtTy, ShiftAmount,
1635 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001636 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001637 return Op;
1638 }
1639
1640 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001641 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001642 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1643 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001644 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001645 Op->VectorList.RegNum = RegNum;
1646 Op->VectorList.Count = Count;
1647 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001648 Op->VectorList.ElementWidth = ElementWidth;
1649 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001650 Op->StartLoc = S;
1651 Op->EndLoc = E;
1652 return Op;
1653 }
1654
David Blaikie960ea3f2014-06-08 16:18:35 +00001655 static std::unique_ptr<AArch64Operand>
1656 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1657 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001658 Op->VectorIndex.Val = Idx;
1659 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> CreateImm(const MCExpr *Val, SMLoc S,
1665 SMLoc E, MCContext &Ctx) {
1666 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001667 Op->Imm.Val = Val;
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> CreateShiftedImm(const MCExpr *Val,
1674 unsigned ShiftAmount,
1675 SMLoc S, SMLoc E,
1676 MCContext &Ctx) {
1677 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001678 Op->ShiftedImm .Val = Val;
1679 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1680 Op->StartLoc = S;
1681 Op->EndLoc = E;
1682 return Op;
1683 }
1684
David Blaikie960ea3f2014-06-08 16:18:35 +00001685 static std::unique_ptr<AArch64Operand>
1686 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1687 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001688 Op->CondCode.Code = Code;
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> CreateFPImm(unsigned Val, SMLoc S,
1695 MCContext &Ctx) {
1696 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001697 Op->FPImm.Val = Val;
1698 Op->StartLoc = S;
1699 Op->EndLoc = S;
1700 return Op;
1701 }
1702
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001703 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1704 StringRef Str,
1705 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001706 MCContext &Ctx) {
1707 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001708 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001709 Op->Barrier.Data = Str.data();
1710 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001711 Op->StartLoc = S;
1712 Op->EndLoc = S;
1713 return Op;
1714 }
1715
Tim Northover7cd58932015-01-22 17:23:04 +00001716 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1717 uint32_t MRSReg,
1718 uint32_t MSRReg,
1719 uint32_t PStateField,
1720 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001721 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001722 Op->SysReg.Data = Str.data();
1723 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001724 Op->SysReg.MRSReg = MRSReg;
1725 Op->SysReg.MSRReg = MSRReg;
1726 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001727 Op->StartLoc = S;
1728 Op->EndLoc = S;
1729 return Op;
1730 }
1731
David Blaikie960ea3f2014-06-08 16:18:35 +00001732 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1733 SMLoc E, MCContext &Ctx) {
1734 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001735 Op->SysCRImm.Val = Val;
1736 Op->StartLoc = S;
1737 Op->EndLoc = E;
1738 return Op;
1739 }
1740
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001741 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1742 StringRef Str,
1743 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001744 MCContext &Ctx) {
1745 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001746 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001747 Op->Barrier.Data = Str.data();
1748 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001749 Op->StartLoc = S;
1750 Op->EndLoc = S;
1751 return Op;
1752 }
1753
Oliver Stannarda34e4702015-12-01 10:48:51 +00001754 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1755 StringRef Str,
1756 SMLoc S,
1757 MCContext &Ctx) {
1758 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1759 Op->PSBHint.Val = Val;
1760 Op->PSBHint.Data = Str.data();
1761 Op->PSBHint.Length = Str.size();
1762 Op->StartLoc = S;
1763 Op->EndLoc = S;
1764 return Op;
1765 }
1766
David Blaikie960ea3f2014-06-08 16:18:35 +00001767 static std::unique_ptr<AArch64Operand>
1768 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1769 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1770 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001771 Op->ShiftExtend.Type = ShOp;
1772 Op->ShiftExtend.Amount = Val;
1773 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1774 Op->StartLoc = S;
1775 Op->EndLoc = E;
1776 return Op;
1777 }
1778};
1779
1780} // end anonymous namespace.
1781
1782void AArch64Operand::print(raw_ostream &OS) const {
1783 switch (Kind) {
1784 case k_FPImm:
1785 OS << "<fpimm " << getFPImm() << "("
1786 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1787 break;
1788 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001789 StringRef Name = getBarrierName();
1790 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001791 OS << "<barrier " << Name << ">";
1792 else
1793 OS << "<barrier invalid #" << getBarrier() << ">";
1794 break;
1795 }
1796 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001797 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001798 break;
1799 case k_ShiftedImm: {
1800 unsigned Shift = getShiftedImmShift();
1801 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001802 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001803 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1804 break;
1805 }
1806 case k_CondCode:
1807 OS << "<condcode " << getCondCode() << ">";
1808 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001809 case k_VectorList: {
1810 OS << "<vectorlist ";
1811 unsigned Reg = getVectorListStart();
1812 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1813 OS << Reg + i << " ";
1814 OS << ">";
1815 break;
1816 }
1817 case k_VectorIndex:
1818 OS << "<vectorindex " << getVectorIndex() << ">";
1819 break;
1820 case k_SysReg:
1821 OS << "<sysreg: " << getSysReg() << '>';
1822 break;
1823 case k_Token:
1824 OS << "'" << getToken() << "'";
1825 break;
1826 case k_SysCR:
1827 OS << "c" << getSysCR();
1828 break;
1829 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001830 StringRef Name = getPrefetchName();
1831 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001832 OS << "<prfop " << Name << ">";
1833 else
1834 OS << "<prfop invalid #" << getPrefetch() << ">";
1835 break;
1836 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001837 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001838 OS << getPSBHintName();
1839 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00001840 case k_Register:
1841 OS << "<register " << getReg() << ">";
1842 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
1843 break;
1844 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001845 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001846 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1847 << getShiftExtendAmount();
1848 if (!hasShiftExtendAmount())
1849 OS << "<imp>";
1850 OS << '>';
1851 break;
1852 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001853}
1854
1855/// @name Auto-generated Match Functions
1856/// {
1857
1858static unsigned MatchRegisterName(StringRef Name);
1859
1860/// }
1861
Florian Hahnc4422242017-11-07 13:07:50 +00001862static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001863 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001864 .Case("v0", AArch64::Q0)
1865 .Case("v1", AArch64::Q1)
1866 .Case("v2", AArch64::Q2)
1867 .Case("v3", AArch64::Q3)
1868 .Case("v4", AArch64::Q4)
1869 .Case("v5", AArch64::Q5)
1870 .Case("v6", AArch64::Q6)
1871 .Case("v7", AArch64::Q7)
1872 .Case("v8", AArch64::Q8)
1873 .Case("v9", AArch64::Q9)
1874 .Case("v10", AArch64::Q10)
1875 .Case("v11", AArch64::Q11)
1876 .Case("v12", AArch64::Q12)
1877 .Case("v13", AArch64::Q13)
1878 .Case("v14", AArch64::Q14)
1879 .Case("v15", AArch64::Q15)
1880 .Case("v16", AArch64::Q16)
1881 .Case("v17", AArch64::Q17)
1882 .Case("v18", AArch64::Q18)
1883 .Case("v19", AArch64::Q19)
1884 .Case("v20", AArch64::Q20)
1885 .Case("v21", AArch64::Q21)
1886 .Case("v22", AArch64::Q22)
1887 .Case("v23", AArch64::Q23)
1888 .Case("v24", AArch64::Q24)
1889 .Case("v25", AArch64::Q25)
1890 .Case("v26", AArch64::Q26)
1891 .Case("v27", AArch64::Q27)
1892 .Case("v28", AArch64::Q28)
1893 .Case("v29", AArch64::Q29)
1894 .Case("v30", AArch64::Q30)
1895 .Case("v31", AArch64::Q31)
1896 .Default(0);
1897}
1898
Sander de Smalen73937b72018-04-11 07:36:10 +00001899/// Returns an optional pair of (#elements, element-width) if Suffix
1900/// is a valid vector kind. Where the number of elements in a vector
1901/// or the vector width is implicit or explicitly unknown (but still a
1902/// valid suffix kind), 0 is used.
1903static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1904 RegKind VectorKind) {
1905 std::pair<int, int> Res = {-1, -1};
1906
1907 switch (VectorKind) {
1908 case RegKind::NeonVector:
1909 Res =
1910 StringSwitch<std::pair<int, int>>(Suffix.lower())
1911 .Case("", {0, 0})
1912 .Case(".1d", {1, 64})
1913 .Case(".1q", {1, 128})
1914 // '.2h' needed for fp16 scalar pairwise reductions
1915 .Case(".2h", {2, 16})
1916 .Case(".2s", {2, 32})
1917 .Case(".2d", {2, 64})
1918 // '.4b' is another special case for the ARMv8.2a dot product
1919 // operand
1920 .Case(".4b", {4, 8})
1921 .Case(".4h", {4, 16})
1922 .Case(".4s", {4, 32})
1923 .Case(".8b", {8, 8})
1924 .Case(".8h", {8, 16})
1925 .Case(".16b", {16, 8})
1926 // Accept the width neutral ones, too, for verbose syntax. If those
1927 // aren't used in the right places, the token operand won't match so
1928 // all will work out.
1929 .Case(".b", {0, 8})
1930 .Case(".h", {0, 16})
1931 .Case(".s", {0, 32})
1932 .Case(".d", {0, 64})
1933 .Default({-1, -1});
1934 break;
1935 case RegKind::SVEPredicateVector:
1936 case RegKind::SVEDataVector:
1937 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1938 .Case("", {0, 0})
1939 .Case(".b", {0, 8})
1940 .Case(".h", {0, 16})
1941 .Case(".s", {0, 32})
1942 .Case(".d", {0, 64})
1943 .Case(".q", {0, 128})
1944 .Default({-1, -1});
1945 break;
1946 default:
1947 llvm_unreachable("Unsupported RegKind");
1948 }
1949
1950 if (Res == std::make_pair(-1, -1))
1951 return Optional<std::pair<int, int>>();
1952
1953 return Optional<std::pair<int, int>>(Res);
1954}
1955
1956static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1957 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001958}
1959
Florian Hahn91f11e52017-11-07 16:45:48 +00001960static unsigned matchSVEDataVectorRegName(StringRef Name) {
1961 return StringSwitch<unsigned>(Name.lower())
1962 .Case("z0", AArch64::Z0)
1963 .Case("z1", AArch64::Z1)
1964 .Case("z2", AArch64::Z2)
1965 .Case("z3", AArch64::Z3)
1966 .Case("z4", AArch64::Z4)
1967 .Case("z5", AArch64::Z5)
1968 .Case("z6", AArch64::Z6)
1969 .Case("z7", AArch64::Z7)
1970 .Case("z8", AArch64::Z8)
1971 .Case("z9", AArch64::Z9)
1972 .Case("z10", AArch64::Z10)
1973 .Case("z11", AArch64::Z11)
1974 .Case("z12", AArch64::Z12)
1975 .Case("z13", AArch64::Z13)
1976 .Case("z14", AArch64::Z14)
1977 .Case("z15", AArch64::Z15)
1978 .Case("z16", AArch64::Z16)
1979 .Case("z17", AArch64::Z17)
1980 .Case("z18", AArch64::Z18)
1981 .Case("z19", AArch64::Z19)
1982 .Case("z20", AArch64::Z20)
1983 .Case("z21", AArch64::Z21)
1984 .Case("z22", AArch64::Z22)
1985 .Case("z23", AArch64::Z23)
1986 .Case("z24", AArch64::Z24)
1987 .Case("z25", AArch64::Z25)
1988 .Case("z26", AArch64::Z26)
1989 .Case("z27", AArch64::Z27)
1990 .Case("z28", AArch64::Z28)
1991 .Case("z29", AArch64::Z29)
1992 .Case("z30", AArch64::Z30)
1993 .Case("z31", AArch64::Z31)
1994 .Default(0);
1995}
1996
Sander de Smalencd6be962017-12-20 11:02:42 +00001997static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1998 return StringSwitch<unsigned>(Name.lower())
1999 .Case("p0", AArch64::P0)
2000 .Case("p1", AArch64::P1)
2001 .Case("p2", AArch64::P2)
2002 .Case("p3", AArch64::P3)
2003 .Case("p4", AArch64::P4)
2004 .Case("p5", AArch64::P5)
2005 .Case("p6", AArch64::P6)
2006 .Case("p7", AArch64::P7)
2007 .Case("p8", AArch64::P8)
2008 .Case("p9", AArch64::P9)
2009 .Case("p10", AArch64::P10)
2010 .Case("p11", AArch64::P11)
2011 .Case("p12", AArch64::P12)
2012 .Case("p13", AArch64::P13)
2013 .Case("p14", AArch64::P14)
2014 .Case("p15", AArch64::P15)
2015 .Default(0);
2016}
2017
Tim Northover3b0846e2014-05-24 12:50:23 +00002018bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2019 SMLoc &EndLoc) {
2020 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002021 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002022 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002023 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002024}
2025
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002026// Matches a register name or register alias previously defined by '.req'
2027unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002028 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002029 unsigned RegNum = 0;
2030 if ((RegNum = matchSVEDataVectorRegName(Name)))
2031 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2032
Sander de Smalencd6be962017-12-20 11:02:42 +00002033 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2034 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2035
Sander de Smalenc067c302017-12-20 09:45:45 +00002036 if ((RegNum = MatchNeonVectorRegName(Name)))
2037 return Kind == RegKind::NeonVector ? RegNum : 0;
2038
2039 // The parsed register must be of RegKind Scalar
2040 if ((RegNum = MatchRegisterName(Name)))
2041 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002042
Florian Hahnc4422242017-11-07 13:07:50 +00002043 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002044 // Handle a few common aliases of registers.
2045 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2046 .Case("fp", AArch64::FP)
2047 .Case("lr", AArch64::LR)
2048 .Case("x31", AArch64::XZR)
2049 .Case("w31", AArch64::WZR)
2050 .Default(0))
2051 return Kind == RegKind::Scalar ? RegNum : 0;
2052
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002053 // Check for aliases registered via .req. Canonicalize to lower case.
2054 // That's more consistent since register names are case insensitive, and
2055 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2056 auto Entry = RegisterReqs.find(Name.lower());
2057 if (Entry == RegisterReqs.end())
2058 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002059
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002060 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002061 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002062 RegNum = Entry->getValue().second;
2063 }
2064 return RegNum;
2065}
2066
Sander de Smalen50d87022018-04-19 07:35:08 +00002067/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002068/// Identifier when called, and if it is a register name the token is eaten and
2069/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002070OperandMatchResultTy
2071AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002072 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002073 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002074 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002075 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002076
2077 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002078 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2079 if (Reg == 0)
2080 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002081
Sander de Smalen50d87022018-04-19 07:35:08 +00002082 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002083 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002084 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002085}
2086
Tim Northover3b0846e2014-05-24 12:50:23 +00002087/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002088OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002089AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002090 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002091 SMLoc S = getLoc();
2092
2093 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2094 Error(S, "Expected cN operand where 0 <= N <= 15");
2095 return MatchOperand_ParseFail;
2096 }
2097
2098 StringRef Tok = Parser.getTok().getIdentifier();
2099 if (Tok[0] != 'c' && Tok[0] != 'C') {
2100 Error(S, "Expected cN operand where 0 <= N <= 15");
2101 return MatchOperand_ParseFail;
2102 }
2103
2104 uint32_t CRNum;
2105 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2106 if (BadNum || CRNum > 15) {
2107 Error(S, "Expected cN operand where 0 <= N <= 15");
2108 return MatchOperand_ParseFail;
2109 }
2110
2111 Parser.Lex(); // Eat identifier token.
2112 Operands.push_back(
2113 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2114 return MatchOperand_Success;
2115}
2116
2117/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002118template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002119OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002120AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002121 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002122 SMLoc S = getLoc();
2123 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002124
2125 auto LookupByName = [](StringRef N) {
2126 if (IsSVEPrefetch) {
2127 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2128 return Optional<unsigned>(Res->Encoding);
2129 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2130 return Optional<unsigned>(Res->Encoding);
2131 return Optional<unsigned>();
2132 };
2133
2134 auto LookupByEncoding = [](unsigned E) {
2135 if (IsSVEPrefetch) {
2136 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2137 return Optional<StringRef>(Res->Name);
2138 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2139 return Optional<StringRef>(Res->Name);
2140 return Optional<StringRef>();
2141 };
2142 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2143
Tim Northover3b0846e2014-05-24 12:50:23 +00002144 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002145 // Eat optional hash.
2146 if (parseOptionalToken(AsmToken::Hash) ||
2147 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002148 const MCExpr *ImmVal;
2149 if (getParser().parseExpression(ImmVal))
2150 return MatchOperand_ParseFail;
2151
2152 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2153 if (!MCE) {
2154 TokError("immediate value expected for prefetch operand");
2155 return MatchOperand_ParseFail;
2156 }
2157 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002158 if (prfop > MaxVal) {
2159 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2160 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002161 return MatchOperand_ParseFail;
2162 }
2163
Sander de Smalen93380372018-05-14 11:54:41 +00002164 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002165 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002166 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002167 return MatchOperand_Success;
2168 }
2169
2170 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002171 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002172 return MatchOperand_ParseFail;
2173 }
2174
Sander de Smalen93380372018-05-14 11:54:41 +00002175 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002176 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002177 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002178 return MatchOperand_ParseFail;
2179 }
2180
2181 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002182 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002183 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002184 return MatchOperand_Success;
2185}
2186
Oliver Stannarda34e4702015-12-01 10:48:51 +00002187/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002188OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002189AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2190 MCAsmParser &Parser = getParser();
2191 SMLoc S = getLoc();
2192 const AsmToken &Tok = Parser.getTok();
2193 if (Tok.isNot(AsmToken::Identifier)) {
2194 TokError("invalid operand for instruction");
2195 return MatchOperand_ParseFail;
2196 }
2197
Tim Northovere6ae6762016-07-05 21:23:04 +00002198 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2199 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002200 TokError("invalid operand for instruction");
2201 return MatchOperand_ParseFail;
2202 }
2203
2204 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002205 Operands.push_back(AArch64Operand::CreatePSBHint(
2206 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002207 return MatchOperand_Success;
2208}
2209
Tim Northover3b0846e2014-05-24 12:50:23 +00002210/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2211/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002212OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002213AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002214 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002215 SMLoc S = getLoc();
2216 const MCExpr *Expr;
2217
2218 if (Parser.getTok().is(AsmToken::Hash)) {
2219 Parser.Lex(); // Eat hash token.
2220 }
2221
2222 if (parseSymbolicImmVal(Expr))
2223 return MatchOperand_ParseFail;
2224
2225 AArch64MCExpr::VariantKind ELFRefKind;
2226 MCSymbolRefExpr::VariantKind DarwinRefKind;
2227 int64_t Addend;
2228 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2229 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2230 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2231 // No modifier was specified at all; this is the syntax for an ELF basic
2232 // ADRP relocation (unfortunately).
2233 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002234 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002235 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2236 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2237 Addend != 0) {
2238 Error(S, "gotpage label reference not allowed an addend");
2239 return MatchOperand_ParseFail;
2240 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2241 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2242 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2243 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2244 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2245 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2246 // The operand must be an @page or @gotpage qualified symbolref.
2247 Error(S, "page or gotpage label reference expected");
2248 return MatchOperand_ParseFail;
2249 }
2250 }
2251
2252 // We have either a label reference possibly with addend or an immediate. The
2253 // addend is a raw value here. The linker will adjust it to only reference the
2254 // page.
2255 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2256 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2257
2258 return MatchOperand_Success;
2259}
2260
2261/// tryParseAdrLabel - Parse and validate a source label for the ADR
2262/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002263OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002264AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2265 SMLoc S = getLoc();
2266 const MCExpr *Expr;
2267
Nirav Davee833c6c2016-11-08 18:31:04 +00002268 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002269 if (getParser().parseExpression(Expr))
2270 return MatchOperand_ParseFail;
2271
2272 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2273 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2274
2275 return MatchOperand_Success;
2276}
2277
2278/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002279OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002280AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002281 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002282 SMLoc S = getLoc();
2283
Nirav Davee833c6c2016-11-08 18:31:04 +00002284 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002285
2286 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002287 bool isNegative = parseOptionalToken(AsmToken::Minus);
2288
Tim Northover3b0846e2014-05-24 12:50:23 +00002289 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002290 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002291 int64_t Val;
Sander de Smalenbdf09fe2018-05-30 09:54:19 +00002292 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002293 Val = Tok.getIntVal();
Sander de Smalenbdf09fe2018-05-30 09:54:19 +00002294 if (Val > 255 || isNegative) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002295 TokError("encoded floating point value out of range");
2296 return MatchOperand_ParseFail;
2297 }
2298 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002299 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002300 if (isNegative)
2301 RealVal.changeSign();
2302
Tim Northover3b0846e2014-05-24 12:50:23 +00002303 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002304 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002305
John Brawn5ca5daa2017-04-20 10:13:54 +00002306 // Check for out of range values. As an exception we let Zero through,
2307 // but as tokens instead of an FPImm so that it can be matched by the
2308 // appropriate alias if one exists.
2309 if (RealVal.isPosZero()) {
2310 Parser.Lex(); // Eat the token.
2311 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2312 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2313 return MatchOperand_Success;
2314 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002315 TokError("expected compatible register or floating-point constant");
2316 return MatchOperand_ParseFail;
2317 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002318 }
2319 Parser.Lex(); // Eat the token.
2320 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2321 return MatchOperand_Success;
2322 }
2323
2324 if (!Hash)
2325 return MatchOperand_NoMatch;
2326
2327 TokError("invalid floating point immediate");
2328 return MatchOperand_ParseFail;
2329}
2330
Sander de Smalen62770792018-05-25 09:47:52 +00002331/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2332/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002333OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002334AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002335 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002336 SMLoc S = getLoc();
2337
2338 if (Parser.getTok().is(AsmToken::Hash))
2339 Parser.Lex(); // Eat '#'
2340 else if (Parser.getTok().isNot(AsmToken::Integer))
2341 // Operand should start from # or should be integer, emit error otherwise.
2342 return MatchOperand_NoMatch;
2343
2344 const MCExpr *Imm;
2345 if (parseSymbolicImmVal(Imm))
2346 return MatchOperand_ParseFail;
2347 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002348 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002349 Operands.push_back(
2350 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002351 return MatchOperand_Success;
2352 }
2353
2354 // Eat ','
2355 Parser.Lex();
2356
2357 // The optional operand must be "lsl #N" where N is non-negative.
2358 if (!Parser.getTok().is(AsmToken::Identifier) ||
2359 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2360 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2361 return MatchOperand_ParseFail;
2362 }
2363
2364 // Eat 'lsl'
2365 Parser.Lex();
2366
Nirav Davee833c6c2016-11-08 18:31:04 +00002367 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002368
2369 if (Parser.getTok().isNot(AsmToken::Integer)) {
2370 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2371 return MatchOperand_ParseFail;
2372 }
2373
2374 int64_t ShiftAmount = Parser.getTok().getIntVal();
2375
2376 if (ShiftAmount < 0) {
2377 Error(Parser.getTok().getLoc(), "positive shift amount required");
2378 return MatchOperand_ParseFail;
2379 }
2380 Parser.Lex(); // Eat the number
2381
Sander de Smalen62770792018-05-25 09:47:52 +00002382 // Just in case the optional lsl #0 is used for immediates other than zero.
2383 if (ShiftAmount == 0 && Imm != 0) {
2384 SMLoc E = Parser.getTok().getLoc();
2385 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2386 return MatchOperand_Success;
2387 }
2388
Tim Northover3b0846e2014-05-24 12:50:23 +00002389 SMLoc E = Parser.getTok().getLoc();
2390 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2391 S, E, getContext()));
2392 return MatchOperand_Success;
2393}
2394
2395/// parseCondCodeString - Parse a Condition Code string.
2396AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2397 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2398 .Case("eq", AArch64CC::EQ)
2399 .Case("ne", AArch64CC::NE)
2400 .Case("cs", AArch64CC::HS)
2401 .Case("hs", AArch64CC::HS)
2402 .Case("cc", AArch64CC::LO)
2403 .Case("lo", AArch64CC::LO)
2404 .Case("mi", AArch64CC::MI)
2405 .Case("pl", AArch64CC::PL)
2406 .Case("vs", AArch64CC::VS)
2407 .Case("vc", AArch64CC::VC)
2408 .Case("hi", AArch64CC::HI)
2409 .Case("ls", AArch64CC::LS)
2410 .Case("ge", AArch64CC::GE)
2411 .Case("lt", AArch64CC::LT)
2412 .Case("gt", AArch64CC::GT)
2413 .Case("le", AArch64CC::LE)
2414 .Case("al", AArch64CC::AL)
2415 .Case("nv", AArch64CC::NV)
2416 .Default(AArch64CC::Invalid);
2417 return CC;
2418}
2419
2420/// parseCondCode - Parse a Condition Code operand.
2421bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2422 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002423 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002424 SMLoc S = getLoc();
2425 const AsmToken &Tok = Parser.getTok();
2426 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2427
2428 StringRef Cond = Tok.getString();
2429 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2430 if (CC == AArch64CC::Invalid)
2431 return TokError("invalid condition code");
2432 Parser.Lex(); // Eat identifier token.
2433
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002434 if (invertCondCode) {
2435 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2436 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002437 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002438 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002439
2440 Operands.push_back(
2441 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2442 return false;
2443}
2444
2445/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2446/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002447OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002448AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002449 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002450 const AsmToken &Tok = Parser.getTok();
2451 std::string LowerID = Tok.getString().lower();
2452 AArch64_AM::ShiftExtendType ShOp =
2453 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2454 .Case("lsl", AArch64_AM::LSL)
2455 .Case("lsr", AArch64_AM::LSR)
2456 .Case("asr", AArch64_AM::ASR)
2457 .Case("ror", AArch64_AM::ROR)
2458 .Case("msl", AArch64_AM::MSL)
2459 .Case("uxtb", AArch64_AM::UXTB)
2460 .Case("uxth", AArch64_AM::UXTH)
2461 .Case("uxtw", AArch64_AM::UXTW)
2462 .Case("uxtx", AArch64_AM::UXTX)
2463 .Case("sxtb", AArch64_AM::SXTB)
2464 .Case("sxth", AArch64_AM::SXTH)
2465 .Case("sxtw", AArch64_AM::SXTW)
2466 .Case("sxtx", AArch64_AM::SXTX)
2467 .Default(AArch64_AM::InvalidShiftExtend);
2468
2469 if (ShOp == AArch64_AM::InvalidShiftExtend)
2470 return MatchOperand_NoMatch;
2471
2472 SMLoc S = Tok.getLoc();
2473 Parser.Lex();
2474
Nirav Davee833c6c2016-11-08 18:31:04 +00002475 bool Hash = parseOptionalToken(AsmToken::Hash);
2476
Tim Northover3b0846e2014-05-24 12:50:23 +00002477 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2478 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2479 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2480 ShOp == AArch64_AM::MSL) {
2481 // We expect a number here.
2482 TokError("expected #imm after shift specifier");
2483 return MatchOperand_ParseFail;
2484 }
2485
Chad Rosier2ff37b82016-12-27 16:58:09 +00002486 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002487 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2488 Operands.push_back(
2489 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2490 return MatchOperand_Success;
2491 }
2492
Chad Rosier2ff37b82016-12-27 16:58:09 +00002493 // Make sure we do actually have a number, identifier or a parenthesized
2494 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002495 SMLoc E = Parser.getTok().getLoc();
2496 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002497 !Parser.getTok().is(AsmToken::LParen) &&
2498 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002499 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002500 return MatchOperand_ParseFail;
2501 }
2502
2503 const MCExpr *ImmVal;
2504 if (getParser().parseExpression(ImmVal))
2505 return MatchOperand_ParseFail;
2506
2507 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2508 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002509 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002510 return MatchOperand_ParseFail;
2511 }
2512
Jim Grosbach57fd2622014-09-23 22:16:02 +00002513 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002514 Operands.push_back(AArch64Operand::CreateShiftExtend(
2515 ShOp, MCE->getValue(), true, S, E, getContext()));
2516 return MatchOperand_Success;
2517}
2518
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002519static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2520 if (FBS[AArch64::HasV8_1aOps])
2521 Str += "ARMv8.1a";
2522 else if (FBS[AArch64::HasV8_2aOps])
2523 Str += "ARMv8.2a";
2524 else
2525 Str += "(unknown)";
2526}
2527
2528void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2529 SMLoc S) {
2530 const uint16_t Op2 = Encoding & 7;
2531 const uint16_t Cm = (Encoding & 0x78) >> 3;
2532 const uint16_t Cn = (Encoding & 0x780) >> 7;
2533 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2534
2535 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2536
2537 Operands.push_back(
2538 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2539 Operands.push_back(
2540 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2541 Operands.push_back(
2542 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2543 Expr = MCConstantExpr::create(Op2, getContext());
2544 Operands.push_back(
2545 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2546}
2547
Tim Northover3b0846e2014-05-24 12:50:23 +00002548/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2549/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2550bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2551 OperandVector &Operands) {
2552 if (Name.find('.') != StringRef::npos)
2553 return TokError("invalid operand");
2554
2555 Mnemonic = Name;
2556 Operands.push_back(
2557 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2558
Rafael Espindola961d4692014-11-11 05:18:41 +00002559 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002560 const AsmToken &Tok = Parser.getTok();
2561 StringRef Op = Tok.getString();
2562 SMLoc S = Tok.getLoc();
2563
Tim Northover3b0846e2014-05-24 12:50:23 +00002564 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002565 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2566 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002567 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002568 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2569 std::string Str("IC " + std::string(IC->Name) + " requires ");
2570 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2571 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002572 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002573 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002574 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002575 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2576 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002577 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002578 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2579 std::string Str("DC " + std::string(DC->Name) + " requires ");
2580 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2581 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002582 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002583 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002584 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002585 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2586 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002587 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002588 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2589 std::string Str("AT " + std::string(AT->Name) + " requires ");
2590 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2591 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002592 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002593 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002594 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002595 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2596 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002597 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002598 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2599 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2600 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2601 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002602 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002603 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002604 }
2605
Tim Northover3b0846e2014-05-24 12:50:23 +00002606 Parser.Lex(); // Eat operand.
2607
2608 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2609 bool HasRegister = false;
2610
2611 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002612 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002613 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2614 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002615 HasRegister = true;
2616 }
2617
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002618 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002619 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002620 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002621 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002622
Nirav Davee833c6c2016-11-08 18:31:04 +00002623 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2624 return true;
2625
Tim Northover3b0846e2014-05-24 12:50:23 +00002626 return false;
2627}
2628
Alex Bradbury58eba092016-11-01 16:32:05 +00002629OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002630AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002631 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002632 const AsmToken &Tok = Parser.getTok();
2633
2634 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002635 if (parseOptionalToken(AsmToken::Hash) ||
2636 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002637 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002638 const MCExpr *ImmVal;
2639 SMLoc ExprLoc = getLoc();
2640 if (getParser().parseExpression(ImmVal))
2641 return MatchOperand_ParseFail;
2642 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2643 if (!MCE) {
2644 Error(ExprLoc, "immediate value expected for barrier operand");
2645 return MatchOperand_ParseFail;
2646 }
2647 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2648 Error(ExprLoc, "barrier operand out of range");
2649 return MatchOperand_ParseFail;
2650 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002651 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2652 Operands.push_back(AArch64Operand::CreateBarrier(
2653 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002654 return MatchOperand_Success;
2655 }
2656
2657 if (Tok.isNot(AsmToken::Identifier)) {
2658 TokError("invalid operand for instruction");
2659 return MatchOperand_ParseFail;
2660 }
2661
Tim Northover3b0846e2014-05-24 12:50:23 +00002662 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002663 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2664 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002665 TokError("'sy' or #imm operand expected");
2666 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002667 } else if (!DB) {
2668 TokError("invalid barrier option name");
2669 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002670 }
2671
Tim Northovere6ae6762016-07-05 21:23:04 +00002672 Operands.push_back(AArch64Operand::CreateBarrier(
2673 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002674 Parser.Lex(); // Consume the option
2675
2676 return MatchOperand_Success;
2677}
2678
Alex Bradbury58eba092016-11-01 16:32:05 +00002679OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002680AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002681 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002682 const AsmToken &Tok = Parser.getTok();
2683
2684 if (Tok.isNot(AsmToken::Identifier))
2685 return MatchOperand_NoMatch;
2686
Tim Northovere6ae6762016-07-05 21:23:04 +00002687 int MRSReg, MSRReg;
2688 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2689 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2690 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2691 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2692 } else
2693 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002694
Tim Northovere6ae6762016-07-05 21:23:04 +00002695 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2696 unsigned PStateImm = -1;
2697 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2698 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002699
Tim Northovere6ae6762016-07-05 21:23:04 +00002700 Operands.push_back(
2701 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2702 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002703 Parser.Lex(); // Eat identifier
2704
2705 return MatchOperand_Success;
2706}
2707
Florian Hahnc4422242017-11-07 13:07:50 +00002708/// tryParseNeonVectorRegister - Parse a vector register operand.
2709bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002710 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002711 if (Parser.getTok().isNot(AsmToken::Identifier))
2712 return true;
2713
2714 SMLoc S = getLoc();
2715 // Check for a vector register specifier first.
2716 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002717 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002718 OperandMatchResultTy Res =
2719 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2720 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002721 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002722
2723 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2724 if (!KindRes)
2725 return true;
2726
2727 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002728 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002729 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2730 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002731
Tim Northover3b0846e2014-05-24 12:50:23 +00002732 // If there was an explicit qualifier, that goes on as a literal text
2733 // operand.
2734 if (!Kind.empty())
2735 Operands.push_back(
2736 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2737
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002738 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2739}
2740
2741OperandMatchResultTy
2742AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002743 SMLoc SIdx = getLoc();
2744 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002745 const MCExpr *ImmVal;
2746 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002747 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002748 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2749 if (!MCE) {
2750 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002751 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002752 }
2753
2754 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002755
Nirav Davee833c6c2016-11-08 18:31:04 +00002756 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002757 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002758
2759 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2760 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002761 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002762 }
2763
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002764 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002765}
2766
Sander de Smalen73937b72018-04-11 07:36:10 +00002767// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002768// optional kind specifier. If it is a register specifier, eat the token
2769// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002770OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002771AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002772 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002773 MCAsmParser &Parser = getParser();
2774 const AsmToken &Tok = Parser.getTok();
2775
Florian Hahn91f11e52017-11-07 16:45:48 +00002776 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002777 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002778
2779 StringRef Name = Tok.getString();
2780 // If there is a kind specifier, it's separated from the register name by
2781 // a '.'.
2782 size_t Start = 0, Next = Name.find('.');
2783 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002784 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002785
2786 if (RegNum) {
2787 if (Next != StringRef::npos) {
2788 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002789 if (!isValidVectorKind(Kind, MatchKind)) {
2790 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002791 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002792 }
2793 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002794 Parser.Lex(); // Eat the register token.
2795
2796 Reg = RegNum;
2797 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002798 }
2799
Sander de Smalen8e607342017-11-15 15:44:43 +00002800 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002801}
2802
Sander de Smalencd6be962017-12-20 11:02:42 +00002803/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2804OperandMatchResultTy
2805AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2806 // Check for a SVE predicate register specifier first.
2807 const SMLoc S = getLoc();
2808 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002809 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002810 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002811 if (Res != MatchOperand_Success)
2812 return Res;
2813
Sander de Smalen73937b72018-04-11 07:36:10 +00002814 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2815 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002816 return MatchOperand_NoMatch;
2817
Sander de Smalen73937b72018-04-11 07:36:10 +00002818 unsigned ElementWidth = KindRes->second;
2819 Operands.push_back(AArch64Operand::CreateVectorReg(
2820 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2821 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002822
Sander de Smalen7868e742018-01-09 11:17:06 +00002823 // Not all predicates are followed by a '/m' or '/z'.
2824 MCAsmParser &Parser = getParser();
2825 if (Parser.getTok().isNot(AsmToken::Slash))
2826 return MatchOperand_Success;
2827
2828 // But when they do they shouldn't have an element type suffix.
2829 if (!Kind.empty()) {
2830 Error(S, "not expecting size suffix");
2831 return MatchOperand_ParseFail;
2832 }
2833
2834 // Add a literal slash as operand
2835 Operands.push_back(
2836 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2837
2838 Parser.Lex(); // Eat the slash.
2839
2840 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002841 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002842 if (Pred != "z" && Pred != "m") {
2843 Error(getLoc(), "expecting 'm' or 'z' predication");
2844 return MatchOperand_ParseFail;
2845 }
2846
2847 // Add zero/merge token.
2848 const char *ZM = Pred == "z" ? "z" : "m";
2849 Operands.push_back(
2850 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2851
2852 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002853 return MatchOperand_Success;
2854}
2855
Sander de Smalen50d87022018-04-19 07:35:08 +00002856/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002857bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002858 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002859 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002860 return false;
2861
Sander de Smalen149916d2018-04-20 07:24:20 +00002862 // Otherwise try for a scalar register.
2863 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
2864 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002865
Sander de Smalen149916d2018-04-20 07:24:20 +00002866 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002867}
2868
2869bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002870 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002871 bool HasELFModifier = false;
2872 AArch64MCExpr::VariantKind RefKind;
2873
Nirav Davee833c6c2016-11-08 18:31:04 +00002874 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002875 HasELFModifier = true;
2876
Nirav Davee833c6c2016-11-08 18:31:04 +00002877 if (Parser.getTok().isNot(AsmToken::Identifier))
2878 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002879
2880 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2881 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2882 .Case("lo12", AArch64MCExpr::VK_LO12)
2883 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2884 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2885 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2886 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2887 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2888 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2889 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2890 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2891 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2892 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2893 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2894 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2895 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2896 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2897 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2898 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2899 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2900 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2901 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2902 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2903 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2904 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2905 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2906 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2907 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2908 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2909 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2910 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2911 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2912 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2913 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2914 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2915 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2916 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002917 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2918 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002919 .Default(AArch64MCExpr::VK_INVALID);
2920
Nirav Davee833c6c2016-11-08 18:31:04 +00002921 if (RefKind == AArch64MCExpr::VK_INVALID)
2922 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002923
2924 Parser.Lex(); // Eat identifier
2925
Nirav Davee833c6c2016-11-08 18:31:04 +00002926 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002927 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002928 }
2929
2930 if (getParser().parseExpression(ImmVal))
2931 return true;
2932
2933 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002934 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002935
2936 return false;
2937}
2938
Sander de Smalen650234b2018-04-12 11:40:52 +00002939template <RegKind VectorKind>
2940OperandMatchResultTy
2941AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
2942 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002943 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00002944 if (!Parser.getTok().is(AsmToken::LCurly))
2945 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002946
2947 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00002948 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00002949 bool NoMatchIsError) {
2950 auto RegTok = Parser.getTok();
2951 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
2952 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002953 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00002954 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002955 llvm_unreachable("Expected a valid vector kind");
2956 }
2957
Sander de Smalen650234b2018-04-12 11:40:52 +00002958 if (RegTok.isNot(AsmToken::Identifier) ||
2959 ParseRes == MatchOperand_ParseFail ||
2960 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
2961 Error(Loc, "vector register expected");
2962 return MatchOperand_ParseFail;
2963 }
2964
2965 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002966 };
2967
Tim Northover3b0846e2014-05-24 12:50:23 +00002968 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00002969 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00002970 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00002971
Tim Northover3b0846e2014-05-24 12:50:23 +00002972 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002973 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002974 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
2975
2976 // Put back the original left bracket if there was no match, so that
2977 // different types of list-operands can be matched (e.g. SVE, Neon).
2978 if (ParseRes == MatchOperand_NoMatch)
2979 Parser.getLexer().UnLex(LCurly);
2980
2981 if (ParseRes != MatchOperand_Success)
2982 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002983
Tim Northover3b0846e2014-05-24 12:50:23 +00002984 int64_t PrevReg = FirstReg;
2985 unsigned Count = 1;
2986
Nirav Davee833c6c2016-11-08 18:31:04 +00002987 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002988 SMLoc Loc = getLoc();
2989 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002990
Sander de Smalen50d87022018-04-19 07:35:08 +00002991 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002992 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2993 if (ParseRes != MatchOperand_Success)
2994 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002995
Tim Northover3b0846e2014-05-24 12:50:23 +00002996 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002997 if (Kind != NextKind) {
2998 Error(Loc, "mismatched register size suffix");
2999 return MatchOperand_ParseFail;
3000 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003001
3002 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3003
3004 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003005 Error(Loc, "invalid number of vectors");
3006 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003007 }
3008
3009 Count += Space;
3010 }
3011 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003012 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003013 SMLoc Loc = getLoc();
3014 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003015 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003016 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3017 if (ParseRes != MatchOperand_Success)
3018 return ParseRes;
3019
Tim Northover3b0846e2014-05-24 12:50:23 +00003020 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003021 if (Kind != NextKind) {
3022 Error(Loc, "mismatched register size suffix");
3023 return MatchOperand_ParseFail;
3024 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003025
3026 // Registers must be incremental (with wraparound at 31)
3027 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003028 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3029 Error(Loc, "registers must be sequential");
3030 return MatchOperand_ParseFail;
3031 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003032
3033 PrevReg = Reg;
3034 ++Count;
3035 }
3036 }
3037
Nirav Davee833c6c2016-11-08 18:31:04 +00003038 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003039 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003040
Sander de Smalen650234b2018-04-12 11:40:52 +00003041 if (Count > 4) {
3042 Error(S, "invalid number of vectors");
3043 return MatchOperand_ParseFail;
3044 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003045
3046 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003047 unsigned ElementWidth = 0;
3048 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003049 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003050 std::tie(NumElements, ElementWidth) = *VK;
3051 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003052
3053 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003054 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3055 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003056
Sander de Smalen650234b2018-04-12 11:40:52 +00003057 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003058}
3059
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003060/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3061bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003062 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3063 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003064 return true;
3065
3066 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3067}
3068
Alex Bradbury58eba092016-11-01 16:32:05 +00003069OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003070AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003071 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003072
Sander de Smalen50d87022018-04-19 07:35:08 +00003073 unsigned RegNum;
3074 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3075 if (Res != MatchOperand_Success)
3076 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003077
Nirav Davee833c6c2016-11-08 18:31:04 +00003078 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003079 Operands.push_back(AArch64Operand::CreateReg(
3080 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003081 return MatchOperand_Success;
3082 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003083
Nirav Davee833c6c2016-11-08 18:31:04 +00003084 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003085
Sander de Smalen50d87022018-04-19 07:35:08 +00003086 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003087 Error(getLoc(), "index must be absent or #0");
3088 return MatchOperand_ParseFail;
3089 }
3090
3091 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003092 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003093 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3094 Error(getLoc(), "index must be absent or #0");
3095 return MatchOperand_ParseFail;
3096 }
3097
Sander de Smalen50d87022018-04-19 07:35:08 +00003098 Operands.push_back(AArch64Operand::CreateReg(
3099 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003100 return MatchOperand_Success;
3101}
3102
Sander de Smalen149916d2018-04-20 07:24:20 +00003103template <bool ParseShiftExtend>
3104OperandMatchResultTy
3105AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3106 SMLoc StartLoc = getLoc();
3107
3108 unsigned RegNum;
3109 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3110 if (Res != MatchOperand_Success)
3111 return Res;
3112
3113 // No shift/extend is the default.
3114 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3115 Operands.push_back(AArch64Operand::CreateReg(
3116 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
3117 return MatchOperand_Success;
3118 }
3119
3120 // Eat the comma
3121 getParser().Lex();
3122
3123 // Match the shift
3124 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3125 Res = tryParseOptionalShiftExtend(ExtOpnd);
3126 if (Res != MatchOperand_Success)
3127 return Res;
3128
3129 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
3130 Operands.push_back(AArch64Operand::CreateReg(RegNum, RegKind::Scalar,
3131 StartLoc, Ext->getEndLoc(), getContext(),
3132 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3133 Ext->hasShiftExtendAmount()));
3134
3135 return MatchOperand_Success;
3136}
3137
Sander de Smalen5c625982018-04-13 12:56:14 +00003138bool AArch64AsmParser::parseOptionalMulVl(OperandVector &Operands) {
3139 MCAsmParser &Parser = getParser();
3140
3141 // Some SVE instructions have a decoration after the immediate, i.e.
3142 // "mul vl". We parse them here and add tokens, which must be present in the
3143 // asm string in the tablegen instruction.
3144 if (!Parser.getTok().getString().equals_lower("mul") ||
3145 !Parser.getLexer().peekTok().getString().equals_lower("vl"))
3146 return true;
3147
3148 SMLoc S = getLoc();
3149 Operands.push_back(
3150 AArch64Operand::CreateToken("mul", false, S, getContext()));
3151 Parser.Lex(); // Eat the "mul"
3152
3153 S = getLoc();
3154 Operands.push_back(
3155 AArch64Operand::CreateToken("vl", false, S, getContext()));
3156 Parser.Lex(); // Eat the "vl"
3157
3158 return false;
3159}
3160
Tim Northover3b0846e2014-05-24 12:50:23 +00003161/// parseOperand - Parse a arm instruction operand. For now this parses the
3162/// operand regardless of the mnemonic.
3163bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3164 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003165 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003166
3167 OperandMatchResultTy ResTy =
3168 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3169
Tim Northover3b0846e2014-05-24 12:50:23 +00003170 // Check if the current operand has a custom associated parser, if so, try to
3171 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003172 if (ResTy == MatchOperand_Success)
3173 return false;
3174 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3175 // there was a match, but an error occurred, in which case, just return that
3176 // the operand parsing failed.
3177 if (ResTy == MatchOperand_ParseFail)
3178 return true;
3179
3180 // Nothing custom, so do general case parsing.
3181 SMLoc S, E;
3182 switch (getLexer().getKind()) {
3183 default: {
3184 SMLoc S = getLoc();
3185 const MCExpr *Expr;
3186 if (parseSymbolicImmVal(Expr))
3187 return Error(S, "invalid operand");
3188
3189 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3190 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3191 return false;
3192 }
3193 case AsmToken::LBrac: {
3194 SMLoc Loc = Parser.getTok().getLoc();
3195 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3196 getContext()));
3197 Parser.Lex(); // Eat '['
3198
3199 // There's no comma after a '[', so we can parse the next operand
3200 // immediately.
3201 return parseOperand(Operands, false, false);
3202 }
3203 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003204 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003205 case AsmToken::Identifier: {
3206 // If we're expecting a Condition Code operand, then just parse that.
3207 if (isCondCode)
3208 return parseCondCode(Operands, invertCondCode);
3209
3210 // If it's a register name, parse it.
3211 if (!parseRegister(Operands))
3212 return false;
3213
Sander de Smalen5c625982018-04-13 12:56:14 +00003214 // See if this is a "mul vl" decoration used by SVE instructions.
3215 if (!parseOptionalMulVl(Operands))
3216 return false;
3217
Tim Northover3b0846e2014-05-24 12:50:23 +00003218 // This could be an optional "shift" or "extend" operand.
3219 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3220 // We can only continue if no tokens were eaten.
3221 if (GotShift != MatchOperand_NoMatch)
3222 return GotShift;
3223
3224 // This was not a register so parse other operands that start with an
3225 // identifier (like labels) as expressions and create them as immediates.
3226 const MCExpr *IdVal;
3227 S = getLoc();
3228 if (getParser().parseExpression(IdVal))
3229 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003230 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3231 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3232 return false;
3233 }
3234 case AsmToken::Integer:
3235 case AsmToken::Real:
3236 case AsmToken::Hash: {
3237 // #42 -> immediate.
3238 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003239
3240 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003241
3242 // Parse a negative sign
3243 bool isNegative = false;
3244 if (Parser.getTok().is(AsmToken::Minus)) {
3245 isNegative = true;
3246 // We need to consume this token only when we have a Real, otherwise
3247 // we let parseSymbolicImmVal take care of it
3248 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3249 Parser.Lex();
3250 }
3251
3252 // The only Real that should come through here is a literal #0.0 for
3253 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3254 // so convert the value.
3255 const AsmToken &Tok = Parser.getTok();
3256 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003257 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003258 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3259 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3260 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3261 Mnemonic != "fcmlt")
3262 return TokError("unexpected floating point literal");
3263 else if (IntVal != 0 || isNegative)
3264 return TokError("expected floating-point constant #0.0");
3265 Parser.Lex(); // Eat the token.
3266
3267 Operands.push_back(
3268 AArch64Operand::CreateToken("#0", false, S, getContext()));
3269 Operands.push_back(
3270 AArch64Operand::CreateToken(".0", false, S, getContext()));
3271 return false;
3272 }
3273
3274 const MCExpr *ImmVal;
3275 if (parseSymbolicImmVal(ImmVal))
3276 return true;
3277
3278 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3279 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3280 return false;
3281 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003282 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003283 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003284 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003285 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003286 Parser.Lex(); // Eat '='
3287 const MCExpr *SubExprVal;
3288 if (getParser().parseExpression(SubExprVal))
3289 return true;
3290
David Peixottoae5ba762014-07-18 16:05:14 +00003291 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003292 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003293 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003294
3295 bool IsXReg =
3296 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3297 Operands[1]->getReg());
3298
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003299 MCContext& Ctx = getContext();
3300 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3301 // 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 +00003302 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003303 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3304 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3305 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3306 ShiftAmt += 16;
3307 Imm >>= 16;
3308 }
3309 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3310 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3311 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003312 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003313 if (ShiftAmt)
3314 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3315 ShiftAmt, true, S, E, Ctx));
3316 return false;
3317 }
David Peixottoae5ba762014-07-18 16:05:14 +00003318 APInt Simm = APInt(64, Imm << ShiftAmt);
3319 // check if the immediate is an unsigned or signed 32-bit int for W regs
3320 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3321 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003322 }
3323 // 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 +00003324 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003325 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003326 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3327 return false;
3328 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003329 }
3330}
3331
3332/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3333/// operands.
3334bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3335 StringRef Name, SMLoc NameLoc,
3336 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003337 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003338 Name = StringSwitch<StringRef>(Name.lower())
3339 .Case("beq", "b.eq")
3340 .Case("bne", "b.ne")
3341 .Case("bhs", "b.hs")
3342 .Case("bcs", "b.cs")
3343 .Case("blo", "b.lo")
3344 .Case("bcc", "b.cc")
3345 .Case("bmi", "b.mi")
3346 .Case("bpl", "b.pl")
3347 .Case("bvs", "b.vs")
3348 .Case("bvc", "b.vc")
3349 .Case("bhi", "b.hi")
3350 .Case("bls", "b.ls")
3351 .Case("bge", "b.ge")
3352 .Case("blt", "b.lt")
3353 .Case("bgt", "b.gt")
3354 .Case("ble", "b.le")
3355 .Case("bal", "b.al")
3356 .Case("bnv", "b.nv")
3357 .Default(Name);
3358
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003359 // First check for the AArch64-specific .req directive.
3360 if (Parser.getTok().is(AsmToken::Identifier) &&
3361 Parser.getTok().getIdentifier() == ".req") {
3362 parseDirectiveReq(Name, NameLoc);
3363 // We always return 'error' for this, as we're done with this
3364 // statement and don't need to match the 'instruction."
3365 return true;
3366 }
3367
Tim Northover3b0846e2014-05-24 12:50:23 +00003368 // Create the leading tokens for the mnemonic, split by '.' characters.
3369 size_t Start = 0, Next = Name.find('.');
3370 StringRef Head = Name.slice(Start, Next);
3371
3372 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003373 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3374 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003375
3376 Operands.push_back(
3377 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3378 Mnemonic = Head;
3379
3380 // Handle condition codes for a branch mnemonic
3381 if (Head == "b" && Next != StringRef::npos) {
3382 Start = Next;
3383 Next = Name.find('.', Start + 1);
3384 Head = Name.slice(Start + 1, Next);
3385
3386 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3387 (Head.data() - Name.data()));
3388 AArch64CC::CondCode CC = parseCondCodeString(Head);
3389 if (CC == AArch64CC::Invalid)
3390 return Error(SuffixLoc, "invalid condition code");
3391 Operands.push_back(
3392 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3393 Operands.push_back(
3394 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3395 }
3396
3397 // Add the remaining tokens in the mnemonic.
3398 while (Next != StringRef::npos) {
3399 Start = Next;
3400 Next = Name.find('.', Start + 1);
3401 Head = Name.slice(Start, Next);
3402 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3403 (Head.data() - Name.data()) + 1);
3404 Operands.push_back(
3405 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3406 }
3407
3408 // Conditional compare instructions have a Condition Code operand, which needs
3409 // to be parsed and an immediate operand created.
3410 bool condCodeFourthOperand =
3411 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3412 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3413 Head == "csinc" || Head == "csinv" || Head == "csneg");
3414
3415 // These instructions are aliases to some of the conditional select
3416 // instructions. However, the condition code is inverted in the aliased
3417 // instruction.
3418 //
3419 // FIXME: Is this the correct way to handle these? Or should the parser
3420 // generate the aliased instructions directly?
3421 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3422 bool condCodeThirdOperand =
3423 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3424
3425 // Read the remaining operands.
3426 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3427 // Read the first operand.
3428 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003429 return true;
3430 }
3431
3432 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003433 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003434 // Parse and remember the operand.
3435 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3436 (N == 3 && condCodeThirdOperand) ||
3437 (N == 2 && condCodeSecondOperand),
3438 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003439 return true;
3440 }
3441
3442 // After successfully parsing some operands there are two special cases to
3443 // consider (i.e. notional operands not separated by commas). Both are due
3444 // to memory specifiers:
3445 // + An RBrac will end an address for load/store/prefetch
3446 // + An '!' will indicate a pre-indexed operation.
3447 //
3448 // It's someone else's responsibility to make sure these tokens are sane
3449 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003450
Nirav Davee833c6c2016-11-08 18:31:04 +00003451 SMLoc RLoc = Parser.getTok().getLoc();
3452 if (parseOptionalToken(AsmToken::RBrac))
3453 Operands.push_back(
3454 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3455 SMLoc ELoc = Parser.getTok().getLoc();
3456 if (parseOptionalToken(AsmToken::Exclaim))
3457 Operands.push_back(
3458 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003459
3460 ++N;
3461 }
3462 }
3463
Nirav Davee833c6c2016-11-08 18:31:04 +00003464 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3465 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003466
Tim Northover3b0846e2014-05-24 12:50:23 +00003467 return false;
3468}
3469
3470// FIXME: This entire function is a giant hack to provide us with decent
3471// operand range validation/diagnostics until TableGen/MC can be extended
3472// to support autogeneration of this kind of validation.
3473bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3474 SmallVectorImpl<SMLoc> &Loc) {
3475 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3476 // Check for indexed addressing modes w/ the base register being the
3477 // same as a destination/source register or pair load where
3478 // the Rt == Rt2. All of those are undefined behaviour.
3479 switch (Inst.getOpcode()) {
3480 case AArch64::LDPSWpre:
3481 case AArch64::LDPWpost:
3482 case AArch64::LDPWpre:
3483 case AArch64::LDPXpost:
3484 case AArch64::LDPXpre: {
3485 unsigned Rt = Inst.getOperand(1).getReg();
3486 unsigned Rt2 = Inst.getOperand(2).getReg();
3487 unsigned Rn = Inst.getOperand(3).getReg();
3488 if (RI->isSubRegisterEq(Rn, Rt))
3489 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3490 "is also a destination");
3491 if (RI->isSubRegisterEq(Rn, Rt2))
3492 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3493 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003494 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003495 }
3496 case AArch64::LDPDi:
3497 case AArch64::LDPQi:
3498 case AArch64::LDPSi:
3499 case AArch64::LDPSWi:
3500 case AArch64::LDPWi:
3501 case AArch64::LDPXi: {
3502 unsigned Rt = Inst.getOperand(0).getReg();
3503 unsigned Rt2 = Inst.getOperand(1).getReg();
3504 if (Rt == Rt2)
3505 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3506 break;
3507 }
3508 case AArch64::LDPDpost:
3509 case AArch64::LDPDpre:
3510 case AArch64::LDPQpost:
3511 case AArch64::LDPQpre:
3512 case AArch64::LDPSpost:
3513 case AArch64::LDPSpre:
3514 case AArch64::LDPSWpost: {
3515 unsigned Rt = Inst.getOperand(1).getReg();
3516 unsigned Rt2 = Inst.getOperand(2).getReg();
3517 if (Rt == Rt2)
3518 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3519 break;
3520 }
3521 case AArch64::STPDpost:
3522 case AArch64::STPDpre:
3523 case AArch64::STPQpost:
3524 case AArch64::STPQpre:
3525 case AArch64::STPSpost:
3526 case AArch64::STPSpre:
3527 case AArch64::STPWpost:
3528 case AArch64::STPWpre:
3529 case AArch64::STPXpost:
3530 case AArch64::STPXpre: {
3531 unsigned Rt = Inst.getOperand(1).getReg();
3532 unsigned Rt2 = Inst.getOperand(2).getReg();
3533 unsigned Rn = Inst.getOperand(3).getReg();
3534 if (RI->isSubRegisterEq(Rn, Rt))
3535 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3536 "is also a source");
3537 if (RI->isSubRegisterEq(Rn, Rt2))
3538 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3539 "is also a source");
3540 break;
3541 }
3542 case AArch64::LDRBBpre:
3543 case AArch64::LDRBpre:
3544 case AArch64::LDRHHpre:
3545 case AArch64::LDRHpre:
3546 case AArch64::LDRSBWpre:
3547 case AArch64::LDRSBXpre:
3548 case AArch64::LDRSHWpre:
3549 case AArch64::LDRSHXpre:
3550 case AArch64::LDRSWpre:
3551 case AArch64::LDRWpre:
3552 case AArch64::LDRXpre:
3553 case AArch64::LDRBBpost:
3554 case AArch64::LDRBpost:
3555 case AArch64::LDRHHpost:
3556 case AArch64::LDRHpost:
3557 case AArch64::LDRSBWpost:
3558 case AArch64::LDRSBXpost:
3559 case AArch64::LDRSHWpost:
3560 case AArch64::LDRSHXpost:
3561 case AArch64::LDRSWpost:
3562 case AArch64::LDRWpost:
3563 case AArch64::LDRXpost: {
3564 unsigned Rt = Inst.getOperand(1).getReg();
3565 unsigned Rn = Inst.getOperand(2).getReg();
3566 if (RI->isSubRegisterEq(Rn, Rt))
3567 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3568 "is also a source");
3569 break;
3570 }
3571 case AArch64::STRBBpost:
3572 case AArch64::STRBpost:
3573 case AArch64::STRHHpost:
3574 case AArch64::STRHpost:
3575 case AArch64::STRWpost:
3576 case AArch64::STRXpost:
3577 case AArch64::STRBBpre:
3578 case AArch64::STRBpre:
3579 case AArch64::STRHHpre:
3580 case AArch64::STRHpre:
3581 case AArch64::STRWpre:
3582 case AArch64::STRXpre: {
3583 unsigned Rt = Inst.getOperand(1).getReg();
3584 unsigned Rn = Inst.getOperand(2).getReg();
3585 if (RI->isSubRegisterEq(Rn, Rt))
3586 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3587 "is also a source");
3588 break;
3589 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003590 case AArch64::STXRB:
3591 case AArch64::STXRH:
3592 case AArch64::STXRW:
3593 case AArch64::STXRX:
3594 case AArch64::STLXRB:
3595 case AArch64::STLXRH:
3596 case AArch64::STLXRW:
3597 case AArch64::STLXRX: {
3598 unsigned Rs = Inst.getOperand(0).getReg();
3599 unsigned Rt = Inst.getOperand(1).getReg();
3600 unsigned Rn = Inst.getOperand(2).getReg();
3601 if (RI->isSubRegisterEq(Rt, Rs) ||
3602 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3603 return Error(Loc[0],
3604 "unpredictable STXR instruction, status is also a source");
3605 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003606 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003607 case AArch64::STXPW:
3608 case AArch64::STXPX:
3609 case AArch64::STLXPW:
3610 case AArch64::STLXPX: {
3611 unsigned Rs = Inst.getOperand(0).getReg();
3612 unsigned Rt1 = Inst.getOperand(1).getReg();
3613 unsigned Rt2 = Inst.getOperand(2).getReg();
3614 unsigned Rn = Inst.getOperand(3).getReg();
3615 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3616 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3617 return Error(Loc[0],
3618 "unpredictable STXP instruction, status is also a source");
3619 break;
3620 }
3621 }
3622
Tim Northover3b0846e2014-05-24 12:50:23 +00003623
3624 // Now check immediate ranges. Separate from the above as there is overlap
3625 // in the instructions being checked and this keeps the nested conditionals
3626 // to a minimum.
3627 switch (Inst.getOpcode()) {
3628 case AArch64::ADDSWri:
3629 case AArch64::ADDSXri:
3630 case AArch64::ADDWri:
3631 case AArch64::ADDXri:
3632 case AArch64::SUBSWri:
3633 case AArch64::SUBSXri:
3634 case AArch64::SUBWri:
3635 case AArch64::SUBXri: {
3636 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3637 // some slight duplication here.
3638 if (Inst.getOperand(2).isExpr()) {
3639 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3640 AArch64MCExpr::VariantKind ELFRefKind;
3641 MCSymbolRefExpr::VariantKind DarwinRefKind;
3642 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003643 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3644
3645 // Only allow these with ADDXri.
3646 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3647 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3648 Inst.getOpcode() == AArch64::ADDXri)
3649 return false;
3650
3651 // Only allow these with ADDXri/ADDWri
3652 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3653 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3654 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3655 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3656 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3657 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3658 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003659 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3660 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3661 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003662 (Inst.getOpcode() == AArch64::ADDXri ||
3663 Inst.getOpcode() == AArch64::ADDWri))
3664 return false;
3665
3666 // Don't allow symbol refs in the immediate field otherwise
3667 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3668 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3669 // 'cmp w0, 'borked')
3670 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003671 }
Diana Picusc93518d2016-10-11 09:17:47 +00003672 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003673 }
3674 return false;
3675 }
3676 default:
3677 return false;
3678 }
3679}
3680
Craig Topper05515562017-10-26 06:46:41 +00003681static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3682 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003683
3684bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3685 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003686 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003687 case Match_InvalidTiedOperand:
3688 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003689 case Match_MissingFeature:
3690 return Error(Loc,
3691 "instruction requires a CPU feature not currently enabled");
3692 case Match_InvalidOperand:
3693 return Error(Loc, "invalid operand for instruction");
3694 case Match_InvalidSuffix:
3695 return Error(Loc, "invalid type suffix for instruction");
3696 case Match_InvalidCondCode:
3697 return Error(Loc, "expected AArch64 condition code");
3698 case Match_AddSubRegExtendSmall:
3699 return Error(Loc,
3700 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3701 case Match_AddSubRegExtendLarge:
3702 return Error(Loc,
3703 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3704 case Match_AddSubSecondSource:
3705 return Error(Loc,
3706 "expected compatible register, symbol or integer in range [0, 4095]");
3707 case Match_LogicalSecondSource:
3708 return Error(Loc, "expected compatible register or logical immediate");
3709 case Match_InvalidMovImm32Shift:
3710 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3711 case Match_InvalidMovImm64Shift:
3712 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3713 case Match_AddSubRegShift32:
3714 return Error(Loc,
3715 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3716 case Match_AddSubRegShift64:
3717 return Error(Loc,
3718 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3719 case Match_InvalidFPImm:
3720 return Error(Loc,
3721 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003722 case Match_InvalidMemoryIndexedSImm6:
3723 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003724 case Match_InvalidMemoryIndexedSImm5:
3725 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003726 case Match_InvalidMemoryIndexed1SImm4:
3727 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003728 case Match_InvalidMemoryIndexed2SImm4:
3729 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003730 case Match_InvalidMemoryIndexed3SImm4:
3731 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003732 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00003733 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00003734 case Match_InvalidMemoryIndexed16SImm4:
3735 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00003736 case Match_InvalidMemoryIndexed1SImm6:
3737 return Error(Loc, "index must be an integer in range [-32, 31].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003738 case Match_InvalidMemoryIndexedSImm9:
3739 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00003740 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00003741 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003742 case Match_InvalidMemoryIndexed4SImm7:
3743 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3744 case Match_InvalidMemoryIndexed8SImm7:
3745 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3746 case Match_InvalidMemoryIndexed16SImm7:
3747 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00003748 case Match_InvalidMemoryIndexed8UImm5:
3749 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
3750 case Match_InvalidMemoryIndexed4UImm5:
3751 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
3752 case Match_InvalidMemoryIndexed2UImm5:
3753 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00003754 case Match_InvalidMemoryIndexed8UImm6:
3755 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
3756 case Match_InvalidMemoryIndexed4UImm6:
3757 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
3758 case Match_InvalidMemoryIndexed2UImm6:
3759 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
3760 case Match_InvalidMemoryIndexed1UImm6:
3761 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003762 case Match_InvalidMemoryWExtend8:
3763 return Error(Loc,
3764 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3765 case Match_InvalidMemoryWExtend16:
3766 return Error(Loc,
3767 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3768 case Match_InvalidMemoryWExtend32:
3769 return Error(Loc,
3770 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3771 case Match_InvalidMemoryWExtend64:
3772 return Error(Loc,
3773 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3774 case Match_InvalidMemoryWExtend128:
3775 return Error(Loc,
3776 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3777 case Match_InvalidMemoryXExtend8:
3778 return Error(Loc,
3779 "expected 'lsl' or 'sxtx' with optional shift of #0");
3780 case Match_InvalidMemoryXExtend16:
3781 return Error(Loc,
3782 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3783 case Match_InvalidMemoryXExtend32:
3784 return Error(Loc,
3785 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3786 case Match_InvalidMemoryXExtend64:
3787 return Error(Loc,
3788 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3789 case Match_InvalidMemoryXExtend128:
3790 return Error(Loc,
3791 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3792 case Match_InvalidMemoryIndexed1:
3793 return Error(Loc, "index must be an integer in range [0, 4095].");
3794 case Match_InvalidMemoryIndexed2:
3795 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3796 case Match_InvalidMemoryIndexed4:
3797 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3798 case Match_InvalidMemoryIndexed8:
3799 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3800 case Match_InvalidMemoryIndexed16:
3801 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003802 case Match_InvalidImm0_1:
3803 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003804 case Match_InvalidImm0_7:
3805 return Error(Loc, "immediate must be an integer in range [0, 7].");
3806 case Match_InvalidImm0_15:
3807 return Error(Loc, "immediate must be an integer in range [0, 15].");
3808 case Match_InvalidImm0_31:
3809 return Error(Loc, "immediate must be an integer in range [0, 31].");
3810 case Match_InvalidImm0_63:
3811 return Error(Loc, "immediate must be an integer in range [0, 63].");
3812 case Match_InvalidImm0_127:
3813 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003814 case Match_InvalidImm0_255:
3815 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003816 case Match_InvalidImm0_65535:
3817 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3818 case Match_InvalidImm1_8:
3819 return Error(Loc, "immediate must be an integer in range [1, 8].");
3820 case Match_InvalidImm1_16:
3821 return Error(Loc, "immediate must be an integer in range [1, 16].");
3822 case Match_InvalidImm1_32:
3823 return Error(Loc, "immediate must be an integer in range [1, 32].");
3824 case Match_InvalidImm1_64:
3825 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00003826 case Match_InvalidSVEAddSubImm8:
3827 return Error(Loc, "immediate must be an integer in range [0, 255]"
3828 " with a shift amount of 0");
3829 case Match_InvalidSVEAddSubImm16:
3830 case Match_InvalidSVEAddSubImm32:
3831 case Match_InvalidSVEAddSubImm64:
3832 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
3833 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00003834 case Match_InvalidSVECpyImm8:
3835 return Error(Loc, "immediate must be an integer in range [-128, 255]"
3836 " with a shift amount of 0");
3837 case Match_InvalidSVECpyImm16:
3838 case Match_InvalidSVECpyImm32:
3839 case Match_InvalidSVECpyImm64:
3840 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
3841 "multiple of 256 in range [-32768, 32512]");
Tim Northover3b0846e2014-05-24 12:50:23 +00003842 case Match_InvalidIndex1:
3843 return Error(Loc, "expected lane specifier '[1]'");
3844 case Match_InvalidIndexB:
3845 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3846 case Match_InvalidIndexH:
3847 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3848 case Match_InvalidIndexS:
3849 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3850 case Match_InvalidIndexD:
3851 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3852 case Match_InvalidLabel:
3853 return Error(Loc, "expected label or encodable integer pc offset");
3854 case Match_MRS:
3855 return Error(Loc, "expected readable system register");
3856 case Match_MSR:
3857 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003858 case Match_InvalidComplexRotationEven:
3859 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3860 case Match_InvalidComplexRotationOdd:
3861 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003862 case Match_MnemonicFail: {
3863 std::string Suggestion = AArch64MnemonicSpellCheck(
3864 ((AArch64Operand &)*Operands[0]).getToken(),
3865 ComputeAvailableFeatures(STI->getFeatureBits()));
3866 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3867 }
Sander de Smalen367694b2018-04-20 08:54:49 +00003868 case Match_InvalidGPR64shifted8:
3869 return Error(Loc, "register must be x0..x30 or xzr, without shift");
3870 case Match_InvalidGPR64shifted16:
3871 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
3872 case Match_InvalidGPR64shifted32:
3873 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
3874 case Match_InvalidGPR64shifted64:
3875 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
3876 case Match_InvalidGPR64NoXZRshifted8:
3877 return Error(Loc, "register must be x0..x30 without shift");
3878 case Match_InvalidGPR64NoXZRshifted16:
3879 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
3880 case Match_InvalidGPR64NoXZRshifted32:
3881 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
3882 case Match_InvalidGPR64NoXZRshifted64:
3883 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00003884 case Match_InvalidZPR32UXTW8:
3885 case Match_InvalidZPR32SXTW8:
3886 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
3887 case Match_InvalidZPR32UXTW16:
3888 case Match_InvalidZPR32SXTW16:
3889 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
3890 case Match_InvalidZPR32UXTW32:
3891 case Match_InvalidZPR32SXTW32:
3892 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
3893 case Match_InvalidZPR32UXTW64:
3894 case Match_InvalidZPR32SXTW64:
3895 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
3896 case Match_InvalidZPR64UXTW8:
3897 case Match_InvalidZPR64SXTW8:
3898 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
3899 case Match_InvalidZPR64UXTW16:
3900 case Match_InvalidZPR64SXTW16:
3901 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
3902 case Match_InvalidZPR64UXTW32:
3903 case Match_InvalidZPR64SXTW32:
3904 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
3905 case Match_InvalidZPR64UXTW64:
3906 case Match_InvalidZPR64SXTW64:
3907 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
3908 case Match_InvalidZPR64LSL8:
3909 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
3910 case Match_InvalidZPR64LSL16:
3911 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
3912 case Match_InvalidZPR64LSL32:
3913 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
3914 case Match_InvalidZPR64LSL64:
3915 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00003916 case Match_InvalidZPR0:
3917 return Error(Loc, "expected register without element width sufix");
3918 case Match_InvalidZPR8:
3919 case Match_InvalidZPR16:
3920 case Match_InvalidZPR32:
3921 case Match_InvalidZPR64:
3922 case Match_InvalidZPR128:
3923 return Error(Loc, "invalid element width");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003924 case Match_InvalidSVEPattern:
3925 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003926 case Match_InvalidSVEPredicateAnyReg:
3927 case Match_InvalidSVEPredicateBReg:
3928 case Match_InvalidSVEPredicateHReg:
3929 case Match_InvalidSVEPredicateSReg:
3930 case Match_InvalidSVEPredicateDReg:
3931 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003932 case Match_InvalidSVEPredicate3bAnyReg:
3933 case Match_InvalidSVEPredicate3bBReg:
3934 case Match_InvalidSVEPredicate3bHReg:
3935 case Match_InvalidSVEPredicate3bSReg:
3936 case Match_InvalidSVEPredicate3bDReg:
3937 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003938 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003939 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003940 }
3941}
3942
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003943static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003944
3945bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3946 OperandVector &Operands,
3947 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003948 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003949 bool MatchingInlineAsm) {
3950 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003951 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3952 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003953
David Blaikie960ea3f2014-06-08 16:18:35 +00003954 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003955 unsigned NumOperands = Operands.size();
3956
3957 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003958 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3959 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003960 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003961 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003962 if (Op3CE) {
3963 uint64_t Op3Val = Op3CE->getValue();
3964 uint64_t NewOp3Val = 0;
3965 uint64_t NewOp4Val = 0;
3966 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003967 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003968 NewOp3Val = (32 - Op3Val) & 0x1f;
3969 NewOp4Val = 31 - Op3Val;
3970 } else {
3971 NewOp3Val = (64 - Op3Val) & 0x3f;
3972 NewOp4Val = 63 - Op3Val;
3973 }
3974
Jim Grosbach13760bd2015-05-30 01:25:56 +00003975 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3976 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003977
3978 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003979 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003980 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003981 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3982 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3983 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003984 }
3985 }
Tim Northover03b99f62015-04-30 18:28:58 +00003986 } else if (NumOperands == 4 && Tok == "bfc") {
3987 // FIXME: Horrible hack to handle BFC->BFM alias.
3988 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3989 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3990 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3991
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003992 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003993 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3994 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3995
3996 if (LSBCE && WidthCE) {
3997 uint64_t LSB = LSBCE->getValue();
3998 uint64_t Width = WidthCE->getValue();
3999
4000 uint64_t RegWidth = 0;
4001 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4002 Op1.getReg()))
4003 RegWidth = 64;
4004 else
4005 RegWidth = 32;
4006
4007 if (LSB >= RegWidth)
4008 return Error(LSBOp.getStartLoc(),
4009 "expected integer in range [0, 31]");
4010 if (Width < 1 || Width > RegWidth)
4011 return Error(WidthOp.getStartLoc(),
4012 "expected integer in range [1, 32]");
4013
4014 uint64_t ImmR = 0;
4015 if (RegWidth == 32)
4016 ImmR = (32 - LSB) & 0x1f;
4017 else
4018 ImmR = (64 - LSB) & 0x3f;
4019
4020 uint64_t ImmS = Width - 1;
4021
4022 if (ImmR != 0 && ImmS >= ImmR)
4023 return Error(WidthOp.getStartLoc(),
4024 "requested insert overflows register");
4025
Jim Grosbach13760bd2015-05-30 01:25:56 +00004026 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4027 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004028 Operands[0] = AArch64Operand::CreateToken(
4029 "bfm", false, Op.getStartLoc(), getContext());
4030 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004031 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4032 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004033 Operands[3] = AArch64Operand::CreateImm(
4034 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4035 Operands.emplace_back(
4036 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4037 WidthOp.getEndLoc(), getContext()));
4038 }
4039 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004040 } else if (NumOperands == 5) {
4041 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4042 // UBFIZ -> UBFM aliases.
4043 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004044 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4045 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4046 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004047
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004048 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004049 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4050 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004051
4052 if (Op3CE && Op4CE) {
4053 uint64_t Op3Val = Op3CE->getValue();
4054 uint64_t Op4Val = Op4CE->getValue();
4055
4056 uint64_t RegWidth = 0;
4057 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004058 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004059 RegWidth = 64;
4060 else
4061 RegWidth = 32;
4062
4063 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004064 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004065 "expected integer in range [0, 31]");
4066 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004067 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004068 "expected integer in range [1, 32]");
4069
4070 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004071 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004072 NewOp3Val = (32 - Op3Val) & 0x1f;
4073 else
4074 NewOp3Val = (64 - Op3Val) & 0x3f;
4075
4076 uint64_t NewOp4Val = Op4Val - 1;
4077
4078 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004079 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004080 "requested insert overflows register");
4081
4082 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004083 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004084 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004085 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004086 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004087 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004088 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004089 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004090 if (Tok == "bfi")
4091 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004092 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004093 else if (Tok == "sbfiz")
4094 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004095 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004096 else if (Tok == "ubfiz")
4097 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004098 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004099 else
4100 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004101 }
4102 }
4103
4104 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4105 // UBFX -> UBFM aliases.
4106 } else if (NumOperands == 5 &&
4107 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004108 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4109 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4110 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004111
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004112 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004113 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4114 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004115
4116 if (Op3CE && Op4CE) {
4117 uint64_t Op3Val = Op3CE->getValue();
4118 uint64_t Op4Val = Op4CE->getValue();
4119
4120 uint64_t RegWidth = 0;
4121 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004122 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004123 RegWidth = 64;
4124 else
4125 RegWidth = 32;
4126
4127 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004128 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004129 "expected integer in range [0, 31]");
4130 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004131 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004132 "expected integer in range [1, 32]");
4133
4134 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4135
4136 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004137 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004138 "requested extract overflows register");
4139
4140 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004141 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004142 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004143 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004144 if (Tok == "bfxil")
4145 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004146 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004147 else if (Tok == "sbfx")
4148 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004149 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004150 else if (Tok == "ubfx")
4151 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004152 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004153 else
4154 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004155 }
4156 }
4157 }
4158 }
Tim Northover9097a072017-12-18 10:36:00 +00004159
4160 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4161 // instruction for FP registers correctly in some rare circumstances. Convert
4162 // it to a safe instruction and warn (because silently changing someone's
4163 // assembly is rude).
4164 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4165 NumOperands == 4 && Tok == "movi") {
4166 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4167 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4168 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4169 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4170 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4171 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4172 if (Suffix.lower() == ".2d" &&
4173 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4174 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4175 " correctly on this CPU, converting to equivalent movi.16b");
4176 // Switch the suffix to .16b.
4177 unsigned Idx = Op1.isToken() ? 1 : 2;
4178 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4179 getContext());
4180 }
4181 }
4182 }
4183
Tim Northover3b0846e2014-05-24 12:50:23 +00004184 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4185 // InstAlias can't quite handle this since the reg classes aren't
4186 // subclasses.
4187 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4188 // The source register can be Wn here, but the matcher expects a
4189 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004190 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004191 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004192 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004193 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4194 Op.getStartLoc(), Op.getEndLoc(),
4195 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004196 }
4197 }
4198 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4199 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004200 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004201 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004202 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004203 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004204 // The source register can be Wn here, but the matcher expects a
4205 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004206 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004207 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004208 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004209 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4210 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004211 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004212 }
4213 }
4214 }
4215 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4216 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004217 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004218 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004219 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004220 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004221 // The source register can be Wn here, but the matcher expects a
4222 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004223 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004224 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004225 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004226 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4227 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004228 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004229 }
4230 }
4231 }
4232
Tim Northover3b0846e2014-05-24 12:50:23 +00004233 MCInst Inst;
4234 // First try to match against the secondary set of tables containing the
4235 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4236 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004237 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004238
4239 // If that fails, try against the alternate table containing long-form NEON:
4240 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004241 if (MatchResult != Match_Success) {
4242 // But first, save the short-form match result: we can use it in case the
4243 // long-form match also fails.
4244 auto ShortFormNEONErrorInfo = ErrorInfo;
4245 auto ShortFormNEONMatchResult = MatchResult;
4246
Tim Northover3b0846e2014-05-24 12:50:23 +00004247 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004248 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004249
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004250 // Now, both matches failed, and the long-form match failed on the mnemonic
4251 // suffix token operand. The short-form match failure is probably more
4252 // relevant: use it instead.
4253 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004254 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004255 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4256 MatchResult = ShortFormNEONMatchResult;
4257 ErrorInfo = ShortFormNEONErrorInfo;
4258 }
4259 }
4260
Tim Northover3b0846e2014-05-24 12:50:23 +00004261 switch (MatchResult) {
4262 case Match_Success: {
4263 // Perform range checking and other semantic validations
4264 SmallVector<SMLoc, 8> OperandLocs;
4265 NumOperands = Operands.size();
4266 for (unsigned i = 1; i < NumOperands; ++i)
4267 OperandLocs.push_back(Operands[i]->getStartLoc());
4268 if (validateInstruction(Inst, OperandLocs))
4269 return true;
4270
4271 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004272 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004273 return false;
4274 }
4275 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004276 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004277 // Special case the error message for the very common case where only
4278 // a single subtarget feature is missing (neon, e.g.).
4279 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004280 uint64_t Mask = 1;
4281 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4282 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004283 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004284 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004285 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004286 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004287 }
4288 return Error(IDLoc, Msg);
4289 }
4290 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004291 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004292 case Match_InvalidOperand: {
4293 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004294
Tim Northover26bb14e2014-08-18 11:49:42 +00004295 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004296 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004297 return Error(IDLoc, "too few operands for instruction",
4298 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004299
David Blaikie960ea3f2014-06-08 16:18:35 +00004300 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004301 if (ErrorLoc == SMLoc())
4302 ErrorLoc = IDLoc;
4303 }
4304 // If the match failed on a suffix token operand, tweak the diagnostic
4305 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004306 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4307 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004308 MatchResult = Match_InvalidSuffix;
4309
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004310 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004311 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004312 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004313 case Match_InvalidMemoryIndexed1:
4314 case Match_InvalidMemoryIndexed2:
4315 case Match_InvalidMemoryIndexed4:
4316 case Match_InvalidMemoryIndexed8:
4317 case Match_InvalidMemoryIndexed16:
4318 case Match_InvalidCondCode:
4319 case Match_AddSubRegExtendSmall:
4320 case Match_AddSubRegExtendLarge:
4321 case Match_AddSubSecondSource:
4322 case Match_LogicalSecondSource:
4323 case Match_AddSubRegShift32:
4324 case Match_AddSubRegShift64:
4325 case Match_InvalidMovImm32Shift:
4326 case Match_InvalidMovImm64Shift:
4327 case Match_InvalidFPImm:
4328 case Match_InvalidMemoryWExtend8:
4329 case Match_InvalidMemoryWExtend16:
4330 case Match_InvalidMemoryWExtend32:
4331 case Match_InvalidMemoryWExtend64:
4332 case Match_InvalidMemoryWExtend128:
4333 case Match_InvalidMemoryXExtend8:
4334 case Match_InvalidMemoryXExtend16:
4335 case Match_InvalidMemoryXExtend32:
4336 case Match_InvalidMemoryXExtend64:
4337 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004338 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004339 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004340 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004341 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004342 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004343 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004344 case Match_InvalidMemoryIndexed4SImm7:
4345 case Match_InvalidMemoryIndexed8SImm7:
4346 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004347 case Match_InvalidMemoryIndexed8UImm5:
4348 case Match_InvalidMemoryIndexed4UImm5:
4349 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004350 case Match_InvalidMemoryIndexed1UImm6:
4351 case Match_InvalidMemoryIndexed2UImm6:
4352 case Match_InvalidMemoryIndexed4UImm6:
4353 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004354 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004355 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004356 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004357 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004358 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004359 case Match_InvalidImm0_7:
4360 case Match_InvalidImm0_15:
4361 case Match_InvalidImm0_31:
4362 case Match_InvalidImm0_63:
4363 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004364 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004365 case Match_InvalidImm0_65535:
4366 case Match_InvalidImm1_8:
4367 case Match_InvalidImm1_16:
4368 case Match_InvalidImm1_32:
4369 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004370 case Match_InvalidSVEAddSubImm8:
4371 case Match_InvalidSVEAddSubImm16:
4372 case Match_InvalidSVEAddSubImm32:
4373 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004374 case Match_InvalidSVECpyImm8:
4375 case Match_InvalidSVECpyImm16:
4376 case Match_InvalidSVECpyImm32:
4377 case Match_InvalidSVECpyImm64:
Tim Northover3b0846e2014-05-24 12:50:23 +00004378 case Match_InvalidIndex1:
4379 case Match_InvalidIndexB:
4380 case Match_InvalidIndexH:
4381 case Match_InvalidIndexS:
4382 case Match_InvalidIndexD:
4383 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004384 case Match_InvalidComplexRotationEven:
4385 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004386 case Match_InvalidGPR64shifted8:
4387 case Match_InvalidGPR64shifted16:
4388 case Match_InvalidGPR64shifted32:
4389 case Match_InvalidGPR64shifted64:
4390 case Match_InvalidGPR64NoXZRshifted8:
4391 case Match_InvalidGPR64NoXZRshifted16:
4392 case Match_InvalidGPR64NoXZRshifted32:
4393 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004394 case Match_InvalidZPR32UXTW8:
4395 case Match_InvalidZPR32UXTW16:
4396 case Match_InvalidZPR32UXTW32:
4397 case Match_InvalidZPR32UXTW64:
4398 case Match_InvalidZPR32SXTW8:
4399 case Match_InvalidZPR32SXTW16:
4400 case Match_InvalidZPR32SXTW32:
4401 case Match_InvalidZPR32SXTW64:
4402 case Match_InvalidZPR64UXTW8:
4403 case Match_InvalidZPR64SXTW8:
4404 case Match_InvalidZPR64UXTW16:
4405 case Match_InvalidZPR64SXTW16:
4406 case Match_InvalidZPR64UXTW32:
4407 case Match_InvalidZPR64SXTW32:
4408 case Match_InvalidZPR64UXTW64:
4409 case Match_InvalidZPR64SXTW64:
4410 case Match_InvalidZPR64LSL8:
4411 case Match_InvalidZPR64LSL16:
4412 case Match_InvalidZPR64LSL32:
4413 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004414 case Match_InvalidZPR0:
4415 case Match_InvalidZPR8:
4416 case Match_InvalidZPR16:
4417 case Match_InvalidZPR32:
4418 case Match_InvalidZPR64:
4419 case Match_InvalidZPR128:
Sander de Smalencd6be962017-12-20 11:02:42 +00004420 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004421 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004422 case Match_InvalidSVEPredicateBReg:
4423 case Match_InvalidSVEPredicateHReg:
4424 case Match_InvalidSVEPredicateSReg:
4425 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004426 case Match_InvalidSVEPredicate3bAnyReg:
4427 case Match_InvalidSVEPredicate3bBReg:
4428 case Match_InvalidSVEPredicate3bHReg:
4429 case Match_InvalidSVEPredicate3bSReg:
4430 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004431 case Match_MSR:
4432 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004433 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004434 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004435 // Any time we get here, there's nothing fancy to do. Just get the
4436 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004437 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004438 if (ErrorLoc == SMLoc())
4439 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004440 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004441 }
4442 }
4443
4444 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004445}
4446
4447/// ParseDirective parses the arm specific directives
4448bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004449 const MCObjectFileInfo::Environment Format =
4450 getContext().getObjectFileInfo()->getObjectFileType();
4451 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4452 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004453
Tim Northover3b0846e2014-05-24 12:50:23 +00004454 StringRef IDVal = DirectiveID.getIdentifier();
4455 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004456 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004457 parseDirectiveArch(Loc);
4458 else if (IDVal == ".cpu")
4459 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00004460 else if (IDVal == ".tlsdesccall")
4461 parseDirectiveTLSDescCall(Loc);
4462 else if (IDVal == ".ltorg" || IDVal == ".pool")
4463 parseDirectiveLtorg(Loc);
4464 else if (IDVal == ".unreq")
4465 parseDirectiveUnreq(Loc);
4466 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004467 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004468 parseDirectiveInst(Loc);
4469 else
4470 return true;
4471 } else if (IDVal == MCLOHDirectiveName())
4472 parseDirectiveLOH(IDVal, Loc);
4473 else
4474 return true;
4475 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004476}
4477
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004478static const struct {
4479 const char *Name;
4480 const FeatureBitset Features;
4481} ExtensionMap[] = {
4482 { "crc", {AArch64::FeatureCRC} },
4483 { "crypto", {AArch64::FeatureCrypto} },
4484 { "fp", {AArch64::FeatureFPARMv8} },
4485 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004486 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004487 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004488
4489 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004490 { "pan", {} },
4491 { "lor", {} },
4492 { "rdma", {} },
4493 { "profile", {} },
4494};
4495
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004496/// parseDirectiveArch
4497/// ::= .arch token
4498bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4499 SMLoc ArchLoc = getLoc();
4500
4501 StringRef Arch, ExtensionString;
4502 std::tie(Arch, ExtensionString) =
4503 getParser().parseStringToEndOfStatement().trim().split('+');
4504
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004505 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4506 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004507 return Error(ArchLoc, "unknown arch name");
4508
4509 if (parseToken(AsmToken::EndOfStatement))
4510 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004511
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004512 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004513 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004514 AArch64::getArchFeatures(ID, AArch64Features);
4515 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4516 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004517
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004518 MCSubtargetInfo &STI = copySTI();
4519 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4520 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4521
4522 SmallVector<StringRef, 4> RequestedExtensions;
4523 if (!ExtensionString.empty())
4524 ExtensionString.split(RequestedExtensions, '+');
4525
4526 FeatureBitset Features = STI.getFeatureBits();
4527 for (auto Name : RequestedExtensions) {
4528 bool EnableFeature = true;
4529
4530 if (Name.startswith_lower("no")) {
4531 EnableFeature = false;
4532 Name = Name.substr(2);
4533 }
4534
4535 for (const auto &Extension : ExtensionMap) {
4536 if (Extension.Name != Name)
4537 continue;
4538
4539 if (Extension.Features.none())
4540 report_fatal_error("unsupported architectural extension: " + Name);
4541
4542 FeatureBitset ToggleFeatures = EnableFeature
4543 ? (~Features & Extension.Features)
4544 : ( Features & Extension.Features);
4545 uint64_t Features =
4546 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4547 setAvailableFeatures(Features);
4548 break;
4549 }
4550 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004551 return false;
4552}
4553
Tim Northover8b96c7e2017-05-15 19:42:15 +00004554static SMLoc incrementLoc(SMLoc L, int Offset) {
4555 return SMLoc::getFromPointer(L.getPointer() + Offset);
4556}
4557
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004558/// parseDirectiveCPU
4559/// ::= .cpu id
4560bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004561 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004562
4563 StringRef CPU, ExtensionString;
4564 std::tie(CPU, ExtensionString) =
4565 getParser().parseStringToEndOfStatement().trim().split('+');
4566
Nirav Davee833c6c2016-11-08 18:31:04 +00004567 if (parseToken(AsmToken::EndOfStatement))
4568 return true;
4569
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004570 SmallVector<StringRef, 4> RequestedExtensions;
4571 if (!ExtensionString.empty())
4572 ExtensionString.split(RequestedExtensions, '+');
4573
4574 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4575 // once that is tablegen'ed
4576 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004577 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004578 return false;
4579 }
4580
4581 MCSubtargetInfo &STI = copySTI();
4582 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004583 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004584
4585 FeatureBitset Features = STI.getFeatureBits();
4586 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004587 // Advance source location past '+'.
4588 CurLoc = incrementLoc(CurLoc, 1);
4589
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004590 bool EnableFeature = true;
4591
4592 if (Name.startswith_lower("no")) {
4593 EnableFeature = false;
4594 Name = Name.substr(2);
4595 }
4596
Tim Northover8b96c7e2017-05-15 19:42:15 +00004597 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004598 for (const auto &Extension : ExtensionMap) {
4599 if (Extension.Name != Name)
4600 continue;
4601
4602 if (Extension.Features.none())
4603 report_fatal_error("unsupported architectural extension: " + Name);
4604
4605 FeatureBitset ToggleFeatures = EnableFeature
4606 ? (~Features & Extension.Features)
4607 : ( Features & Extension.Features);
4608 uint64_t Features =
4609 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4610 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004611 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004612
4613 break;
4614 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004615
4616 if (!FoundExtension)
4617 Error(CurLoc, "unsupported architectural extension");
4618
4619 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004620 }
4621 return false;
4622}
4623
Chad Rosierdcd2a302014-10-22 20:35:57 +00004624/// parseDirectiveInst
4625/// ::= .inst opcode [, ...]
4626bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004627 if (getLexer().is(AsmToken::EndOfStatement))
4628 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004629
Nirav Davee833c6c2016-11-08 18:31:04 +00004630 auto parseOp = [&]() -> bool {
4631 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004632 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004633 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4634 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004635 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004636 if (check(!Value, L, "expected constant expression"))
4637 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004638 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004639 return false;
4640 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004641
Nirav Davee833c6c2016-11-08 18:31:04 +00004642 if (parseMany(parseOp))
4643 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004644 return false;
4645}
4646
Tim Northover3b0846e2014-05-24 12:50:23 +00004647// parseDirectiveTLSDescCall:
4648// ::= .tlsdesccall symbol
4649bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4650 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004651 if (check(getParser().parseIdentifier(Name), L,
4652 "expected symbol after directive") ||
4653 parseToken(AsmToken::EndOfStatement))
4654 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004655
Jim Grosbach6f482002015-05-18 18:43:14 +00004656 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004657 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4658 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004659
4660 MCInst Inst;
4661 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004662 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004663
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004664 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004665 return false;
4666}
4667
4668/// ::= .loh <lohName | lohId> label1, ..., labelN
4669/// The number of arguments depends on the loh identifier.
4670bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004671 MCLOHType Kind;
4672 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4673 if (getParser().getTok().isNot(AsmToken::Integer))
4674 return TokError("expected an identifier or a number in directive");
4675 // We successfully get a numeric value for the identifier.
4676 // Check if it is valid.
4677 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004678 if (Id <= -1U && !isValidMCLOHType(Id))
4679 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004680 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004681 } else {
4682 StringRef Name = getTok().getIdentifier();
4683 // We successfully parse an identifier.
4684 // Check if it is a recognized one.
4685 int Id = MCLOHNameToId(Name);
4686
4687 if (Id == -1)
4688 return TokError("invalid identifier in directive");
4689 Kind = (MCLOHType)Id;
4690 }
4691 // Consume the identifier.
4692 Lex();
4693 // Get the number of arguments of this LOH.
4694 int NbArgs = MCLOHIdToNbArgs(Kind);
4695
4696 assert(NbArgs != -1 && "Invalid number of arguments");
4697
4698 SmallVector<MCSymbol *, 3> Args;
4699 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4700 StringRef Name;
4701 if (getParser().parseIdentifier(Name))
4702 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004703 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004704
4705 if (Idx + 1 == NbArgs)
4706 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004707 if (parseToken(AsmToken::Comma,
4708 "unexpected token in '" + Twine(IDVal) + "' directive"))
4709 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004710 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004711 if (parseToken(AsmToken::EndOfStatement,
4712 "unexpected token in '" + Twine(IDVal) + "' directive"))
4713 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004714
4715 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4716 return false;
4717}
4718
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004719/// parseDirectiveLtorg
4720/// ::= .ltorg | .pool
4721bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004722 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4723 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004724 getTargetStreamer().emitCurrentConstantPool();
4725 return false;
4726}
4727
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004728/// parseDirectiveReq
4729/// ::= name .req registername
4730bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004731 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004732 Parser.Lex(); // Eat the '.req' token.
4733 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004734 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004735 unsigned RegNum;
4736 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004737
Sander de Smalen50d87022018-04-19 07:35:08 +00004738 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004739 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004740 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004741 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004742
Sander de Smalen50d87022018-04-19 07:35:08 +00004743 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004744 return true;
4745
Sander de Smalen50d87022018-04-19 07:35:08 +00004746 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004747 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004748 }
4749
Sander de Smalen50d87022018-04-19 07:35:08 +00004750 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004751 StringRef Kind;
4752 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004753 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004754 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004755
Sander de Smalen50d87022018-04-19 07:35:08 +00004756 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004757 return true;
4758
Sander de Smalen50d87022018-04-19 07:35:08 +00004759 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004760 return Error(SRegLoc,
4761 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004762 }
4763
Sander de Smalen50d87022018-04-19 07:35:08 +00004764 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00004765 StringRef Kind;
4766 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004767 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004768
Sander de Smalen50d87022018-04-19 07:35:08 +00004769 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00004770 return true;
4771
Sander de Smalen50d87022018-04-19 07:35:08 +00004772 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00004773 return Error(SRegLoc,
4774 "sve predicate register without type specifier expected");
4775 }
4776
Sander de Smalen50d87022018-04-19 07:35:08 +00004777 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00004778 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004779
4780 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004781 if (parseToken(AsmToken::EndOfStatement,
4782 "unexpected input in .req directive"))
4783 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004784
Sander de Smalen8e607342017-11-15 15:44:43 +00004785 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004786 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004787 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4788
Nirav Dave2364748a2016-09-16 18:30:20 +00004789 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004790}
4791
4792/// parseDirectiveUneq
4793/// ::= .unreq registername
4794bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004795 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004796 if (getTok().isNot(AsmToken::Identifier))
4797 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004798 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4799 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004800 if (parseToken(AsmToken::EndOfStatement))
4801 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004802 return false;
4803}
4804
Tim Northover3b0846e2014-05-24 12:50:23 +00004805bool
4806AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4807 AArch64MCExpr::VariantKind &ELFRefKind,
4808 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4809 int64_t &Addend) {
4810 ELFRefKind = AArch64MCExpr::VK_INVALID;
4811 DarwinRefKind = MCSymbolRefExpr::VK_None;
4812 Addend = 0;
4813
4814 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4815 ELFRefKind = AE->getKind();
4816 Expr = AE->getSubExpr();
4817 }
4818
4819 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4820 if (SE) {
4821 // It's a simple symbol reference with no addend.
4822 DarwinRefKind = SE->getKind();
4823 return true;
4824 }
4825
4826 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4827 if (!BE)
4828 return false;
4829
4830 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4831 if (!SE)
4832 return false;
4833 DarwinRefKind = SE->getKind();
4834
4835 if (BE->getOpcode() != MCBinaryExpr::Add &&
4836 BE->getOpcode() != MCBinaryExpr::Sub)
4837 return false;
4838
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004839 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004840 // on here than we can deal with.
4841 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4842 if (!AddendExpr)
4843 return false;
4844
4845 Addend = AddendExpr->getValue();
4846 if (BE->getOpcode() == MCBinaryExpr::Sub)
4847 Addend = -Addend;
4848
4849 // It's some symbol reference + a constant addend, but really
4850 // shouldn't use both Darwin and ELF syntax.
4851 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4852 DarwinRefKind == MCSymbolRefExpr::VK_None;
4853}
4854
4855/// Force static initialization.
4856extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004857 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4858 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4859 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004860}
4861
4862#define GET_REGISTER_MATCHER
4863#define GET_SUBTARGET_FEATURE_NAME
4864#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004865#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004866#include "AArch64GenAsmMatcher.inc"
4867
4868// Define this matcher function after the auto-generated include so we
4869// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004870unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004871 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004872 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004873 // If the kind is a token for a literal immediate, check if our asm
4874 // operand matches. This is for InstAliases which have a fixed-value
4875 // immediate in the syntax.
4876 int64_t ExpectedVal;
4877 switch (Kind) {
4878 default:
4879 return Match_InvalidOperand;
4880 case MCK__35_0:
4881 ExpectedVal = 0;
4882 break;
4883 case MCK__35_1:
4884 ExpectedVal = 1;
4885 break;
4886 case MCK__35_12:
4887 ExpectedVal = 12;
4888 break;
4889 case MCK__35_16:
4890 ExpectedVal = 16;
4891 break;
4892 case MCK__35_2:
4893 ExpectedVal = 2;
4894 break;
4895 case MCK__35_24:
4896 ExpectedVal = 24;
4897 break;
4898 case MCK__35_3:
4899 ExpectedVal = 3;
4900 break;
4901 case MCK__35_32:
4902 ExpectedVal = 32;
4903 break;
4904 case MCK__35_4:
4905 ExpectedVal = 4;
4906 break;
4907 case MCK__35_48:
4908 ExpectedVal = 48;
4909 break;
4910 case MCK__35_6:
4911 ExpectedVal = 6;
4912 break;
4913 case MCK__35_64:
4914 ExpectedVal = 64;
4915 break;
4916 case MCK__35_8:
4917 ExpectedVal = 8;
4918 break;
4919 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004920 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004921 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004922 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004923 if (!CE)
4924 return Match_InvalidOperand;
4925 if (CE->getValue() == ExpectedVal)
4926 return Match_Success;
4927 return Match_InvalidOperand;
4928}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004929
Alex Bradbury58eba092016-11-01 16:32:05 +00004930OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004931AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4932
4933 SMLoc S = getLoc();
4934
4935 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4936 Error(S, "expected register");
4937 return MatchOperand_ParseFail;
4938 }
4939
Sander de Smalen50d87022018-04-19 07:35:08 +00004940 unsigned FirstReg;
4941 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
4942 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004943 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00004944
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004945 const MCRegisterClass &WRegClass =
4946 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4947 const MCRegisterClass &XRegClass =
4948 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4949
4950 bool isXReg = XRegClass.contains(FirstReg),
4951 isWReg = WRegClass.contains(FirstReg);
4952 if (!isXReg && !isWReg) {
4953 Error(S, "expected first even register of a "
4954 "consecutive same-size even/odd register pair");
4955 return MatchOperand_ParseFail;
4956 }
4957
4958 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4959 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4960
4961 if (FirstEncoding & 0x1) {
4962 Error(S, "expected first even register of a "
4963 "consecutive same-size even/odd register pair");
4964 return MatchOperand_ParseFail;
4965 }
4966
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004967 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00004968 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004969 return MatchOperand_ParseFail;
4970 }
4971 // Eat the comma
4972 getParser().Lex();
4973
4974 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00004975 unsigned SecondReg;
4976 Res = tryParseScalarRegister(SecondReg);
4977 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004978 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004979
Eugene Zelenko049b0172017-01-06 00:30:53 +00004980 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004981 (isXReg && !XRegClass.contains(SecondReg)) ||
4982 (isWReg && !WRegClass.contains(SecondReg))) {
4983 Error(E,"expected second odd register of a "
4984 "consecutive same-size even/odd register pair");
4985 return MatchOperand_ParseFail;
4986 }
Joel Jones504bf332016-10-24 13:37:13 +00004987
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004988 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004989 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004990 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4991 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4992 } else {
4993 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4994 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4995 }
4996
Florian Hahnc4422242017-11-07 13:07:50 +00004997 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4998 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004999
5000 return MatchOperand_Success;
5001}
Florian Hahn91f11e52017-11-07 16:45:48 +00005002
Sander de Smaleneb896b12018-04-25 09:26:47 +00005003template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005004OperandMatchResultTy
5005AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005006 const SMLoc S = getLoc();
5007 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005008 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005009 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005010
Sander de Smalen8e607342017-11-15 15:44:43 +00005011 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005012 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005013
5014 if (Res != MatchOperand_Success)
5015 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005016
5017 if (ParseSuffix && Kind.empty())
5018 return MatchOperand_NoMatch;
5019
Sander de Smalen73937b72018-04-11 07:36:10 +00005020 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5021 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005022 return MatchOperand_NoMatch;
5023
Sander de Smalen73937b72018-04-11 07:36:10 +00005024 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005025
5026 // No shift/extend is the default.
5027 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5028 Operands.push_back(AArch64Operand::CreateVectorReg(
5029 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5030
5031 return MatchOperand_Success;
5032 }
5033
5034 // Eat the comma
5035 getParser().Lex();
5036
5037 // Match the shift
5038 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5039 Res = tryParseOptionalShiftExtend(ExtOpnd);
5040 if (Res != MatchOperand_Success)
5041 return Res;
5042
5043 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005044 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005045 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5046 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5047 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005048
5049 return MatchOperand_Success;
5050}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005051
5052OperandMatchResultTy
5053AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5054 MCAsmParser &Parser = getParser();
5055
5056 SMLoc SS = getLoc();
5057 const AsmToken &TokE = Parser.getTok();
5058 bool IsHash = TokE.is(AsmToken::Hash);
5059
5060 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5061 return MatchOperand_NoMatch;
5062
5063 int64_t Pattern;
5064 if (IsHash) {
5065 Parser.Lex(); // Eat hash
5066
5067 // Parse the immediate operand.
5068 const MCExpr *ImmVal;
5069 SS = getLoc();
5070 if (Parser.parseExpression(ImmVal))
5071 return MatchOperand_ParseFail;
5072
5073 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5074 if (!MCE)
5075 return MatchOperand_ParseFail;
5076
5077 Pattern = MCE->getValue();
5078 } else {
5079 // Parse the pattern
5080 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5081 if (!Pat)
5082 return MatchOperand_NoMatch;
5083
5084 Parser.Lex();
5085 Pattern = Pat->Encoding;
5086 assert(Pattern >= 0 && Pattern < 32);
5087 }
5088
5089 Operands.push_back(
5090 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5091 SS, getLoc(), getContext()));
5092
5093 return MatchOperand_Success;
5094}