blob: ae9a351d2e2355f3e22a5712ebb2c5ac2e24e5ad [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);
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000135 template<bool AddFPZeroAsLiteral>
Tim Northover3b0846e2014-05-24 12:50:23 +0000136 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
Sander de Smalen62770792018-05-25 09:47:52 +0000137 OperandMatchResultTy tryParseImmWithOptionalShift(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000138 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000139 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000140 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000141 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Sander de Smalen149916d2018-04-20 07:24:20 +0000142 template <bool ParseShiftExtend>
143 OperandMatchResultTy tryParseGPROperand(OperandVector &Operands);
Sander de Smaleneb896b12018-04-25 09:26:47 +0000144 template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +0000145 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000146 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000147 template <RegKind VectorKind>
148 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
149 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000150 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000151
152public:
153 enum AArch64MatchResultTy {
154 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
155#define GET_OPERAND_DIAGNOSTIC_TYPES
156#include "AArch64GenAsmMatcher.inc"
157 };
Joel Jones504bf332016-10-24 13:37:13 +0000158 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000159
Akira Hatanakab11ef082015-11-14 06:35:56 +0000160 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000161 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000162 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000163 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000164 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000165 MCStreamer &S = getParser().getStreamer();
166 if (S.getTargetStreamer() == nullptr)
167 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000168
Alex Bradbury0a59f182018-05-23 11:17:20 +0000169 // Alias .hword/.word/xword to the target-independent .2byte/.4byte/.8byte
170 // directives as they have the same form and semantics:
171 /// ::= (.hword | .word | .xword ) [ expression (, expression)* ]
172 Parser.addAliasForDirective(".hword", ".2byte");
173 Parser.addAliasForDirective(".word", ".4byte");
174 Parser.addAliasForDirective(".xword", ".8byte");
175
Tim Northover3b0846e2014-05-24 12:50:23 +0000176 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000177 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000178 }
179
180 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
181 SMLoc NameLoc, OperandVector &Operands) override;
182 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
183 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000184 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000185 unsigned Kind) override;
186
187 static bool classifySymbolRef(const MCExpr *Expr,
188 AArch64MCExpr::VariantKind &ELFRefKind,
189 MCSymbolRefExpr::VariantKind &DarwinRefKind,
190 int64_t &Addend);
191};
Tim Northover3b0846e2014-05-24 12:50:23 +0000192
193/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
194/// instruction.
195class AArch64Operand : public MCParsedAsmOperand {
196private:
197 enum KindTy {
198 k_Immediate,
199 k_ShiftedImm,
200 k_CondCode,
201 k_Register,
202 k_VectorList,
203 k_VectorIndex,
204 k_Token,
205 k_SysReg,
206 k_SysCR,
207 k_Prefetch,
208 k_ShiftExtend,
209 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000210 k_Barrier,
211 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000212 } Kind;
213
214 SMLoc StartLoc, EndLoc;
215
216 struct TokOp {
217 const char *Data;
218 unsigned Length;
219 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
220 };
221
Sander de Smalen149916d2018-04-20 07:24:20 +0000222 // Separate shift/extend operand.
223 struct ShiftExtendOp {
224 AArch64_AM::ShiftExtendType Type;
225 unsigned Amount;
226 bool HasExplicitAmount;
227 };
228
Tim Northover3b0846e2014-05-24 12:50:23 +0000229 struct RegOp {
230 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000231 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000232 int ElementWidth;
Sander de Smalen149916d2018-04-20 07:24:20 +0000233
234 // In some cases the shift/extend needs to be explicitly parsed together
235 // with the register, rather than as a separate operand. This is needed
236 // for addressing modes where the instruction as a whole dictates the
237 // scaling/extend, rather than specific bits in the instruction.
238 // By parsing them as a single operand, we avoid the need to pass an
239 // extra operand in all CodeGen patterns (because all operands need to
240 // have an associated value), and we avoid the need to update TableGen to
241 // accept operands that have no associated bits in the instruction.
242 //
243 // An added benefit of parsing them together is that the assembler
244 // can give a sensible diagnostic if the scaling is not correct.
245 //
246 // The default is 'lsl #0' (HasExplicitAmount = false) if no
247 // ShiftExtend is specified.
248 ShiftExtendOp ShiftExtend;
Tim Northover3b0846e2014-05-24 12:50:23 +0000249 };
250
251 struct VectorListOp {
252 unsigned RegNum;
253 unsigned Count;
254 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000255 unsigned ElementWidth;
256 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000257 };
258
259 struct VectorIndexOp {
260 unsigned Val;
261 };
262
263 struct ImmOp {
264 const MCExpr *Val;
265 };
266
267 struct ShiftedImmOp {
268 const MCExpr *Val;
269 unsigned ShiftAmount;
270 };
271
272 struct CondCodeOp {
273 AArch64CC::CondCode Code;
274 };
275
276 struct FPImmOp {
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000277 uint64_t Val; // APFloat value bitcasted to uint64_t.
278 bool IsExact; // describes whether parsed value was exact.
Tim Northover3b0846e2014-05-24 12:50:23 +0000279 };
280
281 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000282 const char *Data;
283 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000284 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000285 };
286
287 struct SysRegOp {
288 const char *Data;
289 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000290 uint32_t MRSReg;
291 uint32_t MSRReg;
292 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000293 };
294
295 struct SysCRImmOp {
296 unsigned Val;
297 };
298
299 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000300 const char *Data;
301 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000302 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000303 };
304
Oliver Stannarda34e4702015-12-01 10:48:51 +0000305 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000306 const char *Data;
307 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000308 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000309 };
310
Tim Northover3b0846e2014-05-24 12:50:23 +0000311 struct ExtendOp {
312 unsigned Val;
313 };
314
315 union {
316 struct TokOp Tok;
317 struct RegOp Reg;
318 struct VectorListOp VectorList;
319 struct VectorIndexOp VectorIndex;
320 struct ImmOp Imm;
321 struct ShiftedImmOp ShiftedImm;
322 struct CondCodeOp CondCode;
323 struct FPImmOp FPImm;
324 struct BarrierOp Barrier;
325 struct SysRegOp SysReg;
326 struct SysCRImmOp SysCRImm;
327 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000328 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000329 struct ShiftExtendOp ShiftExtend;
330 };
331
332 // Keep the MCContext around as the MCExprs may need manipulated during
333 // the add<>Operands() calls.
334 MCContext &Ctx;
335
David Blaikie960ea3f2014-06-08 16:18:35 +0000336public:
David Blaikie9f380a32015-03-16 18:06:57 +0000337 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000338
Tim Northover3b0846e2014-05-24 12:50:23 +0000339 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
340 Kind = o.Kind;
341 StartLoc = o.StartLoc;
342 EndLoc = o.EndLoc;
343 switch (Kind) {
344 case k_Token:
345 Tok = o.Tok;
346 break;
347 case k_Immediate:
348 Imm = o.Imm;
349 break;
350 case k_ShiftedImm:
351 ShiftedImm = o.ShiftedImm;
352 break;
353 case k_CondCode:
354 CondCode = o.CondCode;
355 break;
356 case k_FPImm:
357 FPImm = o.FPImm;
358 break;
359 case k_Barrier:
360 Barrier = o.Barrier;
361 break;
362 case k_Register:
363 Reg = o.Reg;
364 break;
365 case k_VectorList:
366 VectorList = o.VectorList;
367 break;
368 case k_VectorIndex:
369 VectorIndex = o.VectorIndex;
370 break;
371 case k_SysReg:
372 SysReg = o.SysReg;
373 break;
374 case k_SysCR:
375 SysCRImm = o.SysCRImm;
376 break;
377 case k_Prefetch:
378 Prefetch = o.Prefetch;
379 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000380 case k_PSBHint:
381 PSBHint = o.PSBHint;
382 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000383 case k_ShiftExtend:
384 ShiftExtend = o.ShiftExtend;
385 break;
386 }
387 }
388
389 /// getStartLoc - Get the location of the first token of this operand.
390 SMLoc getStartLoc() const override { return StartLoc; }
391 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000392 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000393
394 StringRef getToken() const {
395 assert(Kind == k_Token && "Invalid access!");
396 return StringRef(Tok.Data, Tok.Length);
397 }
398
399 bool isTokenSuffix() const {
400 assert(Kind == k_Token && "Invalid access!");
401 return Tok.IsSuffix;
402 }
403
404 const MCExpr *getImm() const {
405 assert(Kind == k_Immediate && "Invalid access!");
406 return Imm.Val;
407 }
408
409 const MCExpr *getShiftedImmVal() const {
410 assert(Kind == k_ShiftedImm && "Invalid access!");
411 return ShiftedImm.Val;
412 }
413
414 unsigned getShiftedImmShift() const {
415 assert(Kind == k_ShiftedImm && "Invalid access!");
416 return ShiftedImm.ShiftAmount;
417 }
418
419 AArch64CC::CondCode getCondCode() const {
420 assert(Kind == k_CondCode && "Invalid access!");
421 return CondCode.Code;
422 }
423
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000424 APFloat getFPImm() const {
425 assert (Kind == k_FPImm && "Invalid access!");
426 return APFloat(APFloat::IEEEdouble(), APInt(64, FPImm.Val, true));
427 }
428
429 bool getFPImmIsExact() const {
430 assert (Kind == k_FPImm && "Invalid access!");
431 return FPImm.IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +0000432 }
433
434 unsigned getBarrier() const {
435 assert(Kind == k_Barrier && "Invalid access!");
436 return Barrier.Val;
437 }
438
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000439 StringRef getBarrierName() const {
440 assert(Kind == k_Barrier && "Invalid access!");
441 return StringRef(Barrier.Data, Barrier.Length);
442 }
443
Tim Northover3b0846e2014-05-24 12:50:23 +0000444 unsigned getReg() const override {
445 assert(Kind == k_Register && "Invalid access!");
446 return Reg.RegNum;
447 }
448
449 unsigned getVectorListStart() const {
450 assert(Kind == k_VectorList && "Invalid access!");
451 return VectorList.RegNum;
452 }
453
454 unsigned getVectorListCount() const {
455 assert(Kind == k_VectorList && "Invalid access!");
456 return VectorList.Count;
457 }
458
459 unsigned getVectorIndex() const {
460 assert(Kind == k_VectorIndex && "Invalid access!");
461 return VectorIndex.Val;
462 }
463
464 StringRef getSysReg() const {
465 assert(Kind == k_SysReg && "Invalid access!");
466 return StringRef(SysReg.Data, SysReg.Length);
467 }
468
Tim Northover3b0846e2014-05-24 12:50:23 +0000469 unsigned getSysCR() const {
470 assert(Kind == k_SysCR && "Invalid access!");
471 return SysCRImm.Val;
472 }
473
474 unsigned getPrefetch() const {
475 assert(Kind == k_Prefetch && "Invalid access!");
476 return Prefetch.Val;
477 }
478
Oliver Stannarda34e4702015-12-01 10:48:51 +0000479 unsigned getPSBHint() const {
480 assert(Kind == k_PSBHint && "Invalid access!");
481 return PSBHint.Val;
482 }
483
484 StringRef getPSBHintName() const {
485 assert(Kind == k_PSBHint && "Invalid access!");
486 return StringRef(PSBHint.Data, PSBHint.Length);
487 }
488
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000489 StringRef getPrefetchName() const {
490 assert(Kind == k_Prefetch && "Invalid access!");
491 return StringRef(Prefetch.Data, Prefetch.Length);
492 }
493
Tim Northover3b0846e2014-05-24 12:50:23 +0000494 AArch64_AM::ShiftExtendType getShiftExtendType() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000495 if (Kind == k_ShiftExtend)
496 return ShiftExtend.Type;
497 if (Kind == k_Register)
498 return Reg.ShiftExtend.Type;
499 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000500 }
501
502 unsigned getShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000503 if (Kind == k_ShiftExtend)
504 return ShiftExtend.Amount;
505 if (Kind == k_Register)
506 return Reg.ShiftExtend.Amount;
507 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000508 }
509
510 bool hasShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000511 if (Kind == k_ShiftExtend)
512 return ShiftExtend.HasExplicitAmount;
513 if (Kind == k_Register)
514 return Reg.ShiftExtend.HasExplicitAmount;
515 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000516 }
517
518 bool isImm() const override { return Kind == k_Immediate; }
519 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000520
521 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
522
Sander de Smalen50ded902018-04-29 17:33:38 +0000523 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
524 return isImmScaled<Bits, Scale>(true);
525 }
526
527 template <int Bits, int Scale> DiagnosticPredicate isUImmScaled() const {
528 return isImmScaled<Bits, Scale>(false);
529 }
530
Sander de Smalenfe17a782018-04-26 12:54:42 +0000531 template <int Bits, int Scale>
Sander de Smalen50ded902018-04-29 17:33:38 +0000532 DiagnosticPredicate isImmScaled(bool Signed) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000533 if (!isImm())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000534 return DiagnosticPredicateTy::NoMatch;
535
Tim Northover3b0846e2014-05-24 12:50:23 +0000536 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
537 if (!MCE)
Sander de Smalenfe17a782018-04-26 12:54:42 +0000538 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000539
Sander de Smalen50ded902018-04-29 17:33:38 +0000540 int64_t MinVal, MaxVal;
541 if (Signed) {
542 int64_t Shift = Bits - 1;
543 MinVal = (int64_t(1) << Shift) * -Scale;
544 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
545 } else {
546 MinVal = 0;
547 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
548 }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000549
Tim Northover3b0846e2014-05-24 12:50:23 +0000550 int64_t Val = MCE->getValue();
Sander de Smalenfe17a782018-04-26 12:54:42 +0000551 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
552 return DiagnosticPredicateTy::Match;
553
554 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +0000555 }
556
Sander de Smalen245e0e62018-01-22 10:46:00 +0000557 bool isSVEPattern() const {
558 if (!isImm())
559 return false;
560 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
561 if (!MCE)
562 return false;
563 int64_t Val = MCE->getValue();
564 return Val >= 0 && Val < 32;
565 }
566
Tim Northover3b0846e2014-05-24 12:50:23 +0000567 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
568 AArch64MCExpr::VariantKind ELFRefKind;
569 MCSymbolRefExpr::VariantKind DarwinRefKind;
570 int64_t Addend;
571 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
572 Addend)) {
573 // If we don't understand the expression, assume the best and
574 // let the fixup and relocation code deal with it.
575 return true;
576 }
577
578 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
579 ELFRefKind == AArch64MCExpr::VK_LO12 ||
580 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
581 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
582 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
583 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
584 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
585 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000586 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
587 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
588 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000589 // Note that we don't range-check the addend. It's adjusted modulo page
590 // size when converted, so there is no "out of range" condition when using
591 // @pageoff.
592 return Addend >= 0 && (Addend % Scale) == 0;
593 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
594 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
595 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
596 return Addend == 0;
597 }
598
599 return false;
600 }
601
602 template <int Scale> bool isUImm12Offset() const {
603 if (!isImm())
604 return false;
605
606 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
607 if (!MCE)
608 return isSymbolicUImm12Offset(getImm(), Scale);
609
610 int64_t Val = MCE->getValue();
611 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
612 }
613
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000614 template <int N, int M>
615 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000616 if (!isImm())
617 return false;
618 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
619 if (!MCE)
620 return false;
621 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000622 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000623 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000624
Sander de Smalena1c259c2018-01-29 13:05:38 +0000625 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
626 // a logical immediate can always be represented when inverted.
627 template <typename T>
628 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000629 if (!isImm())
630 return false;
631 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
632 if (!MCE)
633 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000634
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000635 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000636 int64_t SVal = typename std::make_signed<T>::type(Val);
637 int64_t UVal = typename std::make_unsigned<T>::type(Val);
638 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000639 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000640
Sander de Smalena1c259c2018-01-29 13:05:38 +0000641 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000642 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000643
Tim Northover3b0846e2014-05-24 12:50:23 +0000644 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000645
Sander de Smalen62770792018-05-25 09:47:52 +0000646 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
647 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
648 /// immediate that can be shifted by 'Shift'.
649 template <unsigned Width>
650 Optional<std::pair<int64_t, unsigned> > getShiftedVal() const {
651 if (isShiftedImm() && Width == getShiftedImmShift())
652 if (auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
653 return std::make_pair(CE->getValue(), Width);
654
655 if (isImm())
656 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
657 int64_t Val = CE->getValue();
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000658 if ((Val != 0) && (uint64_t(Val >> Width) << Width) == uint64_t(Val))
Sander de Smalen62770792018-05-25 09:47:52 +0000659 return std::make_pair(Val >> Width, Width);
660 else
661 return std::make_pair(Val, 0u);
662 }
663
664 return {};
665 }
666
Tim Northover3b0846e2014-05-24 12:50:23 +0000667 bool isAddSubImm() const {
668 if (!isShiftedImm() && !isImm())
669 return false;
670
671 const MCExpr *Expr;
672
673 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
674 if (isShiftedImm()) {
675 unsigned Shift = ShiftedImm.ShiftAmount;
676 Expr = ShiftedImm.Val;
677 if (Shift != 0 && Shift != 12)
678 return false;
679 } else {
680 Expr = getImm();
681 }
682
683 AArch64MCExpr::VariantKind ELFRefKind;
684 MCSymbolRefExpr::VariantKind DarwinRefKind;
685 int64_t Addend;
686 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
687 DarwinRefKind, Addend)) {
688 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
689 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
690 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
691 || ELFRefKind == AArch64MCExpr::VK_LO12
692 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
693 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
694 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
695 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
696 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
697 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000698 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
699 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
700 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000701 }
702
Sander de Smalen98686c62018-05-29 10:39:49 +0000703 // If it's a constant, it should be a real immediate in range.
Sander de Smalen62770792018-05-25 09:47:52 +0000704 if (auto ShiftedVal = getShiftedVal<12>())
705 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
Diana Picusc93518d2016-10-11 09:17:47 +0000706
707 // If it's an expression, we hope for the best and let the fixup/relocation
708 // code deal with it.
709 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000710 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000711
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000712 bool isAddSubImmNeg() const {
713 if (!isShiftedImm() && !isImm())
714 return false;
715
Sander de Smalen98686c62018-05-29 10:39:49 +0000716 // Otherwise it should be a real negative immediate in range.
717 if (auto ShiftedVal = getShiftedVal<12>())
718 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000719
Sander de Smalen98686c62018-05-29 10:39:49 +0000720 return false;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000721 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000722
Sander de Smalen62770792018-05-25 09:47:52 +0000723 // Signed value in the range -128 to +127. For element widths of
724 // 16 bits or higher it may also be a signed multiple of 256 in the
725 // range -32768 to +32512.
726 // For element-width of 8 bits a range of -128 to 255 is accepted,
727 // since a copy of a byte can be either signed/unsigned.
728 template <typename T>
729 DiagnosticPredicate isSVECpyImm() const {
730 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
731 return DiagnosticPredicateTy::NoMatch;
732
733 bool IsByte =
734 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
735 if (auto ShiftedImm = getShiftedVal<8>())
736 if (!(IsByte && ShiftedImm->second) &&
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000737 AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
738 << ShiftedImm->second))
Sander de Smalen62770792018-05-25 09:47:52 +0000739 return DiagnosticPredicateTy::Match;
740
741 return DiagnosticPredicateTy::NearMatch;
742 }
743
Sander de Smalen98686c62018-05-29 10:39:49 +0000744 // Unsigned value in the range 0 to 255. For element widths of
745 // 16 bits or higher it may also be a signed multiple of 256 in the
746 // range 0 to 65280.
747 template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
748 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
749 return DiagnosticPredicateTy::NoMatch;
750
751 bool IsByte =
752 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
753 if (auto ShiftedImm = getShiftedVal<8>())
754 if (!(IsByte && ShiftedImm->second) &&
755 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
756 << ShiftedImm->second))
757 return DiagnosticPredicateTy::Match;
758
759 return DiagnosticPredicateTy::NearMatch;
760 }
761
Sander de Smalen97ca6b92018-06-01 07:25:46 +0000762 template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
763 if (isLogicalImm<T>() && !isSVECpyImm<T>())
764 return DiagnosticPredicateTy::Match;
765 return DiagnosticPredicateTy::NoMatch;
766 }
767
Tim Northover3b0846e2014-05-24 12:50:23 +0000768 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000769
Tim Northover3b0846e2014-05-24 12:50:23 +0000770 bool isSIMDImmType10() const {
771 if (!isImm())
772 return false;
773 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
774 if (!MCE)
775 return false;
776 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
777 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000778
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000779 template<int N>
780 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000781 if (!isImm())
782 return false;
783 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
784 if (!MCE)
785 return true;
786 int64_t Val = MCE->getValue();
787 if (Val & 0x3)
788 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000789 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
790 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000791 }
792
793 bool
794 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
795 if (!isImm())
796 return false;
797
798 AArch64MCExpr::VariantKind ELFRefKind;
799 MCSymbolRefExpr::VariantKind DarwinRefKind;
800 int64_t Addend;
801 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
802 DarwinRefKind, Addend)) {
803 return false;
804 }
805 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
806 return false;
807
808 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
809 if (ELFRefKind == AllowedModifiers[i])
810 return Addend == 0;
811 }
812
813 return false;
814 }
815
816 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000817 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000818 }
819
820 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000821 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
822 AArch64MCExpr::VK_TPREL_G2,
823 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000824 }
825
826 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000827 return isMovWSymbol({
828 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000829 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
830 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000831 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000832 }
833
834 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000835 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
836 AArch64MCExpr::VK_TPREL_G0,
837 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000838 }
839
840 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000841 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000842 }
843
844 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000845 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000846 }
847
848 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000849 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
850 AArch64MCExpr::VK_TPREL_G1_NC,
851 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000852 }
853
854 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000855 return isMovWSymbol(
856 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
857 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000858 }
859
860 template<int RegWidth, int Shift>
861 bool isMOVZMovAlias() const {
862 if (!isImm()) return false;
863
864 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
865 if (!CE) return false;
866 uint64_t Value = CE->getValue();
867
Tim Northoverdaa1c012016-06-16 01:42:25 +0000868 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000869 }
870
871 template<int RegWidth, int Shift>
872 bool isMOVNMovAlias() const {
873 if (!isImm()) return false;
874
875 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
876 if (!CE) return false;
877 uint64_t Value = CE->getValue();
878
Tim Northoverdaa1c012016-06-16 01:42:25 +0000879 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000880 }
881
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000882 bool isFPImm() const {
883 return Kind == k_FPImm &&
884 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt()) != -1;
885 }
886
Tim Northover3b0846e2014-05-24 12:50:23 +0000887 bool isBarrier() const { return Kind == k_Barrier; }
888 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000889
Tim Northover3b0846e2014-05-24 12:50:23 +0000890 bool isMRSSystemRegister() const {
891 if (!isSysReg()) return false;
892
Tim Northover7cd58932015-01-22 17:23:04 +0000893 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000894 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000895
Tim Northover3b0846e2014-05-24 12:50:23 +0000896 bool isMSRSystemRegister() const {
897 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000898 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000899 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000900
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000901 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000902 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000903 return (SysReg.PStateField == AArch64PState::PAN ||
904 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000905 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000906
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000907 bool isSystemPStateFieldWithImm0_15() const {
908 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000909 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000910 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000911
Florian Hahnc4422242017-11-07 13:07:50 +0000912 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000913 return Kind == k_Register;
914 }
915
916 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000917 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
918 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000919
Florian Hahnc4422242017-11-07 13:07:50 +0000920 bool isNeonVectorReg() const {
921 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
922 }
923
924 bool isNeonVectorRegLo() const {
925 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000926 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
927 Reg.RegNum);
928 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000929
Sander de Smalencd6be962017-12-20 11:02:42 +0000930 template <unsigned Class> bool isSVEVectorReg() const {
931 RegKind RK;
932 switch (Class) {
933 case AArch64::ZPRRegClassID:
934 RK = RegKind::SVEDataVector;
935 break;
936 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000937 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000938 RK = RegKind::SVEPredicateVector;
939 break;
940 default:
941 llvm_unreachable("Unsupport register class");
942 }
943
944 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000945 AArch64MCRegisterClasses[Class].contains(getReg());
946 }
947
Sander de Smalenfd54a782018-06-04 07:07:35 +0000948 template <unsigned Class> bool isFPRasZPR() const {
949 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
950 AArch64MCRegisterClasses[Class].contains(getReg());
951 }
952
Sander de Smalencd6be962017-12-20 11:02:42 +0000953 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +0000954 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
955 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
956 return DiagnosticPredicateTy::NoMatch;
957
958 if (isSVEVectorReg<Class>() &&
959 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
960 return DiagnosticPredicateTy::Match;
961
962 return DiagnosticPredicateTy::NearMatch;
963 }
964
965 template <int ElementWidth, unsigned Class>
966 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
967 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
968 return DiagnosticPredicateTy::NoMatch;
969
970 if (isSVEVectorReg<Class>() &&
971 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
972 return DiagnosticPredicateTy::Match;
973
974 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +0000975 }
976
Sander de Smaleneb896b12018-04-25 09:26:47 +0000977 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +0000978 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
979 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +0000980 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
981 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
982 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000983 return DiagnosticPredicateTy::NoMatch;
984
Sander de Smalen5861c262018-04-30 07:24:38 +0000985 // Give a more specific diagnostic when the user has explicitly typed in
986 // a shift-amount that does not match what is expected, but for which
987 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
988 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
989 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
990 ShiftExtendTy == AArch64_AM::SXTW) &&
991 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
992 return DiagnosticPredicateTy::NoMatch;
993
994 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000995 return DiagnosticPredicateTy::Match;
996
997 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +0000998 }
999
Tim Northover3b0846e2014-05-24 12:50:23 +00001000 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001001 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001002 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
1003 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001004
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001005 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001006 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001007 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
1008 Reg.RegNum);
1009 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001010
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001011 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001012 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001013 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1014 Reg.RegNum);
1015 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001016
Sam Parker5f934642017-08-31 09:27:04 +00001017 template<int64_t Angle, int64_t Remainder>
1018 bool isComplexRotation() const {
1019 if (!isImm()) return false;
1020
1021 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1022 if (!CE) return false;
1023 uint64_t Value = CE->getValue();
1024
1025 return (Value % Angle == Remainder && Value <= 270);
1026 }
1027
Sander de Smalen149916d2018-04-20 07:24:20 +00001028 template <unsigned RegClassID> bool isGPR64() const {
1029 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1030 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1031 }
1032
1033 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001034 DiagnosticPredicate isGPR64WithShiftExtend() const {
1035 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1036 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001037
Sander de Smalenfe17a782018-04-26 12:54:42 +00001038 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1039 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1040 return DiagnosticPredicateTy::Match;
1041 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001042 }
1043
Tim Northover3b0846e2014-05-24 12:50:23 +00001044 /// Is this a vector list with the type implicit (presumably attached to the
1045 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001046 template <RegKind VectorKind, unsigned NumRegs>
1047 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001048 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001049 VectorList.NumElements == 0 &&
1050 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001051 }
1052
Sander de Smalen650234b2018-04-12 11:40:52 +00001053 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1054 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001055 bool isTypedVectorList() const {
1056 if (Kind != k_VectorList)
1057 return false;
1058 if (VectorList.Count != NumRegs)
1059 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001060 if (VectorList.RegisterKind != VectorKind)
1061 return false;
1062 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001063 return false;
1064 return VectorList.NumElements == NumElements;
1065 }
1066
Sander de Smalenc33d6682018-06-04 06:40:55 +00001067 template <int Min, int Max>
1068 DiagnosticPredicate isVectorIndex() const {
1069 if (Kind != k_VectorIndex)
1070 return DiagnosticPredicateTy::NoMatch;
1071 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1072 return DiagnosticPredicateTy::Match;
1073 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001074 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001075
Tim Northover3b0846e2014-05-24 12:50:23 +00001076 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001077
Tim Northover3b0846e2014-05-24 12:50:23 +00001078 bool isTokenEqual(StringRef Str) const {
1079 return Kind == k_Token && getToken() == Str;
1080 }
1081 bool isSysCR() const { return Kind == k_SysCR; }
1082 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001083 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001084 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1085 bool isShifter() const {
1086 if (!isShiftExtend())
1087 return false;
1088
1089 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1090 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1091 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1092 ST == AArch64_AM::MSL);
1093 }
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001094
1095 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1096 if (Kind != k_FPImm)
1097 return DiagnosticPredicateTy::NoMatch;
1098
1099 if (getFPImmIsExact()) {
1100 // Lookup the immediate from table of supported immediates.
1101 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1102 assert(Desc && "Unknown enum value");
1103
1104 // Calculate its FP value.
1105 APFloat RealVal(APFloat::IEEEdouble());
1106 if (RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero) !=
1107 APFloat::opOK)
1108 llvm_unreachable("FP immediate is not exact");
1109
1110 if (getFPImm().bitwiseIsEqual(RealVal))
1111 return DiagnosticPredicateTy::Match;
1112 }
1113
1114 return DiagnosticPredicateTy::NearMatch;
1115 }
1116
1117 template <unsigned ImmA, unsigned ImmB>
1118 DiagnosticPredicate isExactFPImm() const {
1119 DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1120 if ((Res = isExactFPImm<ImmA>()))
1121 return DiagnosticPredicateTy::Match;
1122 if ((Res = isExactFPImm<ImmB>()))
1123 return DiagnosticPredicateTy::Match;
1124 return Res;
1125 }
1126
Tim Northover3b0846e2014-05-24 12:50:23 +00001127 bool isExtend() const {
1128 if (!isShiftExtend())
1129 return false;
1130
1131 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1132 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1133 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1134 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1135 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1136 ET == AArch64_AM::LSL) &&
1137 getShiftExtendAmount() <= 4;
1138 }
1139
1140 bool isExtend64() const {
1141 if (!isExtend())
1142 return false;
1143 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1144 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1145 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1146 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001147
Tim Northover3b0846e2014-05-24 12:50:23 +00001148 bool isExtendLSL64() const {
1149 if (!isExtend())
1150 return false;
1151 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1152 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1153 ET == AArch64_AM::LSL) &&
1154 getShiftExtendAmount() <= 4;
1155 }
1156
1157 template<int Width> bool isMemXExtend() const {
1158 if (!isExtend())
1159 return false;
1160 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1161 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1162 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1163 getShiftExtendAmount() == 0);
1164 }
1165
1166 template<int Width> bool isMemWExtend() const {
1167 if (!isExtend())
1168 return false;
1169 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1170 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1171 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1172 getShiftExtendAmount() == 0);
1173 }
1174
1175 template <unsigned width>
1176 bool isArithmeticShifter() const {
1177 if (!isShifter())
1178 return false;
1179
1180 // An arithmetic shifter is LSL, LSR, or ASR.
1181 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1182 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1183 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1184 }
1185
1186 template <unsigned width>
1187 bool isLogicalShifter() const {
1188 if (!isShifter())
1189 return false;
1190
1191 // A logical shifter is LSL, LSR, ASR or ROR.
1192 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1193 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1194 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1195 getShiftExtendAmount() < width;
1196 }
1197
1198 bool isMovImm32Shifter() const {
1199 if (!isShifter())
1200 return false;
1201
1202 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1203 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1204 if (ST != AArch64_AM::LSL)
1205 return false;
1206 uint64_t Val = getShiftExtendAmount();
1207 return (Val == 0 || Val == 16);
1208 }
1209
1210 bool isMovImm64Shifter() const {
1211 if (!isShifter())
1212 return false;
1213
1214 // A MOVi shifter is LSL of 0 or 16.
1215 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1216 if (ST != AArch64_AM::LSL)
1217 return false;
1218 uint64_t Val = getShiftExtendAmount();
1219 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1220 }
1221
1222 bool isLogicalVecShifter() const {
1223 if (!isShifter())
1224 return false;
1225
1226 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1227 unsigned Shift = getShiftExtendAmount();
1228 return getShiftExtendType() == AArch64_AM::LSL &&
1229 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1230 }
1231
1232 bool isLogicalVecHalfWordShifter() const {
1233 if (!isLogicalVecShifter())
1234 return false;
1235
1236 // A logical vector shifter is a left shift by 0 or 8.
1237 unsigned Shift = getShiftExtendAmount();
1238 return getShiftExtendType() == AArch64_AM::LSL &&
1239 (Shift == 0 || Shift == 8);
1240 }
1241
1242 bool isMoveVecShifter() const {
1243 if (!isShiftExtend())
1244 return false;
1245
1246 // A logical vector shifter is a left shift by 8 or 16.
1247 unsigned Shift = getShiftExtendAmount();
1248 return getShiftExtendType() == AArch64_AM::MSL &&
1249 (Shift == 8 || Shift == 16);
1250 }
1251
1252 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1253 // to LDUR/STUR when the offset is not legal for the former but is for
1254 // the latter. As such, in addition to checking for being a legal unscaled
1255 // address, also check that it is not a legal scaled address. This avoids
1256 // ambiguity in the matcher.
1257 template<int Width>
1258 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001259 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001260 }
1261
1262 bool isAdrpLabel() const {
1263 // Validation was handled during parsing, so we just sanity check that
1264 // something didn't go haywire.
1265 if (!isImm())
1266 return false;
1267
1268 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1269 int64_t Val = CE->getValue();
1270 int64_t Min = - (4096 * (1LL << (21 - 1)));
1271 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1272 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1273 }
1274
1275 return true;
1276 }
1277
1278 bool isAdrLabel() const {
1279 // Validation was handled during parsing, so we just sanity check that
1280 // something didn't go haywire.
1281 if (!isImm())
1282 return false;
1283
1284 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1285 int64_t Val = CE->getValue();
1286 int64_t Min = - (1LL << (21 - 1));
1287 int64_t Max = ((1LL << (21 - 1)) - 1);
1288 return Val >= Min && Val <= Max;
1289 }
1290
1291 return true;
1292 }
1293
1294 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1295 // Add as immediates when possible. Null MCExpr = 0.
1296 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001297 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001298 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001299 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001300 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001301 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001302 }
1303
1304 void addRegOperands(MCInst &Inst, unsigned N) const {
1305 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001306 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001307 }
1308
1309 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1310 assert(N == 1 && "Invalid number of operands!");
1311 assert(
1312 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1313
1314 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1315 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1316 RI->getEncodingValue(getReg()));
1317
Jim Grosbache9119e42015-05-13 18:37:00 +00001318 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001319 }
1320
Sander de Smalenfd54a782018-06-04 07:07:35 +00001321 template <int Width>
1322 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1323 unsigned Base;
1324 switch (Width) {
1325 case 8: Base = AArch64::B0; break;
1326 case 16: Base = AArch64::H0; break;
1327 case 32: Base = AArch64::S0; break;
1328 case 64: Base = AArch64::D0; break;
1329 case 128: Base = AArch64::Q0; break;
1330 default:
1331 llvm_unreachable("Unsupported width");
1332 }
1333 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1334 }
1335
Tim Northover3b0846e2014-05-24 12:50:23 +00001336 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1337 assert(N == 1 && "Invalid number of operands!");
1338 assert(
1339 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001340 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001341 }
1342
1343 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1344 assert(N == 1 && "Invalid number of operands!");
1345 assert(
1346 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001347 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001348 }
1349
1350 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1351 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001352 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001353 }
1354
Sander de Smalen525e3222018-04-12 13:19:32 +00001355 enum VecListIndexType {
1356 VecListIdx_DReg = 0,
1357 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001358 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001359 };
1360
1361 template <VecListIndexType RegTy, unsigned NumRegs>
1362 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001363 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001364 static const unsigned FirstRegs[][5] = {
1365 /* DReg */ { AArch64::Q0,
1366 AArch64::D0, AArch64::D0_D1,
1367 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1368 /* QReg */ { AArch64::Q0,
1369 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001370 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1371 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001372 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001373 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001374 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001375
Sander de Smalen7a210db2018-04-16 10:46:18 +00001376 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1377 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001378
Sander de Smalen525e3222018-04-12 13:19:32 +00001379 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1380 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1381 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001382 }
1383
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001384 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001385 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001386 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001387 }
1388
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001389 template <unsigned ImmIs0, unsigned ImmIs1>
1390 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1391 assert(N == 1 && "Invalid number of operands!");
1392 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1393 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1394 }
1395
Tim Northover3b0846e2014-05-24 12:50:23 +00001396 void addImmOperands(MCInst &Inst, unsigned N) const {
1397 assert(N == 1 && "Invalid number of operands!");
1398 // If this is a pageoff symrefexpr with an addend, adjust the addend
1399 // to be only the page-offset portion. Otherwise, just add the expr
1400 // as-is.
1401 addExpr(Inst, getImm());
1402 }
1403
Sander de Smalen62770792018-05-25 09:47:52 +00001404 template <int Shift>
1405 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001406 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001407 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1408 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1409 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1410 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001411 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001412 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001413 } else {
1414 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001415 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001416 }
1417 }
1418
Sander de Smalen62770792018-05-25 09:47:52 +00001419 template <int Shift>
1420 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001421 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001422 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1423 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1424 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1425 } else
1426 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001427 }
1428
Tim Northover3b0846e2014-05-24 12:50:23 +00001429 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1430 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001431 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001432 }
1433
1434 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1435 assert(N == 1 && "Invalid number of operands!");
1436 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1437 if (!MCE)
1438 addExpr(Inst, getImm());
1439 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001440 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001441 }
1442
1443 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1444 addImmOperands(Inst, N);
1445 }
1446
1447 template<int Scale>
1448 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1449 assert(N == 1 && "Invalid number of operands!");
1450 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1451
1452 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001453 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001454 return;
1455 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001456 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001457 }
1458
Sander de Smalen5c625982018-04-13 12:56:14 +00001459 template <int Scale>
1460 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1461 assert(N == 1 && "Invalid number of operands!");
1462 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1463 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1464 }
1465
Sander de Smalena1c259c2018-01-29 13:05:38 +00001466 template <typename T>
1467 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001468 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001469 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001470 typename std::make_unsigned<T>::type Val = MCE->getValue();
1471 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001472 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001473 }
1474
Sander de Smalena1c259c2018-01-29 13:05:38 +00001475 template <typename T>
1476 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001477 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001478 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001479 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1480 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001481 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001482 }
1483
Tim Northover3b0846e2014-05-24 12:50:23 +00001484 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1485 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001486 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001487 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001488 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001489 }
1490
1491 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1492 // Branch operands don't encode the low bits, so shift them off
1493 // here. If it's a label, however, just put it on directly as there's
1494 // not enough information now to do anything.
1495 assert(N == 1 && "Invalid number of operands!");
1496 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1497 if (!MCE) {
1498 addExpr(Inst, getImm());
1499 return;
1500 }
1501 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001502 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001503 }
1504
1505 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1506 // Branch operands don't encode the low bits, so shift them off
1507 // here. If it's a label, however, just put it on directly as there's
1508 // not enough information now to do anything.
1509 assert(N == 1 && "Invalid number of operands!");
1510 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1511 if (!MCE) {
1512 addExpr(Inst, getImm());
1513 return;
1514 }
1515 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001516 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001517 }
1518
1519 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1520 // Branch operands don't encode the low bits, so shift them off
1521 // here. If it's a label, however, just put it on directly as there's
1522 // not enough information now to do anything.
1523 assert(N == 1 && "Invalid number of operands!");
1524 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1525 if (!MCE) {
1526 addExpr(Inst, getImm());
1527 return;
1528 }
1529 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001530 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001531 }
1532
1533 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1534 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001535 Inst.addOperand(MCOperand::createImm(
1536 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
Tim Northover3b0846e2014-05-24 12:50:23 +00001537 }
1538
1539 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1540 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001541 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001542 }
1543
1544 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1545 assert(N == 1 && "Invalid number of operands!");
1546
Jim Grosbache9119e42015-05-13 18:37:00 +00001547 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001548 }
1549
1550 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1551 assert(N == 1 && "Invalid number of operands!");
1552
Jim Grosbache9119e42015-05-13 18:37:00 +00001553 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001554 }
1555
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001556 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1557 assert(N == 1 && "Invalid number of operands!");
1558
1559 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1560 }
1561
1562 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001563 assert(N == 1 && "Invalid number of operands!");
1564
Jim Grosbache9119e42015-05-13 18:37:00 +00001565 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001566 }
1567
1568 void addSysCROperands(MCInst &Inst, unsigned N) const {
1569 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001570 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001571 }
1572
1573 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1574 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001575 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001576 }
1577
Oliver Stannarda34e4702015-12-01 10:48:51 +00001578 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1579 assert(N == 1 && "Invalid number of operands!");
1580 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1581 }
1582
Tim Northover3b0846e2014-05-24 12:50:23 +00001583 void addShifterOperands(MCInst &Inst, unsigned N) const {
1584 assert(N == 1 && "Invalid number of operands!");
1585 unsigned Imm =
1586 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001587 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001588 }
1589
1590 void addExtendOperands(MCInst &Inst, unsigned N) const {
1591 assert(N == 1 && "Invalid number of operands!");
1592 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1593 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1594 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001595 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001596 }
1597
1598 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1599 assert(N == 1 && "Invalid number of operands!");
1600 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1601 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1602 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001603 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001604 }
1605
1606 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1607 assert(N == 2 && "Invalid number of operands!");
1608 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1609 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001610 Inst.addOperand(MCOperand::createImm(IsSigned));
1611 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001612 }
1613
1614 // For 8-bit load/store instructions with a register offset, both the
1615 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1616 // they're disambiguated by whether the shift was explicit or implicit rather
1617 // than its size.
1618 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1619 assert(N == 2 && "Invalid number of operands!");
1620 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1621 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001622 Inst.addOperand(MCOperand::createImm(IsSigned));
1623 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001624 }
1625
1626 template<int Shift>
1627 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1628 assert(N == 1 && "Invalid number of operands!");
1629
1630 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1631 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001632 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001633 }
1634
1635 template<int Shift>
1636 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1637 assert(N == 1 && "Invalid number of operands!");
1638
1639 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1640 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001641 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001642 }
1643
Sam Parker5f934642017-08-31 09:27:04 +00001644 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1645 assert(N == 1 && "Invalid number of operands!");
1646 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1647 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1648 }
1649
1650 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1651 assert(N == 1 && "Invalid number of operands!");
1652 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1653 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1654 }
1655
Tim Northover3b0846e2014-05-24 12:50:23 +00001656 void print(raw_ostream &OS) const override;
1657
David Blaikie960ea3f2014-06-08 16:18:35 +00001658 static std::unique_ptr<AArch64Operand>
1659 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1660 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001661 Op->Tok.Data = Str.data();
1662 Op->Tok.Length = Str.size();
1663 Op->Tok.IsSuffix = IsSuffix;
1664 Op->StartLoc = S;
1665 Op->EndLoc = S;
1666 return Op;
1667 }
1668
David Blaikie960ea3f2014-06-08 16:18:35 +00001669 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001670 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
1671 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1672 unsigned ShiftAmount = 0,
1673 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001674 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001675 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001676 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001677 Op->Reg.ElementWidth = 0;
1678 Op->Reg.ShiftExtend.Type = ExtTy;
1679 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1680 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001681 Op->StartLoc = S;
1682 Op->EndLoc = E;
1683 return Op;
1684 }
1685
David Blaikie960ea3f2014-06-08 16:18:35 +00001686 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001687 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001688 SMLoc S, SMLoc E, MCContext &Ctx,
1689 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1690 unsigned ShiftAmount = 0,
1691 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001692 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1693 Kind == RegKind::SVEPredicateVector) &&
1694 "Invalid vector kind");
Sander de Smalen149916d2018-04-20 07:24:20 +00001695 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, ExtTy, ShiftAmount,
1696 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001697 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001698 return Op;
1699 }
1700
1701 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001702 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001703 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1704 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001705 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001706 Op->VectorList.RegNum = RegNum;
1707 Op->VectorList.Count = Count;
1708 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001709 Op->VectorList.ElementWidth = ElementWidth;
1710 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001711 Op->StartLoc = S;
1712 Op->EndLoc = E;
1713 return Op;
1714 }
1715
David Blaikie960ea3f2014-06-08 16:18:35 +00001716 static std::unique_ptr<AArch64Operand>
1717 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1718 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001719 Op->VectorIndex.Val = Idx;
1720 Op->StartLoc = S;
1721 Op->EndLoc = E;
1722 return Op;
1723 }
1724
David Blaikie960ea3f2014-06-08 16:18:35 +00001725 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1726 SMLoc E, MCContext &Ctx) {
1727 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001728 Op->Imm.Val = Val;
1729 Op->StartLoc = S;
1730 Op->EndLoc = E;
1731 return Op;
1732 }
1733
David Blaikie960ea3f2014-06-08 16:18:35 +00001734 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1735 unsigned ShiftAmount,
1736 SMLoc S, SMLoc E,
1737 MCContext &Ctx) {
1738 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001739 Op->ShiftedImm .Val = Val;
1740 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1741 Op->StartLoc = S;
1742 Op->EndLoc = E;
1743 return Op;
1744 }
1745
David Blaikie960ea3f2014-06-08 16:18:35 +00001746 static std::unique_ptr<AArch64Operand>
1747 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1748 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001749 Op->CondCode.Code = Code;
1750 Op->StartLoc = S;
1751 Op->EndLoc = E;
1752 return Op;
1753 }
1754
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001755 static std::unique_ptr<AArch64Operand>
1756 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001757 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001758 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
1759 Op->FPImm.IsExact = IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +00001760 Op->StartLoc = S;
1761 Op->EndLoc = S;
1762 return Op;
1763 }
1764
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001765 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1766 StringRef Str,
1767 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001768 MCContext &Ctx) {
1769 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001770 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001771 Op->Barrier.Data = Str.data();
1772 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001773 Op->StartLoc = S;
1774 Op->EndLoc = S;
1775 return Op;
1776 }
1777
Tim Northover7cd58932015-01-22 17:23:04 +00001778 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1779 uint32_t MRSReg,
1780 uint32_t MSRReg,
1781 uint32_t PStateField,
1782 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001783 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001784 Op->SysReg.Data = Str.data();
1785 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001786 Op->SysReg.MRSReg = MRSReg;
1787 Op->SysReg.MSRReg = MSRReg;
1788 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001789 Op->StartLoc = S;
1790 Op->EndLoc = S;
1791 return Op;
1792 }
1793
David Blaikie960ea3f2014-06-08 16:18:35 +00001794 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1795 SMLoc E, MCContext &Ctx) {
1796 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001797 Op->SysCRImm.Val = Val;
1798 Op->StartLoc = S;
1799 Op->EndLoc = E;
1800 return Op;
1801 }
1802
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001803 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1804 StringRef Str,
1805 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001806 MCContext &Ctx) {
1807 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001808 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001809 Op->Barrier.Data = Str.data();
1810 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001811 Op->StartLoc = S;
1812 Op->EndLoc = S;
1813 return Op;
1814 }
1815
Oliver Stannarda34e4702015-12-01 10:48:51 +00001816 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1817 StringRef Str,
1818 SMLoc S,
1819 MCContext &Ctx) {
1820 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1821 Op->PSBHint.Val = Val;
1822 Op->PSBHint.Data = Str.data();
1823 Op->PSBHint.Length = Str.size();
1824 Op->StartLoc = S;
1825 Op->EndLoc = S;
1826 return Op;
1827 }
1828
David Blaikie960ea3f2014-06-08 16:18:35 +00001829 static std::unique_ptr<AArch64Operand>
1830 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1831 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1832 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001833 Op->ShiftExtend.Type = ShOp;
1834 Op->ShiftExtend.Amount = Val;
1835 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1836 Op->StartLoc = S;
1837 Op->EndLoc = E;
1838 return Op;
1839 }
1840};
1841
1842} // end anonymous namespace.
1843
1844void AArch64Operand::print(raw_ostream &OS) const {
1845 switch (Kind) {
1846 case k_FPImm:
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001847 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
1848 if (!getFPImmIsExact())
1849 OS << " (inexact)";
1850 OS << ">";
Tim Northover3b0846e2014-05-24 12:50:23 +00001851 break;
1852 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001853 StringRef Name = getBarrierName();
1854 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001855 OS << "<barrier " << Name << ">";
1856 else
1857 OS << "<barrier invalid #" << getBarrier() << ">";
1858 break;
1859 }
1860 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001861 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001862 break;
1863 case k_ShiftedImm: {
1864 unsigned Shift = getShiftedImmShift();
1865 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001866 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001867 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1868 break;
1869 }
1870 case k_CondCode:
1871 OS << "<condcode " << getCondCode() << ">";
1872 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001873 case k_VectorList: {
1874 OS << "<vectorlist ";
1875 unsigned Reg = getVectorListStart();
1876 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1877 OS << Reg + i << " ";
1878 OS << ">";
1879 break;
1880 }
1881 case k_VectorIndex:
1882 OS << "<vectorindex " << getVectorIndex() << ">";
1883 break;
1884 case k_SysReg:
1885 OS << "<sysreg: " << getSysReg() << '>';
1886 break;
1887 case k_Token:
1888 OS << "'" << getToken() << "'";
1889 break;
1890 case k_SysCR:
1891 OS << "c" << getSysCR();
1892 break;
1893 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001894 StringRef Name = getPrefetchName();
1895 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001896 OS << "<prfop " << Name << ">";
1897 else
1898 OS << "<prfop invalid #" << getPrefetch() << ">";
1899 break;
1900 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001901 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001902 OS << getPSBHintName();
1903 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00001904 case k_Register:
1905 OS << "<register " << getReg() << ">";
1906 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
1907 break;
1908 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001909 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001910 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1911 << getShiftExtendAmount();
1912 if (!hasShiftExtendAmount())
1913 OS << "<imp>";
1914 OS << '>';
1915 break;
1916 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001917}
1918
1919/// @name Auto-generated Match Functions
1920/// {
1921
1922static unsigned MatchRegisterName(StringRef Name);
1923
1924/// }
1925
Florian Hahnc4422242017-11-07 13:07:50 +00001926static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001927 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001928 .Case("v0", AArch64::Q0)
1929 .Case("v1", AArch64::Q1)
1930 .Case("v2", AArch64::Q2)
1931 .Case("v3", AArch64::Q3)
1932 .Case("v4", AArch64::Q4)
1933 .Case("v5", AArch64::Q5)
1934 .Case("v6", AArch64::Q6)
1935 .Case("v7", AArch64::Q7)
1936 .Case("v8", AArch64::Q8)
1937 .Case("v9", AArch64::Q9)
1938 .Case("v10", AArch64::Q10)
1939 .Case("v11", AArch64::Q11)
1940 .Case("v12", AArch64::Q12)
1941 .Case("v13", AArch64::Q13)
1942 .Case("v14", AArch64::Q14)
1943 .Case("v15", AArch64::Q15)
1944 .Case("v16", AArch64::Q16)
1945 .Case("v17", AArch64::Q17)
1946 .Case("v18", AArch64::Q18)
1947 .Case("v19", AArch64::Q19)
1948 .Case("v20", AArch64::Q20)
1949 .Case("v21", AArch64::Q21)
1950 .Case("v22", AArch64::Q22)
1951 .Case("v23", AArch64::Q23)
1952 .Case("v24", AArch64::Q24)
1953 .Case("v25", AArch64::Q25)
1954 .Case("v26", AArch64::Q26)
1955 .Case("v27", AArch64::Q27)
1956 .Case("v28", AArch64::Q28)
1957 .Case("v29", AArch64::Q29)
1958 .Case("v30", AArch64::Q30)
1959 .Case("v31", AArch64::Q31)
1960 .Default(0);
1961}
1962
Sander de Smalen73937b72018-04-11 07:36:10 +00001963/// Returns an optional pair of (#elements, element-width) if Suffix
1964/// is a valid vector kind. Where the number of elements in a vector
1965/// or the vector width is implicit or explicitly unknown (but still a
1966/// valid suffix kind), 0 is used.
1967static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1968 RegKind VectorKind) {
1969 std::pair<int, int> Res = {-1, -1};
1970
1971 switch (VectorKind) {
1972 case RegKind::NeonVector:
1973 Res =
1974 StringSwitch<std::pair<int, int>>(Suffix.lower())
1975 .Case("", {0, 0})
1976 .Case(".1d", {1, 64})
1977 .Case(".1q", {1, 128})
1978 // '.2h' needed for fp16 scalar pairwise reductions
1979 .Case(".2h", {2, 16})
1980 .Case(".2s", {2, 32})
1981 .Case(".2d", {2, 64})
1982 // '.4b' is another special case for the ARMv8.2a dot product
1983 // operand
1984 .Case(".4b", {4, 8})
1985 .Case(".4h", {4, 16})
1986 .Case(".4s", {4, 32})
1987 .Case(".8b", {8, 8})
1988 .Case(".8h", {8, 16})
1989 .Case(".16b", {16, 8})
1990 // Accept the width neutral ones, too, for verbose syntax. If those
1991 // aren't used in the right places, the token operand won't match so
1992 // all will work out.
1993 .Case(".b", {0, 8})
1994 .Case(".h", {0, 16})
1995 .Case(".s", {0, 32})
1996 .Case(".d", {0, 64})
1997 .Default({-1, -1});
1998 break;
1999 case RegKind::SVEPredicateVector:
2000 case RegKind::SVEDataVector:
2001 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2002 .Case("", {0, 0})
2003 .Case(".b", {0, 8})
2004 .Case(".h", {0, 16})
2005 .Case(".s", {0, 32})
2006 .Case(".d", {0, 64})
2007 .Case(".q", {0, 128})
2008 .Default({-1, -1});
2009 break;
2010 default:
2011 llvm_unreachable("Unsupported RegKind");
2012 }
2013
2014 if (Res == std::make_pair(-1, -1))
2015 return Optional<std::pair<int, int>>();
2016
2017 return Optional<std::pair<int, int>>(Res);
2018}
2019
2020static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2021 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002022}
2023
Florian Hahn91f11e52017-11-07 16:45:48 +00002024static unsigned matchSVEDataVectorRegName(StringRef Name) {
2025 return StringSwitch<unsigned>(Name.lower())
2026 .Case("z0", AArch64::Z0)
2027 .Case("z1", AArch64::Z1)
2028 .Case("z2", AArch64::Z2)
2029 .Case("z3", AArch64::Z3)
2030 .Case("z4", AArch64::Z4)
2031 .Case("z5", AArch64::Z5)
2032 .Case("z6", AArch64::Z6)
2033 .Case("z7", AArch64::Z7)
2034 .Case("z8", AArch64::Z8)
2035 .Case("z9", AArch64::Z9)
2036 .Case("z10", AArch64::Z10)
2037 .Case("z11", AArch64::Z11)
2038 .Case("z12", AArch64::Z12)
2039 .Case("z13", AArch64::Z13)
2040 .Case("z14", AArch64::Z14)
2041 .Case("z15", AArch64::Z15)
2042 .Case("z16", AArch64::Z16)
2043 .Case("z17", AArch64::Z17)
2044 .Case("z18", AArch64::Z18)
2045 .Case("z19", AArch64::Z19)
2046 .Case("z20", AArch64::Z20)
2047 .Case("z21", AArch64::Z21)
2048 .Case("z22", AArch64::Z22)
2049 .Case("z23", AArch64::Z23)
2050 .Case("z24", AArch64::Z24)
2051 .Case("z25", AArch64::Z25)
2052 .Case("z26", AArch64::Z26)
2053 .Case("z27", AArch64::Z27)
2054 .Case("z28", AArch64::Z28)
2055 .Case("z29", AArch64::Z29)
2056 .Case("z30", AArch64::Z30)
2057 .Case("z31", AArch64::Z31)
2058 .Default(0);
2059}
2060
Sander de Smalencd6be962017-12-20 11:02:42 +00002061static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2062 return StringSwitch<unsigned>(Name.lower())
2063 .Case("p0", AArch64::P0)
2064 .Case("p1", AArch64::P1)
2065 .Case("p2", AArch64::P2)
2066 .Case("p3", AArch64::P3)
2067 .Case("p4", AArch64::P4)
2068 .Case("p5", AArch64::P5)
2069 .Case("p6", AArch64::P6)
2070 .Case("p7", AArch64::P7)
2071 .Case("p8", AArch64::P8)
2072 .Case("p9", AArch64::P9)
2073 .Case("p10", AArch64::P10)
2074 .Case("p11", AArch64::P11)
2075 .Case("p12", AArch64::P12)
2076 .Case("p13", AArch64::P13)
2077 .Case("p14", AArch64::P14)
2078 .Case("p15", AArch64::P15)
2079 .Default(0);
2080}
2081
Tim Northover3b0846e2014-05-24 12:50:23 +00002082bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2083 SMLoc &EndLoc) {
2084 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002085 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002086 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002087 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002088}
2089
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002090// Matches a register name or register alias previously defined by '.req'
2091unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002092 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002093 unsigned RegNum = 0;
2094 if ((RegNum = matchSVEDataVectorRegName(Name)))
2095 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2096
Sander de Smalencd6be962017-12-20 11:02:42 +00002097 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2098 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2099
Sander de Smalenc067c302017-12-20 09:45:45 +00002100 if ((RegNum = MatchNeonVectorRegName(Name)))
2101 return Kind == RegKind::NeonVector ? RegNum : 0;
2102
2103 // The parsed register must be of RegKind Scalar
2104 if ((RegNum = MatchRegisterName(Name)))
2105 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002106
Florian Hahnc4422242017-11-07 13:07:50 +00002107 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002108 // Handle a few common aliases of registers.
2109 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2110 .Case("fp", AArch64::FP)
2111 .Case("lr", AArch64::LR)
2112 .Case("x31", AArch64::XZR)
2113 .Case("w31", AArch64::WZR)
2114 .Default(0))
2115 return Kind == RegKind::Scalar ? RegNum : 0;
2116
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002117 // Check for aliases registered via .req. Canonicalize to lower case.
2118 // That's more consistent since register names are case insensitive, and
2119 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2120 auto Entry = RegisterReqs.find(Name.lower());
2121 if (Entry == RegisterReqs.end())
2122 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002123
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002124 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002125 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002126 RegNum = Entry->getValue().second;
2127 }
2128 return RegNum;
2129}
2130
Sander de Smalen50d87022018-04-19 07:35:08 +00002131/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002132/// Identifier when called, and if it is a register name the token is eaten and
2133/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002134OperandMatchResultTy
2135AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002136 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002137 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002138 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002139 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002140
2141 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002142 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2143 if (Reg == 0)
2144 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002145
Sander de Smalen50d87022018-04-19 07:35:08 +00002146 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002147 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002148 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002149}
2150
Tim Northover3b0846e2014-05-24 12:50:23 +00002151/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002152OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002153AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002154 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002155 SMLoc S = getLoc();
2156
2157 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2158 Error(S, "Expected cN operand where 0 <= N <= 15");
2159 return MatchOperand_ParseFail;
2160 }
2161
2162 StringRef Tok = Parser.getTok().getIdentifier();
2163 if (Tok[0] != 'c' && Tok[0] != 'C') {
2164 Error(S, "Expected cN operand where 0 <= N <= 15");
2165 return MatchOperand_ParseFail;
2166 }
2167
2168 uint32_t CRNum;
2169 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2170 if (BadNum || CRNum > 15) {
2171 Error(S, "Expected cN operand where 0 <= N <= 15");
2172 return MatchOperand_ParseFail;
2173 }
2174
2175 Parser.Lex(); // Eat identifier token.
2176 Operands.push_back(
2177 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2178 return MatchOperand_Success;
2179}
2180
2181/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002182template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002183OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002184AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002185 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002186 SMLoc S = getLoc();
2187 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002188
2189 auto LookupByName = [](StringRef N) {
2190 if (IsSVEPrefetch) {
2191 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2192 return Optional<unsigned>(Res->Encoding);
2193 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2194 return Optional<unsigned>(Res->Encoding);
2195 return Optional<unsigned>();
2196 };
2197
2198 auto LookupByEncoding = [](unsigned E) {
2199 if (IsSVEPrefetch) {
2200 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2201 return Optional<StringRef>(Res->Name);
2202 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2203 return Optional<StringRef>(Res->Name);
2204 return Optional<StringRef>();
2205 };
2206 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2207
Tim Northover3b0846e2014-05-24 12:50:23 +00002208 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002209 // Eat optional hash.
2210 if (parseOptionalToken(AsmToken::Hash) ||
2211 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002212 const MCExpr *ImmVal;
2213 if (getParser().parseExpression(ImmVal))
2214 return MatchOperand_ParseFail;
2215
2216 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2217 if (!MCE) {
2218 TokError("immediate value expected for prefetch operand");
2219 return MatchOperand_ParseFail;
2220 }
2221 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002222 if (prfop > MaxVal) {
2223 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2224 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002225 return MatchOperand_ParseFail;
2226 }
2227
Sander de Smalen93380372018-05-14 11:54:41 +00002228 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002229 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002230 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002231 return MatchOperand_Success;
2232 }
2233
2234 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002235 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002236 return MatchOperand_ParseFail;
2237 }
2238
Sander de Smalen93380372018-05-14 11:54:41 +00002239 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002240 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002241 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002242 return MatchOperand_ParseFail;
2243 }
2244
2245 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002246 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002247 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002248 return MatchOperand_Success;
2249}
2250
Oliver Stannarda34e4702015-12-01 10:48:51 +00002251/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002252OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002253AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2254 MCAsmParser &Parser = getParser();
2255 SMLoc S = getLoc();
2256 const AsmToken &Tok = Parser.getTok();
2257 if (Tok.isNot(AsmToken::Identifier)) {
2258 TokError("invalid operand for instruction");
2259 return MatchOperand_ParseFail;
2260 }
2261
Tim Northovere6ae6762016-07-05 21:23:04 +00002262 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2263 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002264 TokError("invalid operand for instruction");
2265 return MatchOperand_ParseFail;
2266 }
2267
2268 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002269 Operands.push_back(AArch64Operand::CreatePSBHint(
2270 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002271 return MatchOperand_Success;
2272}
2273
Tim Northover3b0846e2014-05-24 12:50:23 +00002274/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2275/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002276OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002277AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002278 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002279 SMLoc S = getLoc();
2280 const MCExpr *Expr;
2281
2282 if (Parser.getTok().is(AsmToken::Hash)) {
2283 Parser.Lex(); // Eat hash token.
2284 }
2285
2286 if (parseSymbolicImmVal(Expr))
2287 return MatchOperand_ParseFail;
2288
2289 AArch64MCExpr::VariantKind ELFRefKind;
2290 MCSymbolRefExpr::VariantKind DarwinRefKind;
2291 int64_t Addend;
2292 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2293 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2294 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2295 // No modifier was specified at all; this is the syntax for an ELF basic
2296 // ADRP relocation (unfortunately).
2297 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002298 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002299 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2300 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2301 Addend != 0) {
2302 Error(S, "gotpage label reference not allowed an addend");
2303 return MatchOperand_ParseFail;
2304 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2305 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2306 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2307 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2308 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2309 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2310 // The operand must be an @page or @gotpage qualified symbolref.
2311 Error(S, "page or gotpage label reference expected");
2312 return MatchOperand_ParseFail;
2313 }
2314 }
2315
2316 // We have either a label reference possibly with addend or an immediate. The
2317 // addend is a raw value here. The linker will adjust it to only reference the
2318 // page.
2319 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2320 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2321
2322 return MatchOperand_Success;
2323}
2324
2325/// tryParseAdrLabel - Parse and validate a source label for the ADR
2326/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002327OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002328AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2329 SMLoc S = getLoc();
2330 const MCExpr *Expr;
2331
Nirav Davee833c6c2016-11-08 18:31:04 +00002332 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002333 if (getParser().parseExpression(Expr))
2334 return MatchOperand_ParseFail;
2335
2336 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2337 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2338
2339 return MatchOperand_Success;
2340}
2341
2342/// tryParseFPImm - A floating point immediate expression operand.
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002343template<bool AddFPZeroAsLiteral>
Alex Bradbury58eba092016-11-01 16:32:05 +00002344OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002345AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002346 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002347 SMLoc S = getLoc();
2348
Nirav Davee833c6c2016-11-08 18:31:04 +00002349 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002350
2351 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002352 bool isNegative = parseOptionalToken(AsmToken::Minus);
2353
Tim Northover3b0846e2014-05-24 12:50:23 +00002354 const AsmToken &Tok = Parser.getTok();
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002355 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2356 if (!Hash)
2357 return MatchOperand_NoMatch;
2358 TokError("invalid floating point immediate");
2359 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002360 }
2361
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002362 // Parse hexadecimal representation.
2363 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2364 if (Tok.getIntVal() > 255 || isNegative) {
2365 TokError("encoded floating point value out of range");
2366 return MatchOperand_ParseFail;
2367 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002368
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002369 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2370 Operands.push_back(
2371 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2372 } else {
2373 // Parse FP representation.
2374 APFloat RealVal(APFloat::IEEEdouble());
2375 auto Status =
2376 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2377 if (isNegative)
2378 RealVal.changeSign();
2379
2380 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2381 Operands.push_back(
2382 AArch64Operand::CreateToken("#0", false, S, getContext()));
2383 Operands.push_back(
2384 AArch64Operand::CreateToken(".0", false, S, getContext()));
2385 } else
2386 Operands.push_back(AArch64Operand::CreateFPImm(
2387 RealVal, Status == APFloat::opOK, S, getContext()));
2388 }
2389
2390 Parser.Lex(); // Eat the token.
2391
2392 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002393}
2394
Sander de Smalen62770792018-05-25 09:47:52 +00002395/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2396/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002397OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002398AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002399 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002400 SMLoc S = getLoc();
2401
2402 if (Parser.getTok().is(AsmToken::Hash))
2403 Parser.Lex(); // Eat '#'
2404 else if (Parser.getTok().isNot(AsmToken::Integer))
2405 // Operand should start from # or should be integer, emit error otherwise.
2406 return MatchOperand_NoMatch;
2407
2408 const MCExpr *Imm;
2409 if (parseSymbolicImmVal(Imm))
2410 return MatchOperand_ParseFail;
2411 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002412 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002413 Operands.push_back(
2414 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002415 return MatchOperand_Success;
2416 }
2417
2418 // Eat ','
2419 Parser.Lex();
2420
2421 // The optional operand must be "lsl #N" where N is non-negative.
2422 if (!Parser.getTok().is(AsmToken::Identifier) ||
2423 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2424 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2425 return MatchOperand_ParseFail;
2426 }
2427
2428 // Eat 'lsl'
2429 Parser.Lex();
2430
Nirav Davee833c6c2016-11-08 18:31:04 +00002431 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002432
2433 if (Parser.getTok().isNot(AsmToken::Integer)) {
2434 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2435 return MatchOperand_ParseFail;
2436 }
2437
2438 int64_t ShiftAmount = Parser.getTok().getIntVal();
2439
2440 if (ShiftAmount < 0) {
2441 Error(Parser.getTok().getLoc(), "positive shift amount required");
2442 return MatchOperand_ParseFail;
2443 }
2444 Parser.Lex(); // Eat the number
2445
Sander de Smalen62770792018-05-25 09:47:52 +00002446 // Just in case the optional lsl #0 is used for immediates other than zero.
2447 if (ShiftAmount == 0 && Imm != 0) {
2448 SMLoc E = Parser.getTok().getLoc();
2449 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2450 return MatchOperand_Success;
2451 }
2452
Tim Northover3b0846e2014-05-24 12:50:23 +00002453 SMLoc E = Parser.getTok().getLoc();
2454 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2455 S, E, getContext()));
2456 return MatchOperand_Success;
2457}
2458
2459/// parseCondCodeString - Parse a Condition Code string.
2460AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2461 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2462 .Case("eq", AArch64CC::EQ)
2463 .Case("ne", AArch64CC::NE)
2464 .Case("cs", AArch64CC::HS)
2465 .Case("hs", AArch64CC::HS)
2466 .Case("cc", AArch64CC::LO)
2467 .Case("lo", AArch64CC::LO)
2468 .Case("mi", AArch64CC::MI)
2469 .Case("pl", AArch64CC::PL)
2470 .Case("vs", AArch64CC::VS)
2471 .Case("vc", AArch64CC::VC)
2472 .Case("hi", AArch64CC::HI)
2473 .Case("ls", AArch64CC::LS)
2474 .Case("ge", AArch64CC::GE)
2475 .Case("lt", AArch64CC::LT)
2476 .Case("gt", AArch64CC::GT)
2477 .Case("le", AArch64CC::LE)
2478 .Case("al", AArch64CC::AL)
2479 .Case("nv", AArch64CC::NV)
2480 .Default(AArch64CC::Invalid);
2481 return CC;
2482}
2483
2484/// parseCondCode - Parse a Condition Code operand.
2485bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2486 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002487 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002488 SMLoc S = getLoc();
2489 const AsmToken &Tok = Parser.getTok();
2490 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2491
2492 StringRef Cond = Tok.getString();
2493 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2494 if (CC == AArch64CC::Invalid)
2495 return TokError("invalid condition code");
2496 Parser.Lex(); // Eat identifier token.
2497
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002498 if (invertCondCode) {
2499 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2500 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002501 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002502 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002503
2504 Operands.push_back(
2505 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2506 return false;
2507}
2508
2509/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2510/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002511OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002512AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002513 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002514 const AsmToken &Tok = Parser.getTok();
2515 std::string LowerID = Tok.getString().lower();
2516 AArch64_AM::ShiftExtendType ShOp =
2517 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2518 .Case("lsl", AArch64_AM::LSL)
2519 .Case("lsr", AArch64_AM::LSR)
2520 .Case("asr", AArch64_AM::ASR)
2521 .Case("ror", AArch64_AM::ROR)
2522 .Case("msl", AArch64_AM::MSL)
2523 .Case("uxtb", AArch64_AM::UXTB)
2524 .Case("uxth", AArch64_AM::UXTH)
2525 .Case("uxtw", AArch64_AM::UXTW)
2526 .Case("uxtx", AArch64_AM::UXTX)
2527 .Case("sxtb", AArch64_AM::SXTB)
2528 .Case("sxth", AArch64_AM::SXTH)
2529 .Case("sxtw", AArch64_AM::SXTW)
2530 .Case("sxtx", AArch64_AM::SXTX)
2531 .Default(AArch64_AM::InvalidShiftExtend);
2532
2533 if (ShOp == AArch64_AM::InvalidShiftExtend)
2534 return MatchOperand_NoMatch;
2535
2536 SMLoc S = Tok.getLoc();
2537 Parser.Lex();
2538
Nirav Davee833c6c2016-11-08 18:31:04 +00002539 bool Hash = parseOptionalToken(AsmToken::Hash);
2540
Tim Northover3b0846e2014-05-24 12:50:23 +00002541 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2542 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2543 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2544 ShOp == AArch64_AM::MSL) {
2545 // We expect a number here.
2546 TokError("expected #imm after shift specifier");
2547 return MatchOperand_ParseFail;
2548 }
2549
Chad Rosier2ff37b82016-12-27 16:58:09 +00002550 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002551 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2552 Operands.push_back(
2553 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2554 return MatchOperand_Success;
2555 }
2556
Chad Rosier2ff37b82016-12-27 16:58:09 +00002557 // Make sure we do actually have a number, identifier or a parenthesized
2558 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002559 SMLoc E = Parser.getTok().getLoc();
2560 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002561 !Parser.getTok().is(AsmToken::LParen) &&
2562 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002563 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002564 return MatchOperand_ParseFail;
2565 }
2566
2567 const MCExpr *ImmVal;
2568 if (getParser().parseExpression(ImmVal))
2569 return MatchOperand_ParseFail;
2570
2571 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2572 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002573 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002574 return MatchOperand_ParseFail;
2575 }
2576
Jim Grosbach57fd2622014-09-23 22:16:02 +00002577 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002578 Operands.push_back(AArch64Operand::CreateShiftExtend(
2579 ShOp, MCE->getValue(), true, S, E, getContext()));
2580 return MatchOperand_Success;
2581}
2582
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002583static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2584 if (FBS[AArch64::HasV8_1aOps])
2585 Str += "ARMv8.1a";
2586 else if (FBS[AArch64::HasV8_2aOps])
2587 Str += "ARMv8.2a";
2588 else
2589 Str += "(unknown)";
2590}
2591
2592void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2593 SMLoc S) {
2594 const uint16_t Op2 = Encoding & 7;
2595 const uint16_t Cm = (Encoding & 0x78) >> 3;
2596 const uint16_t Cn = (Encoding & 0x780) >> 7;
2597 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2598
2599 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2600
2601 Operands.push_back(
2602 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2603 Operands.push_back(
2604 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2605 Operands.push_back(
2606 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2607 Expr = MCConstantExpr::create(Op2, getContext());
2608 Operands.push_back(
2609 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2610}
2611
Tim Northover3b0846e2014-05-24 12:50:23 +00002612/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2613/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2614bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2615 OperandVector &Operands) {
2616 if (Name.find('.') != StringRef::npos)
2617 return TokError("invalid operand");
2618
2619 Mnemonic = Name;
2620 Operands.push_back(
2621 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2622
Rafael Espindola961d4692014-11-11 05:18:41 +00002623 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002624 const AsmToken &Tok = Parser.getTok();
2625 StringRef Op = Tok.getString();
2626 SMLoc S = Tok.getLoc();
2627
Tim Northover3b0846e2014-05-24 12:50:23 +00002628 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002629 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2630 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002631 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002632 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2633 std::string Str("IC " + std::string(IC->Name) + " requires ");
2634 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2635 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002636 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002637 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002638 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002639 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2640 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002641 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002642 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2643 std::string Str("DC " + std::string(DC->Name) + " requires ");
2644 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2645 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002646 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002647 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002648 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002649 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2650 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002651 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002652 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2653 std::string Str("AT " + std::string(AT->Name) + " requires ");
2654 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2655 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002656 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002657 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002658 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002659 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2660 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002661 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002662 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2663 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2664 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2665 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002666 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002667 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002668 }
2669
Tim Northover3b0846e2014-05-24 12:50:23 +00002670 Parser.Lex(); // Eat operand.
2671
2672 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2673 bool HasRegister = false;
2674
2675 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002676 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002677 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2678 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002679 HasRegister = true;
2680 }
2681
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002682 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002683 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002684 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002685 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002686
Nirav Davee833c6c2016-11-08 18:31:04 +00002687 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2688 return true;
2689
Tim Northover3b0846e2014-05-24 12:50:23 +00002690 return false;
2691}
2692
Alex Bradbury58eba092016-11-01 16:32:05 +00002693OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002694AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002695 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002696 const AsmToken &Tok = Parser.getTok();
2697
2698 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002699 if (parseOptionalToken(AsmToken::Hash) ||
2700 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002701 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002702 const MCExpr *ImmVal;
2703 SMLoc ExprLoc = getLoc();
2704 if (getParser().parseExpression(ImmVal))
2705 return MatchOperand_ParseFail;
2706 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2707 if (!MCE) {
2708 Error(ExprLoc, "immediate value expected for barrier operand");
2709 return MatchOperand_ParseFail;
2710 }
2711 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2712 Error(ExprLoc, "barrier operand out of range");
2713 return MatchOperand_ParseFail;
2714 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002715 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2716 Operands.push_back(AArch64Operand::CreateBarrier(
2717 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002718 return MatchOperand_Success;
2719 }
2720
2721 if (Tok.isNot(AsmToken::Identifier)) {
2722 TokError("invalid operand for instruction");
2723 return MatchOperand_ParseFail;
2724 }
2725
Tim Northover3b0846e2014-05-24 12:50:23 +00002726 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002727 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2728 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002729 TokError("'sy' or #imm operand expected");
2730 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002731 } else if (!DB) {
2732 TokError("invalid barrier option name");
2733 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002734 }
2735
Tim Northovere6ae6762016-07-05 21:23:04 +00002736 Operands.push_back(AArch64Operand::CreateBarrier(
2737 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002738 Parser.Lex(); // Consume the option
2739
2740 return MatchOperand_Success;
2741}
2742
Alex Bradbury58eba092016-11-01 16:32:05 +00002743OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002744AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002745 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002746 const AsmToken &Tok = Parser.getTok();
2747
2748 if (Tok.isNot(AsmToken::Identifier))
2749 return MatchOperand_NoMatch;
2750
Tim Northovere6ae6762016-07-05 21:23:04 +00002751 int MRSReg, MSRReg;
2752 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2753 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2754 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2755 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2756 } else
2757 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002758
Tim Northovere6ae6762016-07-05 21:23:04 +00002759 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2760 unsigned PStateImm = -1;
2761 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2762 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002763
Tim Northovere6ae6762016-07-05 21:23:04 +00002764 Operands.push_back(
2765 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2766 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002767 Parser.Lex(); // Eat identifier
2768
2769 return MatchOperand_Success;
2770}
2771
Florian Hahnc4422242017-11-07 13:07:50 +00002772/// tryParseNeonVectorRegister - Parse a vector register operand.
2773bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002774 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002775 if (Parser.getTok().isNot(AsmToken::Identifier))
2776 return true;
2777
2778 SMLoc S = getLoc();
2779 // Check for a vector register specifier first.
2780 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002781 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002782 OperandMatchResultTy Res =
2783 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2784 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002785 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002786
2787 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2788 if (!KindRes)
2789 return true;
2790
2791 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002792 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002793 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2794 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002795
Tim Northover3b0846e2014-05-24 12:50:23 +00002796 // If there was an explicit qualifier, that goes on as a literal text
2797 // operand.
2798 if (!Kind.empty())
2799 Operands.push_back(
2800 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2801
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002802 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2803}
2804
2805OperandMatchResultTy
2806AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002807 SMLoc SIdx = getLoc();
2808 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002809 const MCExpr *ImmVal;
2810 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002811 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002812 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2813 if (!MCE) {
2814 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002815 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002816 }
2817
2818 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002819
Nirav Davee833c6c2016-11-08 18:31:04 +00002820 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002821 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002822
2823 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2824 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002825 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002826 }
2827
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002828 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002829}
2830
Sander de Smalen73937b72018-04-11 07:36:10 +00002831// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002832// optional kind specifier. If it is a register specifier, eat the token
2833// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002834OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002835AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002836 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002837 MCAsmParser &Parser = getParser();
2838 const AsmToken &Tok = Parser.getTok();
2839
Florian Hahn91f11e52017-11-07 16:45:48 +00002840 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002841 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002842
2843 StringRef Name = Tok.getString();
2844 // If there is a kind specifier, it's separated from the register name by
2845 // a '.'.
2846 size_t Start = 0, Next = Name.find('.');
2847 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002848 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002849
2850 if (RegNum) {
2851 if (Next != StringRef::npos) {
2852 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002853 if (!isValidVectorKind(Kind, MatchKind)) {
2854 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002855 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002856 }
2857 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002858 Parser.Lex(); // Eat the register token.
2859
2860 Reg = RegNum;
2861 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002862 }
2863
Sander de Smalen8e607342017-11-15 15:44:43 +00002864 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002865}
2866
Sander de Smalencd6be962017-12-20 11:02:42 +00002867/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2868OperandMatchResultTy
2869AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2870 // Check for a SVE predicate register specifier first.
2871 const SMLoc S = getLoc();
2872 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002873 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002874 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002875 if (Res != MatchOperand_Success)
2876 return Res;
2877
Sander de Smalen73937b72018-04-11 07:36:10 +00002878 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2879 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002880 return MatchOperand_NoMatch;
2881
Sander de Smalen73937b72018-04-11 07:36:10 +00002882 unsigned ElementWidth = KindRes->second;
2883 Operands.push_back(AArch64Operand::CreateVectorReg(
2884 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2885 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002886
Sander de Smalen7868e742018-01-09 11:17:06 +00002887 // Not all predicates are followed by a '/m' or '/z'.
2888 MCAsmParser &Parser = getParser();
2889 if (Parser.getTok().isNot(AsmToken::Slash))
2890 return MatchOperand_Success;
2891
2892 // But when they do they shouldn't have an element type suffix.
2893 if (!Kind.empty()) {
2894 Error(S, "not expecting size suffix");
2895 return MatchOperand_ParseFail;
2896 }
2897
2898 // Add a literal slash as operand
2899 Operands.push_back(
2900 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2901
2902 Parser.Lex(); // Eat the slash.
2903
2904 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002905 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002906 if (Pred != "z" && Pred != "m") {
2907 Error(getLoc(), "expecting 'm' or 'z' predication");
2908 return MatchOperand_ParseFail;
2909 }
2910
2911 // Add zero/merge token.
2912 const char *ZM = Pred == "z" ? "z" : "m";
2913 Operands.push_back(
2914 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2915
2916 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002917 return MatchOperand_Success;
2918}
2919
Sander de Smalen50d87022018-04-19 07:35:08 +00002920/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002921bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002922 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002923 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002924 return false;
2925
Sander de Smalen149916d2018-04-20 07:24:20 +00002926 // Otherwise try for a scalar register.
2927 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
2928 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002929
Sander de Smalen149916d2018-04-20 07:24:20 +00002930 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002931}
2932
2933bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002934 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002935 bool HasELFModifier = false;
2936 AArch64MCExpr::VariantKind RefKind;
2937
Nirav Davee833c6c2016-11-08 18:31:04 +00002938 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002939 HasELFModifier = true;
2940
Nirav Davee833c6c2016-11-08 18:31:04 +00002941 if (Parser.getTok().isNot(AsmToken::Identifier))
2942 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002943
2944 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2945 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2946 .Case("lo12", AArch64MCExpr::VK_LO12)
2947 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2948 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2949 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2950 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2951 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2952 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2953 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2954 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2955 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2956 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2957 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2958 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2959 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2960 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2961 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2962 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2963 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2964 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2965 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2966 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2967 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2968 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2969 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2970 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2971 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2972 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2973 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2974 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2975 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2976 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2977 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2978 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2979 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2980 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002981 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2982 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002983 .Default(AArch64MCExpr::VK_INVALID);
2984
Nirav Davee833c6c2016-11-08 18:31:04 +00002985 if (RefKind == AArch64MCExpr::VK_INVALID)
2986 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002987
2988 Parser.Lex(); // Eat identifier
2989
Nirav Davee833c6c2016-11-08 18:31:04 +00002990 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002991 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002992 }
2993
2994 if (getParser().parseExpression(ImmVal))
2995 return true;
2996
2997 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002998 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002999
3000 return false;
3001}
3002
Sander de Smalen650234b2018-04-12 11:40:52 +00003003template <RegKind VectorKind>
3004OperandMatchResultTy
3005AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3006 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003007 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003008 if (!Parser.getTok().is(AsmToken::LCurly))
3009 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003010
3011 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003012 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003013 bool NoMatchIsError) {
3014 auto RegTok = Parser.getTok();
3015 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3016 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003017 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003018 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003019 llvm_unreachable("Expected a valid vector kind");
3020 }
3021
Sander de Smalen650234b2018-04-12 11:40:52 +00003022 if (RegTok.isNot(AsmToken::Identifier) ||
3023 ParseRes == MatchOperand_ParseFail ||
3024 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3025 Error(Loc, "vector register expected");
3026 return MatchOperand_ParseFail;
3027 }
3028
3029 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003030 };
3031
Tim Northover3b0846e2014-05-24 12:50:23 +00003032 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003033 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003034 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003035
Tim Northover3b0846e2014-05-24 12:50:23 +00003036 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003037 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003038 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3039
3040 // Put back the original left bracket if there was no match, so that
3041 // different types of list-operands can be matched (e.g. SVE, Neon).
3042 if (ParseRes == MatchOperand_NoMatch)
3043 Parser.getLexer().UnLex(LCurly);
3044
3045 if (ParseRes != MatchOperand_Success)
3046 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003047
Tim Northover3b0846e2014-05-24 12:50:23 +00003048 int64_t PrevReg = FirstReg;
3049 unsigned Count = 1;
3050
Nirav Davee833c6c2016-11-08 18:31:04 +00003051 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003052 SMLoc Loc = getLoc();
3053 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003054
Sander de Smalen50d87022018-04-19 07:35:08 +00003055 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003056 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3057 if (ParseRes != MatchOperand_Success)
3058 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003059
Tim Northover3b0846e2014-05-24 12:50:23 +00003060 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003061 if (Kind != NextKind) {
3062 Error(Loc, "mismatched register size suffix");
3063 return MatchOperand_ParseFail;
3064 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003065
3066 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3067
3068 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003069 Error(Loc, "invalid number of vectors");
3070 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003071 }
3072
3073 Count += Space;
3074 }
3075 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003076 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003077 SMLoc Loc = getLoc();
3078 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003079 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003080 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3081 if (ParseRes != MatchOperand_Success)
3082 return ParseRes;
3083
Tim Northover3b0846e2014-05-24 12:50:23 +00003084 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003085 if (Kind != NextKind) {
3086 Error(Loc, "mismatched register size suffix");
3087 return MatchOperand_ParseFail;
3088 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003089
3090 // Registers must be incremental (with wraparound at 31)
3091 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003092 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3093 Error(Loc, "registers must be sequential");
3094 return MatchOperand_ParseFail;
3095 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003096
3097 PrevReg = Reg;
3098 ++Count;
3099 }
3100 }
3101
Nirav Davee833c6c2016-11-08 18:31:04 +00003102 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003103 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003104
Sander de Smalen650234b2018-04-12 11:40:52 +00003105 if (Count > 4) {
3106 Error(S, "invalid number of vectors");
3107 return MatchOperand_ParseFail;
3108 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003109
3110 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003111 unsigned ElementWidth = 0;
3112 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003113 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003114 std::tie(NumElements, ElementWidth) = *VK;
3115 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003116
3117 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003118 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3119 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003120
Sander de Smalen650234b2018-04-12 11:40:52 +00003121 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003122}
3123
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003124/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3125bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003126 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3127 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003128 return true;
3129
3130 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3131}
3132
Alex Bradbury58eba092016-11-01 16:32:05 +00003133OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003134AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003135 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003136
Sander de Smalen50d87022018-04-19 07:35:08 +00003137 unsigned RegNum;
3138 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3139 if (Res != MatchOperand_Success)
3140 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003141
Nirav Davee833c6c2016-11-08 18:31:04 +00003142 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003143 Operands.push_back(AArch64Operand::CreateReg(
3144 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003145 return MatchOperand_Success;
3146 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003147
Nirav Davee833c6c2016-11-08 18:31:04 +00003148 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003149
Sander de Smalen50d87022018-04-19 07:35:08 +00003150 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003151 Error(getLoc(), "index must be absent or #0");
3152 return MatchOperand_ParseFail;
3153 }
3154
3155 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003156 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003157 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3158 Error(getLoc(), "index must be absent or #0");
3159 return MatchOperand_ParseFail;
3160 }
3161
Sander de Smalen50d87022018-04-19 07:35:08 +00003162 Operands.push_back(AArch64Operand::CreateReg(
3163 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003164 return MatchOperand_Success;
3165}
3166
Sander de Smalen149916d2018-04-20 07:24:20 +00003167template <bool ParseShiftExtend>
3168OperandMatchResultTy
3169AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3170 SMLoc StartLoc = getLoc();
3171
3172 unsigned RegNum;
3173 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3174 if (Res != MatchOperand_Success)
3175 return Res;
3176
3177 // No shift/extend is the default.
3178 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3179 Operands.push_back(AArch64Operand::CreateReg(
3180 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
3181 return MatchOperand_Success;
3182 }
3183
3184 // Eat the comma
3185 getParser().Lex();
3186
3187 // Match the shift
3188 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3189 Res = tryParseOptionalShiftExtend(ExtOpnd);
3190 if (Res != MatchOperand_Success)
3191 return Res;
3192
3193 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
3194 Operands.push_back(AArch64Operand::CreateReg(RegNum, RegKind::Scalar,
3195 StartLoc, Ext->getEndLoc(), getContext(),
3196 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3197 Ext->hasShiftExtendAmount()));
3198
3199 return MatchOperand_Success;
3200}
3201
Sander de Smalen5c625982018-04-13 12:56:14 +00003202bool AArch64AsmParser::parseOptionalMulVl(OperandVector &Operands) {
3203 MCAsmParser &Parser = getParser();
3204
3205 // Some SVE instructions have a decoration after the immediate, i.e.
3206 // "mul vl". We parse them here and add tokens, which must be present in the
3207 // asm string in the tablegen instruction.
3208 if (!Parser.getTok().getString().equals_lower("mul") ||
3209 !Parser.getLexer().peekTok().getString().equals_lower("vl"))
3210 return true;
3211
3212 SMLoc S = getLoc();
3213 Operands.push_back(
3214 AArch64Operand::CreateToken("mul", false, S, getContext()));
3215 Parser.Lex(); // Eat the "mul"
3216
3217 S = getLoc();
3218 Operands.push_back(
3219 AArch64Operand::CreateToken("vl", false, S, getContext()));
3220 Parser.Lex(); // Eat the "vl"
3221
3222 return false;
3223}
3224
Tim Northover3b0846e2014-05-24 12:50:23 +00003225/// parseOperand - Parse a arm instruction operand. For now this parses the
3226/// operand regardless of the mnemonic.
3227bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3228 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003229 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003230
3231 OperandMatchResultTy ResTy =
3232 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3233
Tim Northover3b0846e2014-05-24 12:50:23 +00003234 // Check if the current operand has a custom associated parser, if so, try to
3235 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003236 if (ResTy == MatchOperand_Success)
3237 return false;
3238 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3239 // there was a match, but an error occurred, in which case, just return that
3240 // the operand parsing failed.
3241 if (ResTy == MatchOperand_ParseFail)
3242 return true;
3243
3244 // Nothing custom, so do general case parsing.
3245 SMLoc S, E;
3246 switch (getLexer().getKind()) {
3247 default: {
3248 SMLoc S = getLoc();
3249 const MCExpr *Expr;
3250 if (parseSymbolicImmVal(Expr))
3251 return Error(S, "invalid operand");
3252
3253 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3254 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3255 return false;
3256 }
3257 case AsmToken::LBrac: {
3258 SMLoc Loc = Parser.getTok().getLoc();
3259 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3260 getContext()));
3261 Parser.Lex(); // Eat '['
3262
3263 // There's no comma after a '[', so we can parse the next operand
3264 // immediately.
3265 return parseOperand(Operands, false, false);
3266 }
3267 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003268 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003269 case AsmToken::Identifier: {
3270 // If we're expecting a Condition Code operand, then just parse that.
3271 if (isCondCode)
3272 return parseCondCode(Operands, invertCondCode);
3273
3274 // If it's a register name, parse it.
3275 if (!parseRegister(Operands))
3276 return false;
3277
Sander de Smalen5c625982018-04-13 12:56:14 +00003278 // See if this is a "mul vl" decoration used by SVE instructions.
3279 if (!parseOptionalMulVl(Operands))
3280 return false;
3281
Tim Northover3b0846e2014-05-24 12:50:23 +00003282 // This could be an optional "shift" or "extend" operand.
3283 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3284 // We can only continue if no tokens were eaten.
3285 if (GotShift != MatchOperand_NoMatch)
3286 return GotShift;
3287
3288 // This was not a register so parse other operands that start with an
3289 // identifier (like labels) as expressions and create them as immediates.
3290 const MCExpr *IdVal;
3291 S = getLoc();
3292 if (getParser().parseExpression(IdVal))
3293 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003294 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3295 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3296 return false;
3297 }
3298 case AsmToken::Integer:
3299 case AsmToken::Real:
3300 case AsmToken::Hash: {
3301 // #42 -> immediate.
3302 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003303
3304 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003305
3306 // Parse a negative sign
3307 bool isNegative = false;
3308 if (Parser.getTok().is(AsmToken::Minus)) {
3309 isNegative = true;
3310 // We need to consume this token only when we have a Real, otherwise
3311 // we let parseSymbolicImmVal take care of it
3312 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3313 Parser.Lex();
3314 }
3315
3316 // The only Real that should come through here is a literal #0.0 for
3317 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3318 // so convert the value.
3319 const AsmToken &Tok = Parser.getTok();
3320 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003321 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003322 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3323 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3324 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3325 Mnemonic != "fcmlt")
3326 return TokError("unexpected floating point literal");
3327 else if (IntVal != 0 || isNegative)
3328 return TokError("expected floating-point constant #0.0");
3329 Parser.Lex(); // Eat the token.
3330
3331 Operands.push_back(
3332 AArch64Operand::CreateToken("#0", false, S, getContext()));
3333 Operands.push_back(
3334 AArch64Operand::CreateToken(".0", false, S, getContext()));
3335 return false;
3336 }
3337
3338 const MCExpr *ImmVal;
3339 if (parseSymbolicImmVal(ImmVal))
3340 return true;
3341
3342 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3343 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3344 return false;
3345 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003346 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003347 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003348 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003349 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003350 Parser.Lex(); // Eat '='
3351 const MCExpr *SubExprVal;
3352 if (getParser().parseExpression(SubExprVal))
3353 return true;
3354
David Peixottoae5ba762014-07-18 16:05:14 +00003355 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003356 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003357 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003358
3359 bool IsXReg =
3360 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3361 Operands[1]->getReg());
3362
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003363 MCContext& Ctx = getContext();
3364 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3365 // 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 +00003366 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003367 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3368 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3369 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3370 ShiftAmt += 16;
3371 Imm >>= 16;
3372 }
3373 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3374 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3375 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003376 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003377 if (ShiftAmt)
3378 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3379 ShiftAmt, true, S, E, Ctx));
3380 return false;
3381 }
David Peixottoae5ba762014-07-18 16:05:14 +00003382 APInt Simm = APInt(64, Imm << ShiftAmt);
3383 // check if the immediate is an unsigned or signed 32-bit int for W regs
3384 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3385 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003386 }
3387 // 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 +00003388 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003389 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003390 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3391 return false;
3392 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003393 }
3394}
3395
3396/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3397/// operands.
3398bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3399 StringRef Name, SMLoc NameLoc,
3400 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003401 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003402 Name = StringSwitch<StringRef>(Name.lower())
3403 .Case("beq", "b.eq")
3404 .Case("bne", "b.ne")
3405 .Case("bhs", "b.hs")
3406 .Case("bcs", "b.cs")
3407 .Case("blo", "b.lo")
3408 .Case("bcc", "b.cc")
3409 .Case("bmi", "b.mi")
3410 .Case("bpl", "b.pl")
3411 .Case("bvs", "b.vs")
3412 .Case("bvc", "b.vc")
3413 .Case("bhi", "b.hi")
3414 .Case("bls", "b.ls")
3415 .Case("bge", "b.ge")
3416 .Case("blt", "b.lt")
3417 .Case("bgt", "b.gt")
3418 .Case("ble", "b.le")
3419 .Case("bal", "b.al")
3420 .Case("bnv", "b.nv")
3421 .Default(Name);
3422
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003423 // First check for the AArch64-specific .req directive.
3424 if (Parser.getTok().is(AsmToken::Identifier) &&
3425 Parser.getTok().getIdentifier() == ".req") {
3426 parseDirectiveReq(Name, NameLoc);
3427 // We always return 'error' for this, as we're done with this
3428 // statement and don't need to match the 'instruction."
3429 return true;
3430 }
3431
Tim Northover3b0846e2014-05-24 12:50:23 +00003432 // Create the leading tokens for the mnemonic, split by '.' characters.
3433 size_t Start = 0, Next = Name.find('.');
3434 StringRef Head = Name.slice(Start, Next);
3435
3436 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003437 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3438 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003439
3440 Operands.push_back(
3441 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3442 Mnemonic = Head;
3443
3444 // Handle condition codes for a branch mnemonic
3445 if (Head == "b" && Next != StringRef::npos) {
3446 Start = Next;
3447 Next = Name.find('.', Start + 1);
3448 Head = Name.slice(Start + 1, Next);
3449
3450 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3451 (Head.data() - Name.data()));
3452 AArch64CC::CondCode CC = parseCondCodeString(Head);
3453 if (CC == AArch64CC::Invalid)
3454 return Error(SuffixLoc, "invalid condition code");
3455 Operands.push_back(
3456 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3457 Operands.push_back(
3458 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3459 }
3460
3461 // Add the remaining tokens in the mnemonic.
3462 while (Next != StringRef::npos) {
3463 Start = Next;
3464 Next = Name.find('.', Start + 1);
3465 Head = Name.slice(Start, Next);
3466 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3467 (Head.data() - Name.data()) + 1);
3468 Operands.push_back(
3469 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3470 }
3471
3472 // Conditional compare instructions have a Condition Code operand, which needs
3473 // to be parsed and an immediate operand created.
3474 bool condCodeFourthOperand =
3475 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3476 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3477 Head == "csinc" || Head == "csinv" || Head == "csneg");
3478
3479 // These instructions are aliases to some of the conditional select
3480 // instructions. However, the condition code is inverted in the aliased
3481 // instruction.
3482 //
3483 // FIXME: Is this the correct way to handle these? Or should the parser
3484 // generate the aliased instructions directly?
3485 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3486 bool condCodeThirdOperand =
3487 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3488
3489 // Read the remaining operands.
3490 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3491 // Read the first operand.
3492 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003493 return true;
3494 }
3495
3496 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003497 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003498 // Parse and remember the operand.
3499 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3500 (N == 3 && condCodeThirdOperand) ||
3501 (N == 2 && condCodeSecondOperand),
3502 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003503 return true;
3504 }
3505
3506 // After successfully parsing some operands there are two special cases to
3507 // consider (i.e. notional operands not separated by commas). Both are due
3508 // to memory specifiers:
3509 // + An RBrac will end an address for load/store/prefetch
3510 // + An '!' will indicate a pre-indexed operation.
3511 //
3512 // It's someone else's responsibility to make sure these tokens are sane
3513 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003514
Nirav Davee833c6c2016-11-08 18:31:04 +00003515 SMLoc RLoc = Parser.getTok().getLoc();
3516 if (parseOptionalToken(AsmToken::RBrac))
3517 Operands.push_back(
3518 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3519 SMLoc ELoc = Parser.getTok().getLoc();
3520 if (parseOptionalToken(AsmToken::Exclaim))
3521 Operands.push_back(
3522 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003523
3524 ++N;
3525 }
3526 }
3527
Nirav Davee833c6c2016-11-08 18:31:04 +00003528 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3529 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003530
Tim Northover3b0846e2014-05-24 12:50:23 +00003531 return false;
3532}
3533
3534// FIXME: This entire function is a giant hack to provide us with decent
3535// operand range validation/diagnostics until TableGen/MC can be extended
3536// to support autogeneration of this kind of validation.
3537bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3538 SmallVectorImpl<SMLoc> &Loc) {
3539 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3540 // Check for indexed addressing modes w/ the base register being the
3541 // same as a destination/source register or pair load where
3542 // the Rt == Rt2. All of those are undefined behaviour.
3543 switch (Inst.getOpcode()) {
3544 case AArch64::LDPSWpre:
3545 case AArch64::LDPWpost:
3546 case AArch64::LDPWpre:
3547 case AArch64::LDPXpost:
3548 case AArch64::LDPXpre: {
3549 unsigned Rt = Inst.getOperand(1).getReg();
3550 unsigned Rt2 = Inst.getOperand(2).getReg();
3551 unsigned Rn = Inst.getOperand(3).getReg();
3552 if (RI->isSubRegisterEq(Rn, Rt))
3553 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3554 "is also a destination");
3555 if (RI->isSubRegisterEq(Rn, Rt2))
3556 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3557 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003558 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003559 }
3560 case AArch64::LDPDi:
3561 case AArch64::LDPQi:
3562 case AArch64::LDPSi:
3563 case AArch64::LDPSWi:
3564 case AArch64::LDPWi:
3565 case AArch64::LDPXi: {
3566 unsigned Rt = Inst.getOperand(0).getReg();
3567 unsigned Rt2 = Inst.getOperand(1).getReg();
3568 if (Rt == Rt2)
3569 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3570 break;
3571 }
3572 case AArch64::LDPDpost:
3573 case AArch64::LDPDpre:
3574 case AArch64::LDPQpost:
3575 case AArch64::LDPQpre:
3576 case AArch64::LDPSpost:
3577 case AArch64::LDPSpre:
3578 case AArch64::LDPSWpost: {
3579 unsigned Rt = Inst.getOperand(1).getReg();
3580 unsigned Rt2 = Inst.getOperand(2).getReg();
3581 if (Rt == Rt2)
3582 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3583 break;
3584 }
3585 case AArch64::STPDpost:
3586 case AArch64::STPDpre:
3587 case AArch64::STPQpost:
3588 case AArch64::STPQpre:
3589 case AArch64::STPSpost:
3590 case AArch64::STPSpre:
3591 case AArch64::STPWpost:
3592 case AArch64::STPWpre:
3593 case AArch64::STPXpost:
3594 case AArch64::STPXpre: {
3595 unsigned Rt = Inst.getOperand(1).getReg();
3596 unsigned Rt2 = Inst.getOperand(2).getReg();
3597 unsigned Rn = Inst.getOperand(3).getReg();
3598 if (RI->isSubRegisterEq(Rn, Rt))
3599 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3600 "is also a source");
3601 if (RI->isSubRegisterEq(Rn, Rt2))
3602 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3603 "is also a source");
3604 break;
3605 }
3606 case AArch64::LDRBBpre:
3607 case AArch64::LDRBpre:
3608 case AArch64::LDRHHpre:
3609 case AArch64::LDRHpre:
3610 case AArch64::LDRSBWpre:
3611 case AArch64::LDRSBXpre:
3612 case AArch64::LDRSHWpre:
3613 case AArch64::LDRSHXpre:
3614 case AArch64::LDRSWpre:
3615 case AArch64::LDRWpre:
3616 case AArch64::LDRXpre:
3617 case AArch64::LDRBBpost:
3618 case AArch64::LDRBpost:
3619 case AArch64::LDRHHpost:
3620 case AArch64::LDRHpost:
3621 case AArch64::LDRSBWpost:
3622 case AArch64::LDRSBXpost:
3623 case AArch64::LDRSHWpost:
3624 case AArch64::LDRSHXpost:
3625 case AArch64::LDRSWpost:
3626 case AArch64::LDRWpost:
3627 case AArch64::LDRXpost: {
3628 unsigned Rt = Inst.getOperand(1).getReg();
3629 unsigned Rn = Inst.getOperand(2).getReg();
3630 if (RI->isSubRegisterEq(Rn, Rt))
3631 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3632 "is also a source");
3633 break;
3634 }
3635 case AArch64::STRBBpost:
3636 case AArch64::STRBpost:
3637 case AArch64::STRHHpost:
3638 case AArch64::STRHpost:
3639 case AArch64::STRWpost:
3640 case AArch64::STRXpost:
3641 case AArch64::STRBBpre:
3642 case AArch64::STRBpre:
3643 case AArch64::STRHHpre:
3644 case AArch64::STRHpre:
3645 case AArch64::STRWpre:
3646 case AArch64::STRXpre: {
3647 unsigned Rt = Inst.getOperand(1).getReg();
3648 unsigned Rn = Inst.getOperand(2).getReg();
3649 if (RI->isSubRegisterEq(Rn, Rt))
3650 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3651 "is also a source");
3652 break;
3653 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003654 case AArch64::STXRB:
3655 case AArch64::STXRH:
3656 case AArch64::STXRW:
3657 case AArch64::STXRX:
3658 case AArch64::STLXRB:
3659 case AArch64::STLXRH:
3660 case AArch64::STLXRW:
3661 case AArch64::STLXRX: {
3662 unsigned Rs = Inst.getOperand(0).getReg();
3663 unsigned Rt = Inst.getOperand(1).getReg();
3664 unsigned Rn = Inst.getOperand(2).getReg();
3665 if (RI->isSubRegisterEq(Rt, Rs) ||
3666 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3667 return Error(Loc[0],
3668 "unpredictable STXR instruction, status is also a source");
3669 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003670 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003671 case AArch64::STXPW:
3672 case AArch64::STXPX:
3673 case AArch64::STLXPW:
3674 case AArch64::STLXPX: {
3675 unsigned Rs = Inst.getOperand(0).getReg();
3676 unsigned Rt1 = Inst.getOperand(1).getReg();
3677 unsigned Rt2 = Inst.getOperand(2).getReg();
3678 unsigned Rn = Inst.getOperand(3).getReg();
3679 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3680 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3681 return Error(Loc[0],
3682 "unpredictable STXP instruction, status is also a source");
3683 break;
3684 }
3685 }
3686
Tim Northover3b0846e2014-05-24 12:50:23 +00003687
3688 // Now check immediate ranges. Separate from the above as there is overlap
3689 // in the instructions being checked and this keeps the nested conditionals
3690 // to a minimum.
3691 switch (Inst.getOpcode()) {
3692 case AArch64::ADDSWri:
3693 case AArch64::ADDSXri:
3694 case AArch64::ADDWri:
3695 case AArch64::ADDXri:
3696 case AArch64::SUBSWri:
3697 case AArch64::SUBSXri:
3698 case AArch64::SUBWri:
3699 case AArch64::SUBXri: {
3700 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3701 // some slight duplication here.
3702 if (Inst.getOperand(2).isExpr()) {
3703 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3704 AArch64MCExpr::VariantKind ELFRefKind;
3705 MCSymbolRefExpr::VariantKind DarwinRefKind;
3706 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003707 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3708
3709 // Only allow these with ADDXri.
3710 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3711 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3712 Inst.getOpcode() == AArch64::ADDXri)
3713 return false;
3714
3715 // Only allow these with ADDXri/ADDWri
3716 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3717 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3718 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3719 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3720 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3721 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3722 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003723 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3724 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3725 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003726 (Inst.getOpcode() == AArch64::ADDXri ||
3727 Inst.getOpcode() == AArch64::ADDWri))
3728 return false;
3729
3730 // Don't allow symbol refs in the immediate field otherwise
3731 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3732 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3733 // 'cmp w0, 'borked')
3734 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003735 }
Diana Picusc93518d2016-10-11 09:17:47 +00003736 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003737 }
3738 return false;
3739 }
3740 default:
3741 return false;
3742 }
3743}
3744
Craig Topper05515562017-10-26 06:46:41 +00003745static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3746 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003747
3748bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3749 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003750 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003751 case Match_InvalidTiedOperand:
3752 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003753 case Match_MissingFeature:
3754 return Error(Loc,
3755 "instruction requires a CPU feature not currently enabled");
3756 case Match_InvalidOperand:
3757 return Error(Loc, "invalid operand for instruction");
3758 case Match_InvalidSuffix:
3759 return Error(Loc, "invalid type suffix for instruction");
3760 case Match_InvalidCondCode:
3761 return Error(Loc, "expected AArch64 condition code");
3762 case Match_AddSubRegExtendSmall:
3763 return Error(Loc,
3764 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3765 case Match_AddSubRegExtendLarge:
3766 return Error(Loc,
3767 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3768 case Match_AddSubSecondSource:
3769 return Error(Loc,
3770 "expected compatible register, symbol or integer in range [0, 4095]");
3771 case Match_LogicalSecondSource:
3772 return Error(Loc, "expected compatible register or logical immediate");
3773 case Match_InvalidMovImm32Shift:
3774 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3775 case Match_InvalidMovImm64Shift:
3776 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3777 case Match_AddSubRegShift32:
3778 return Error(Loc,
3779 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3780 case Match_AddSubRegShift64:
3781 return Error(Loc,
3782 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3783 case Match_InvalidFPImm:
3784 return Error(Loc,
3785 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003786 case Match_InvalidMemoryIndexedSImm6:
3787 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003788 case Match_InvalidMemoryIndexedSImm5:
3789 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003790 case Match_InvalidMemoryIndexed1SImm4:
3791 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003792 case Match_InvalidMemoryIndexed2SImm4:
3793 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003794 case Match_InvalidMemoryIndexed3SImm4:
3795 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003796 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00003797 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00003798 case Match_InvalidMemoryIndexed16SImm4:
3799 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00003800 case Match_InvalidMemoryIndexed1SImm6:
3801 return Error(Loc, "index must be an integer in range [-32, 31].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003802 case Match_InvalidMemoryIndexedSImm9:
3803 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00003804 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00003805 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003806 case Match_InvalidMemoryIndexed4SImm7:
3807 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3808 case Match_InvalidMemoryIndexed8SImm7:
3809 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3810 case Match_InvalidMemoryIndexed16SImm7:
3811 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00003812 case Match_InvalidMemoryIndexed8UImm5:
3813 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
3814 case Match_InvalidMemoryIndexed4UImm5:
3815 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
3816 case Match_InvalidMemoryIndexed2UImm5:
3817 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00003818 case Match_InvalidMemoryIndexed8UImm6:
3819 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
3820 case Match_InvalidMemoryIndexed4UImm6:
3821 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
3822 case Match_InvalidMemoryIndexed2UImm6:
3823 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
3824 case Match_InvalidMemoryIndexed1UImm6:
3825 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003826 case Match_InvalidMemoryWExtend8:
3827 return Error(Loc,
3828 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3829 case Match_InvalidMemoryWExtend16:
3830 return Error(Loc,
3831 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3832 case Match_InvalidMemoryWExtend32:
3833 return Error(Loc,
3834 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3835 case Match_InvalidMemoryWExtend64:
3836 return Error(Loc,
3837 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3838 case Match_InvalidMemoryWExtend128:
3839 return Error(Loc,
3840 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3841 case Match_InvalidMemoryXExtend8:
3842 return Error(Loc,
3843 "expected 'lsl' or 'sxtx' with optional shift of #0");
3844 case Match_InvalidMemoryXExtend16:
3845 return Error(Loc,
3846 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3847 case Match_InvalidMemoryXExtend32:
3848 return Error(Loc,
3849 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3850 case Match_InvalidMemoryXExtend64:
3851 return Error(Loc,
3852 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3853 case Match_InvalidMemoryXExtend128:
3854 return Error(Loc,
3855 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3856 case Match_InvalidMemoryIndexed1:
3857 return Error(Loc, "index must be an integer in range [0, 4095].");
3858 case Match_InvalidMemoryIndexed2:
3859 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3860 case Match_InvalidMemoryIndexed4:
3861 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3862 case Match_InvalidMemoryIndexed8:
3863 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3864 case Match_InvalidMemoryIndexed16:
3865 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003866 case Match_InvalidImm0_1:
3867 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003868 case Match_InvalidImm0_7:
3869 return Error(Loc, "immediate must be an integer in range [0, 7].");
3870 case Match_InvalidImm0_15:
3871 return Error(Loc, "immediate must be an integer in range [0, 15].");
3872 case Match_InvalidImm0_31:
3873 return Error(Loc, "immediate must be an integer in range [0, 31].");
3874 case Match_InvalidImm0_63:
3875 return Error(Loc, "immediate must be an integer in range [0, 63].");
3876 case Match_InvalidImm0_127:
3877 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003878 case Match_InvalidImm0_255:
3879 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003880 case Match_InvalidImm0_65535:
3881 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3882 case Match_InvalidImm1_8:
3883 return Error(Loc, "immediate must be an integer in range [1, 8].");
3884 case Match_InvalidImm1_16:
3885 return Error(Loc, "immediate must be an integer in range [1, 16].");
3886 case Match_InvalidImm1_32:
3887 return Error(Loc, "immediate must be an integer in range [1, 32].");
3888 case Match_InvalidImm1_64:
3889 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00003890 case Match_InvalidSVEAddSubImm8:
3891 return Error(Loc, "immediate must be an integer in range [0, 255]"
3892 " with a shift amount of 0");
3893 case Match_InvalidSVEAddSubImm16:
3894 case Match_InvalidSVEAddSubImm32:
3895 case Match_InvalidSVEAddSubImm64:
3896 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
3897 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00003898 case Match_InvalidSVECpyImm8:
3899 return Error(Loc, "immediate must be an integer in range [-128, 255]"
3900 " with a shift amount of 0");
3901 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00003902 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
3903 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00003904 case Match_InvalidSVECpyImm32:
3905 case Match_InvalidSVECpyImm64:
3906 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
3907 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003908 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00003909 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003910 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00003911 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003912 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00003913 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003914 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00003915 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003916 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00003917 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00003918 case Match_InvalidSVEIndexRange0_63:
3919 return Error(Loc, "vector lane must be an integer in range [0, 63].");
3920 case Match_InvalidSVEIndexRange0_31:
3921 return Error(Loc, "vector lane must be an integer in range [0, 31].");
3922 case Match_InvalidSVEIndexRange0_15:
3923 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3924 case Match_InvalidSVEIndexRange0_7:
3925 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3926 case Match_InvalidSVEIndexRange0_3:
3927 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003928 case Match_InvalidLabel:
3929 return Error(Loc, "expected label or encodable integer pc offset");
3930 case Match_MRS:
3931 return Error(Loc, "expected readable system register");
3932 case Match_MSR:
3933 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003934 case Match_InvalidComplexRotationEven:
3935 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3936 case Match_InvalidComplexRotationOdd:
3937 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003938 case Match_MnemonicFail: {
3939 std::string Suggestion = AArch64MnemonicSpellCheck(
3940 ((AArch64Operand &)*Operands[0]).getToken(),
3941 ComputeAvailableFeatures(STI->getFeatureBits()));
3942 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3943 }
Sander de Smalen367694b2018-04-20 08:54:49 +00003944 case Match_InvalidGPR64shifted8:
3945 return Error(Loc, "register must be x0..x30 or xzr, without shift");
3946 case Match_InvalidGPR64shifted16:
3947 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
3948 case Match_InvalidGPR64shifted32:
3949 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
3950 case Match_InvalidGPR64shifted64:
3951 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
3952 case Match_InvalidGPR64NoXZRshifted8:
3953 return Error(Loc, "register must be x0..x30 without shift");
3954 case Match_InvalidGPR64NoXZRshifted16:
3955 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
3956 case Match_InvalidGPR64NoXZRshifted32:
3957 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
3958 case Match_InvalidGPR64NoXZRshifted64:
3959 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00003960 case Match_InvalidZPR32UXTW8:
3961 case Match_InvalidZPR32SXTW8:
3962 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
3963 case Match_InvalidZPR32UXTW16:
3964 case Match_InvalidZPR32SXTW16:
3965 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
3966 case Match_InvalidZPR32UXTW32:
3967 case Match_InvalidZPR32SXTW32:
3968 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
3969 case Match_InvalidZPR32UXTW64:
3970 case Match_InvalidZPR32SXTW64:
3971 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
3972 case Match_InvalidZPR64UXTW8:
3973 case Match_InvalidZPR64SXTW8:
3974 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
3975 case Match_InvalidZPR64UXTW16:
3976 case Match_InvalidZPR64SXTW16:
3977 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
3978 case Match_InvalidZPR64UXTW32:
3979 case Match_InvalidZPR64SXTW32:
3980 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
3981 case Match_InvalidZPR64UXTW64:
3982 case Match_InvalidZPR64SXTW64:
3983 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
3984 case Match_InvalidZPR64LSL8:
3985 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
3986 case Match_InvalidZPR64LSL16:
3987 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
3988 case Match_InvalidZPR64LSL32:
3989 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
3990 case Match_InvalidZPR64LSL64:
3991 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00003992 case Match_InvalidZPR0:
3993 return Error(Loc, "expected register without element width sufix");
3994 case Match_InvalidZPR8:
3995 case Match_InvalidZPR16:
3996 case Match_InvalidZPR32:
3997 case Match_InvalidZPR64:
3998 case Match_InvalidZPR128:
3999 return Error(Loc, "invalid element width");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004000 case Match_InvalidSVEPattern:
4001 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004002 case Match_InvalidSVEPredicateAnyReg:
4003 case Match_InvalidSVEPredicateBReg:
4004 case Match_InvalidSVEPredicateHReg:
4005 case Match_InvalidSVEPredicateSReg:
4006 case Match_InvalidSVEPredicateDReg:
4007 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004008 case Match_InvalidSVEPredicate3bAnyReg:
4009 case Match_InvalidSVEPredicate3bBReg:
4010 case Match_InvalidSVEPredicate3bHReg:
4011 case Match_InvalidSVEPredicate3bSReg:
4012 case Match_InvalidSVEPredicate3bDReg:
4013 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004014 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004015 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004016 }
4017}
4018
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004019static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004020
4021bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4022 OperandVector &Operands,
4023 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004024 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004025 bool MatchingInlineAsm) {
4026 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004027 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4028 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004029
David Blaikie960ea3f2014-06-08 16:18:35 +00004030 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004031 unsigned NumOperands = Operands.size();
4032
4033 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004034 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4035 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004036 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004037 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004038 if (Op3CE) {
4039 uint64_t Op3Val = Op3CE->getValue();
4040 uint64_t NewOp3Val = 0;
4041 uint64_t NewOp4Val = 0;
4042 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004043 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004044 NewOp3Val = (32 - Op3Val) & 0x1f;
4045 NewOp4Val = 31 - Op3Val;
4046 } else {
4047 NewOp3Val = (64 - Op3Val) & 0x3f;
4048 NewOp4Val = 63 - Op3Val;
4049 }
4050
Jim Grosbach13760bd2015-05-30 01:25:56 +00004051 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4052 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004053
4054 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004055 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004056 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004057 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4058 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4059 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004060 }
4061 }
Tim Northover03b99f62015-04-30 18:28:58 +00004062 } else if (NumOperands == 4 && Tok == "bfc") {
4063 // FIXME: Horrible hack to handle BFC->BFM alias.
4064 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4065 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4066 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4067
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004068 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004069 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4070 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4071
4072 if (LSBCE && WidthCE) {
4073 uint64_t LSB = LSBCE->getValue();
4074 uint64_t Width = WidthCE->getValue();
4075
4076 uint64_t RegWidth = 0;
4077 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4078 Op1.getReg()))
4079 RegWidth = 64;
4080 else
4081 RegWidth = 32;
4082
4083 if (LSB >= RegWidth)
4084 return Error(LSBOp.getStartLoc(),
4085 "expected integer in range [0, 31]");
4086 if (Width < 1 || Width > RegWidth)
4087 return Error(WidthOp.getStartLoc(),
4088 "expected integer in range [1, 32]");
4089
4090 uint64_t ImmR = 0;
4091 if (RegWidth == 32)
4092 ImmR = (32 - LSB) & 0x1f;
4093 else
4094 ImmR = (64 - LSB) & 0x3f;
4095
4096 uint64_t ImmS = Width - 1;
4097
4098 if (ImmR != 0 && ImmS >= ImmR)
4099 return Error(WidthOp.getStartLoc(),
4100 "requested insert overflows register");
4101
Jim Grosbach13760bd2015-05-30 01:25:56 +00004102 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4103 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004104 Operands[0] = AArch64Operand::CreateToken(
4105 "bfm", false, Op.getStartLoc(), getContext());
4106 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004107 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4108 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004109 Operands[3] = AArch64Operand::CreateImm(
4110 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4111 Operands.emplace_back(
4112 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4113 WidthOp.getEndLoc(), getContext()));
4114 }
4115 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004116 } else if (NumOperands == 5) {
4117 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4118 // UBFIZ -> UBFM aliases.
4119 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004120 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4121 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4122 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004123
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004124 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004125 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4126 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004127
4128 if (Op3CE && Op4CE) {
4129 uint64_t Op3Val = Op3CE->getValue();
4130 uint64_t Op4Val = Op4CE->getValue();
4131
4132 uint64_t RegWidth = 0;
4133 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004134 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004135 RegWidth = 64;
4136 else
4137 RegWidth = 32;
4138
4139 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004140 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004141 "expected integer in range [0, 31]");
4142 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004143 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004144 "expected integer in range [1, 32]");
4145
4146 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004147 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004148 NewOp3Val = (32 - Op3Val) & 0x1f;
4149 else
4150 NewOp3Val = (64 - Op3Val) & 0x3f;
4151
4152 uint64_t NewOp4Val = Op4Val - 1;
4153
4154 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004155 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004156 "requested insert overflows register");
4157
4158 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004159 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004160 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004161 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004162 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004163 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004164 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004165 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004166 if (Tok == "bfi")
4167 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004168 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004169 else if (Tok == "sbfiz")
4170 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004171 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004172 else if (Tok == "ubfiz")
4173 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004174 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004175 else
4176 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004177 }
4178 }
4179
4180 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4181 // UBFX -> UBFM aliases.
4182 } else if (NumOperands == 5 &&
4183 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004184 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4185 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4186 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004187
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004188 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004189 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4190 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004191
4192 if (Op3CE && Op4CE) {
4193 uint64_t Op3Val = Op3CE->getValue();
4194 uint64_t Op4Val = Op4CE->getValue();
4195
4196 uint64_t RegWidth = 0;
4197 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004198 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004199 RegWidth = 64;
4200 else
4201 RegWidth = 32;
4202
4203 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004204 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004205 "expected integer in range [0, 31]");
4206 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004207 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004208 "expected integer in range [1, 32]");
4209
4210 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4211
4212 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004213 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004214 "requested extract overflows register");
4215
4216 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004217 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004218 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004219 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004220 if (Tok == "bfxil")
4221 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004222 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004223 else if (Tok == "sbfx")
4224 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004225 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004226 else if (Tok == "ubfx")
4227 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004228 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004229 else
4230 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004231 }
4232 }
4233 }
4234 }
Tim Northover9097a072017-12-18 10:36:00 +00004235
4236 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4237 // instruction for FP registers correctly in some rare circumstances. Convert
4238 // it to a safe instruction and warn (because silently changing someone's
4239 // assembly is rude).
4240 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4241 NumOperands == 4 && Tok == "movi") {
4242 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4243 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4244 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4245 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4246 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4247 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4248 if (Suffix.lower() == ".2d" &&
4249 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4250 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4251 " correctly on this CPU, converting to equivalent movi.16b");
4252 // Switch the suffix to .16b.
4253 unsigned Idx = Op1.isToken() ? 1 : 2;
4254 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4255 getContext());
4256 }
4257 }
4258 }
4259
Tim Northover3b0846e2014-05-24 12:50:23 +00004260 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4261 // InstAlias can't quite handle this since the reg classes aren't
4262 // subclasses.
4263 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4264 // The source register can be Wn here, but the matcher expects a
4265 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004266 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004267 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004268 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004269 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4270 Op.getStartLoc(), Op.getEndLoc(),
4271 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004272 }
4273 }
4274 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4275 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004276 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004277 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004278 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004279 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004280 // The source register can be Wn here, but the matcher expects a
4281 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004282 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004283 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004284 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004285 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4286 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004287 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004288 }
4289 }
4290 }
4291 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4292 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004293 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004294 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004295 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004296 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004297 // The source register can be Wn here, but the matcher expects a
4298 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004299 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004300 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004301 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004302 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4303 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004304 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004305 }
4306 }
4307 }
4308
Tim Northover3b0846e2014-05-24 12:50:23 +00004309 MCInst Inst;
4310 // First try to match against the secondary set of tables containing the
4311 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4312 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004313 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004314
4315 // If that fails, try against the alternate table containing long-form NEON:
4316 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004317 if (MatchResult != Match_Success) {
4318 // But first, save the short-form match result: we can use it in case the
4319 // long-form match also fails.
4320 auto ShortFormNEONErrorInfo = ErrorInfo;
4321 auto ShortFormNEONMatchResult = MatchResult;
4322
Tim Northover3b0846e2014-05-24 12:50:23 +00004323 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004324 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004325
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004326 // Now, both matches failed, and the long-form match failed on the mnemonic
4327 // suffix token operand. The short-form match failure is probably more
4328 // relevant: use it instead.
4329 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004330 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004331 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4332 MatchResult = ShortFormNEONMatchResult;
4333 ErrorInfo = ShortFormNEONErrorInfo;
4334 }
4335 }
4336
Tim Northover3b0846e2014-05-24 12:50:23 +00004337 switch (MatchResult) {
4338 case Match_Success: {
4339 // Perform range checking and other semantic validations
4340 SmallVector<SMLoc, 8> OperandLocs;
4341 NumOperands = Operands.size();
4342 for (unsigned i = 1; i < NumOperands; ++i)
4343 OperandLocs.push_back(Operands[i]->getStartLoc());
4344 if (validateInstruction(Inst, OperandLocs))
4345 return true;
4346
4347 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004348 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004349 return false;
4350 }
4351 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004352 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004353 // Special case the error message for the very common case where only
4354 // a single subtarget feature is missing (neon, e.g.).
4355 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004356 uint64_t Mask = 1;
4357 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4358 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004359 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004360 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004361 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004362 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004363 }
4364 return Error(IDLoc, Msg);
4365 }
4366 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004367 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004368 case Match_InvalidOperand: {
4369 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004370
Tim Northover26bb14e2014-08-18 11:49:42 +00004371 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004372 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004373 return Error(IDLoc, "too few operands for instruction",
4374 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004375
David Blaikie960ea3f2014-06-08 16:18:35 +00004376 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004377 if (ErrorLoc == SMLoc())
4378 ErrorLoc = IDLoc;
4379 }
4380 // If the match failed on a suffix token operand, tweak the diagnostic
4381 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004382 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4383 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004384 MatchResult = Match_InvalidSuffix;
4385
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004386 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004387 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004388 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004389 case Match_InvalidMemoryIndexed1:
4390 case Match_InvalidMemoryIndexed2:
4391 case Match_InvalidMemoryIndexed4:
4392 case Match_InvalidMemoryIndexed8:
4393 case Match_InvalidMemoryIndexed16:
4394 case Match_InvalidCondCode:
4395 case Match_AddSubRegExtendSmall:
4396 case Match_AddSubRegExtendLarge:
4397 case Match_AddSubSecondSource:
4398 case Match_LogicalSecondSource:
4399 case Match_AddSubRegShift32:
4400 case Match_AddSubRegShift64:
4401 case Match_InvalidMovImm32Shift:
4402 case Match_InvalidMovImm64Shift:
4403 case Match_InvalidFPImm:
4404 case Match_InvalidMemoryWExtend8:
4405 case Match_InvalidMemoryWExtend16:
4406 case Match_InvalidMemoryWExtend32:
4407 case Match_InvalidMemoryWExtend64:
4408 case Match_InvalidMemoryWExtend128:
4409 case Match_InvalidMemoryXExtend8:
4410 case Match_InvalidMemoryXExtend16:
4411 case Match_InvalidMemoryXExtend32:
4412 case Match_InvalidMemoryXExtend64:
4413 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004414 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004415 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004416 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004417 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004418 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004419 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004420 case Match_InvalidMemoryIndexed4SImm7:
4421 case Match_InvalidMemoryIndexed8SImm7:
4422 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004423 case Match_InvalidMemoryIndexed8UImm5:
4424 case Match_InvalidMemoryIndexed4UImm5:
4425 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004426 case Match_InvalidMemoryIndexed1UImm6:
4427 case Match_InvalidMemoryIndexed2UImm6:
4428 case Match_InvalidMemoryIndexed4UImm6:
4429 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004430 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004431 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004432 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004433 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004434 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004435 case Match_InvalidImm0_7:
4436 case Match_InvalidImm0_15:
4437 case Match_InvalidImm0_31:
4438 case Match_InvalidImm0_63:
4439 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004440 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004441 case Match_InvalidImm0_65535:
4442 case Match_InvalidImm1_8:
4443 case Match_InvalidImm1_16:
4444 case Match_InvalidImm1_32:
4445 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004446 case Match_InvalidSVEAddSubImm8:
4447 case Match_InvalidSVEAddSubImm16:
4448 case Match_InvalidSVEAddSubImm32:
4449 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004450 case Match_InvalidSVECpyImm8:
4451 case Match_InvalidSVECpyImm16:
4452 case Match_InvalidSVECpyImm32:
4453 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004454 case Match_InvalidIndexRange1_1:
4455 case Match_InvalidIndexRange0_15:
4456 case Match_InvalidIndexRange0_7:
4457 case Match_InvalidIndexRange0_3:
4458 case Match_InvalidIndexRange0_1:
4459 case Match_InvalidSVEIndexRange0_63:
4460 case Match_InvalidSVEIndexRange0_31:
4461 case Match_InvalidSVEIndexRange0_15:
4462 case Match_InvalidSVEIndexRange0_7:
4463 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004464 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004465 case Match_InvalidComplexRotationEven:
4466 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004467 case Match_InvalidGPR64shifted8:
4468 case Match_InvalidGPR64shifted16:
4469 case Match_InvalidGPR64shifted32:
4470 case Match_InvalidGPR64shifted64:
4471 case Match_InvalidGPR64NoXZRshifted8:
4472 case Match_InvalidGPR64NoXZRshifted16:
4473 case Match_InvalidGPR64NoXZRshifted32:
4474 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004475 case Match_InvalidZPR32UXTW8:
4476 case Match_InvalidZPR32UXTW16:
4477 case Match_InvalidZPR32UXTW32:
4478 case Match_InvalidZPR32UXTW64:
4479 case Match_InvalidZPR32SXTW8:
4480 case Match_InvalidZPR32SXTW16:
4481 case Match_InvalidZPR32SXTW32:
4482 case Match_InvalidZPR32SXTW64:
4483 case Match_InvalidZPR64UXTW8:
4484 case Match_InvalidZPR64SXTW8:
4485 case Match_InvalidZPR64UXTW16:
4486 case Match_InvalidZPR64SXTW16:
4487 case Match_InvalidZPR64UXTW32:
4488 case Match_InvalidZPR64SXTW32:
4489 case Match_InvalidZPR64UXTW64:
4490 case Match_InvalidZPR64SXTW64:
4491 case Match_InvalidZPR64LSL8:
4492 case Match_InvalidZPR64LSL16:
4493 case Match_InvalidZPR64LSL32:
4494 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004495 case Match_InvalidZPR0:
4496 case Match_InvalidZPR8:
4497 case Match_InvalidZPR16:
4498 case Match_InvalidZPR32:
4499 case Match_InvalidZPR64:
4500 case Match_InvalidZPR128:
Sander de Smalencd6be962017-12-20 11:02:42 +00004501 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004502 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004503 case Match_InvalidSVEPredicateBReg:
4504 case Match_InvalidSVEPredicateHReg:
4505 case Match_InvalidSVEPredicateSReg:
4506 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004507 case Match_InvalidSVEPredicate3bAnyReg:
4508 case Match_InvalidSVEPredicate3bBReg:
4509 case Match_InvalidSVEPredicate3bHReg:
4510 case Match_InvalidSVEPredicate3bSReg:
4511 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004512 case Match_MSR:
4513 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004514 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004515 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004516 // Any time we get here, there's nothing fancy to do. Just get the
4517 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004518 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004519 if (ErrorLoc == SMLoc())
4520 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004521 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004522 }
4523 }
4524
4525 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004526}
4527
4528/// ParseDirective parses the arm specific directives
4529bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004530 const MCObjectFileInfo::Environment Format =
4531 getContext().getObjectFileInfo()->getObjectFileType();
4532 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4533 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004534
Tim Northover3b0846e2014-05-24 12:50:23 +00004535 StringRef IDVal = DirectiveID.getIdentifier();
4536 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004537 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004538 parseDirectiveArch(Loc);
4539 else if (IDVal == ".cpu")
4540 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00004541 else if (IDVal == ".tlsdesccall")
4542 parseDirectiveTLSDescCall(Loc);
4543 else if (IDVal == ".ltorg" || IDVal == ".pool")
4544 parseDirectiveLtorg(Loc);
4545 else if (IDVal == ".unreq")
4546 parseDirectiveUnreq(Loc);
4547 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004548 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004549 parseDirectiveInst(Loc);
4550 else
4551 return true;
4552 } else if (IDVal == MCLOHDirectiveName())
4553 parseDirectiveLOH(IDVal, Loc);
4554 else
4555 return true;
4556 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004557}
4558
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004559static const struct {
4560 const char *Name;
4561 const FeatureBitset Features;
4562} ExtensionMap[] = {
4563 { "crc", {AArch64::FeatureCRC} },
4564 { "crypto", {AArch64::FeatureCrypto} },
4565 { "fp", {AArch64::FeatureFPARMv8} },
4566 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004567 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004568 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004569
4570 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004571 { "pan", {} },
4572 { "lor", {} },
4573 { "rdma", {} },
4574 { "profile", {} },
4575};
4576
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004577/// parseDirectiveArch
4578/// ::= .arch token
4579bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4580 SMLoc ArchLoc = getLoc();
4581
4582 StringRef Arch, ExtensionString;
4583 std::tie(Arch, ExtensionString) =
4584 getParser().parseStringToEndOfStatement().trim().split('+');
4585
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004586 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4587 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004588 return Error(ArchLoc, "unknown arch name");
4589
4590 if (parseToken(AsmToken::EndOfStatement))
4591 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004592
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004593 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004594 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004595 AArch64::getArchFeatures(ID, AArch64Features);
4596 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4597 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004598
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004599 MCSubtargetInfo &STI = copySTI();
4600 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4601 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4602
4603 SmallVector<StringRef, 4> RequestedExtensions;
4604 if (!ExtensionString.empty())
4605 ExtensionString.split(RequestedExtensions, '+');
4606
4607 FeatureBitset Features = STI.getFeatureBits();
4608 for (auto Name : RequestedExtensions) {
4609 bool EnableFeature = true;
4610
4611 if (Name.startswith_lower("no")) {
4612 EnableFeature = false;
4613 Name = Name.substr(2);
4614 }
4615
4616 for (const auto &Extension : ExtensionMap) {
4617 if (Extension.Name != Name)
4618 continue;
4619
4620 if (Extension.Features.none())
4621 report_fatal_error("unsupported architectural extension: " + Name);
4622
4623 FeatureBitset ToggleFeatures = EnableFeature
4624 ? (~Features & Extension.Features)
4625 : ( Features & Extension.Features);
4626 uint64_t Features =
4627 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4628 setAvailableFeatures(Features);
4629 break;
4630 }
4631 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004632 return false;
4633}
4634
Tim Northover8b96c7e2017-05-15 19:42:15 +00004635static SMLoc incrementLoc(SMLoc L, int Offset) {
4636 return SMLoc::getFromPointer(L.getPointer() + Offset);
4637}
4638
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004639/// parseDirectiveCPU
4640/// ::= .cpu id
4641bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004642 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004643
4644 StringRef CPU, ExtensionString;
4645 std::tie(CPU, ExtensionString) =
4646 getParser().parseStringToEndOfStatement().trim().split('+');
4647
Nirav Davee833c6c2016-11-08 18:31:04 +00004648 if (parseToken(AsmToken::EndOfStatement))
4649 return true;
4650
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004651 SmallVector<StringRef, 4> RequestedExtensions;
4652 if (!ExtensionString.empty())
4653 ExtensionString.split(RequestedExtensions, '+');
4654
4655 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4656 // once that is tablegen'ed
4657 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004658 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004659 return false;
4660 }
4661
4662 MCSubtargetInfo &STI = copySTI();
4663 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004664 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004665
4666 FeatureBitset Features = STI.getFeatureBits();
4667 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004668 // Advance source location past '+'.
4669 CurLoc = incrementLoc(CurLoc, 1);
4670
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004671 bool EnableFeature = true;
4672
4673 if (Name.startswith_lower("no")) {
4674 EnableFeature = false;
4675 Name = Name.substr(2);
4676 }
4677
Tim Northover8b96c7e2017-05-15 19:42:15 +00004678 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004679 for (const auto &Extension : ExtensionMap) {
4680 if (Extension.Name != Name)
4681 continue;
4682
4683 if (Extension.Features.none())
4684 report_fatal_error("unsupported architectural extension: " + Name);
4685
4686 FeatureBitset ToggleFeatures = EnableFeature
4687 ? (~Features & Extension.Features)
4688 : ( Features & Extension.Features);
4689 uint64_t Features =
4690 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4691 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004692 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004693
4694 break;
4695 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004696
4697 if (!FoundExtension)
4698 Error(CurLoc, "unsupported architectural extension");
4699
4700 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004701 }
4702 return false;
4703}
4704
Chad Rosierdcd2a302014-10-22 20:35:57 +00004705/// parseDirectiveInst
4706/// ::= .inst opcode [, ...]
4707bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004708 if (getLexer().is(AsmToken::EndOfStatement))
4709 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004710
Nirav Davee833c6c2016-11-08 18:31:04 +00004711 auto parseOp = [&]() -> bool {
4712 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004713 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004714 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4715 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004716 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004717 if (check(!Value, L, "expected constant expression"))
4718 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004719 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004720 return false;
4721 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004722
Nirav Davee833c6c2016-11-08 18:31:04 +00004723 if (parseMany(parseOp))
4724 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004725 return false;
4726}
4727
Tim Northover3b0846e2014-05-24 12:50:23 +00004728// parseDirectiveTLSDescCall:
4729// ::= .tlsdesccall symbol
4730bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4731 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004732 if (check(getParser().parseIdentifier(Name), L,
4733 "expected symbol after directive") ||
4734 parseToken(AsmToken::EndOfStatement))
4735 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004736
Jim Grosbach6f482002015-05-18 18:43:14 +00004737 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004738 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4739 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004740
4741 MCInst Inst;
4742 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004743 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004744
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004745 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004746 return false;
4747}
4748
4749/// ::= .loh <lohName | lohId> label1, ..., labelN
4750/// The number of arguments depends on the loh identifier.
4751bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004752 MCLOHType Kind;
4753 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4754 if (getParser().getTok().isNot(AsmToken::Integer))
4755 return TokError("expected an identifier or a number in directive");
4756 // We successfully get a numeric value for the identifier.
4757 // Check if it is valid.
4758 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004759 if (Id <= -1U && !isValidMCLOHType(Id))
4760 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004761 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004762 } else {
4763 StringRef Name = getTok().getIdentifier();
4764 // We successfully parse an identifier.
4765 // Check if it is a recognized one.
4766 int Id = MCLOHNameToId(Name);
4767
4768 if (Id == -1)
4769 return TokError("invalid identifier in directive");
4770 Kind = (MCLOHType)Id;
4771 }
4772 // Consume the identifier.
4773 Lex();
4774 // Get the number of arguments of this LOH.
4775 int NbArgs = MCLOHIdToNbArgs(Kind);
4776
4777 assert(NbArgs != -1 && "Invalid number of arguments");
4778
4779 SmallVector<MCSymbol *, 3> Args;
4780 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4781 StringRef Name;
4782 if (getParser().parseIdentifier(Name))
4783 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004784 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004785
4786 if (Idx + 1 == NbArgs)
4787 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004788 if (parseToken(AsmToken::Comma,
4789 "unexpected token in '" + Twine(IDVal) + "' directive"))
4790 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004791 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004792 if (parseToken(AsmToken::EndOfStatement,
4793 "unexpected token in '" + Twine(IDVal) + "' directive"))
4794 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004795
4796 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4797 return false;
4798}
4799
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004800/// parseDirectiveLtorg
4801/// ::= .ltorg | .pool
4802bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004803 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4804 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004805 getTargetStreamer().emitCurrentConstantPool();
4806 return false;
4807}
4808
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004809/// parseDirectiveReq
4810/// ::= name .req registername
4811bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004812 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004813 Parser.Lex(); // Eat the '.req' token.
4814 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004815 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004816 unsigned RegNum;
4817 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004818
Sander de Smalen50d87022018-04-19 07:35:08 +00004819 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004820 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004821 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004822 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004823
Sander de Smalen50d87022018-04-19 07:35:08 +00004824 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004825 return true;
4826
Sander de Smalen50d87022018-04-19 07:35:08 +00004827 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004828 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004829 }
4830
Sander de Smalen50d87022018-04-19 07:35:08 +00004831 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004832 StringRef Kind;
4833 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004834 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004835 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004836
Sander de Smalen50d87022018-04-19 07:35:08 +00004837 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004838 return true;
4839
Sander de Smalen50d87022018-04-19 07:35:08 +00004840 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004841 return Error(SRegLoc,
4842 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004843 }
4844
Sander de Smalen50d87022018-04-19 07:35:08 +00004845 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00004846 StringRef Kind;
4847 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004848 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004849
Sander de Smalen50d87022018-04-19 07:35:08 +00004850 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00004851 return true;
4852
Sander de Smalen50d87022018-04-19 07:35:08 +00004853 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00004854 return Error(SRegLoc,
4855 "sve predicate register without type specifier expected");
4856 }
4857
Sander de Smalen50d87022018-04-19 07:35:08 +00004858 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00004859 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004860
4861 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004862 if (parseToken(AsmToken::EndOfStatement,
4863 "unexpected input in .req directive"))
4864 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004865
Sander de Smalen8e607342017-11-15 15:44:43 +00004866 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004867 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004868 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4869
Nirav Dave2364748a2016-09-16 18:30:20 +00004870 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004871}
4872
4873/// parseDirectiveUneq
4874/// ::= .unreq registername
4875bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004876 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004877 if (getTok().isNot(AsmToken::Identifier))
4878 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004879 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4880 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004881 if (parseToken(AsmToken::EndOfStatement))
4882 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004883 return false;
4884}
4885
Tim Northover3b0846e2014-05-24 12:50:23 +00004886bool
4887AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4888 AArch64MCExpr::VariantKind &ELFRefKind,
4889 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4890 int64_t &Addend) {
4891 ELFRefKind = AArch64MCExpr::VK_INVALID;
4892 DarwinRefKind = MCSymbolRefExpr::VK_None;
4893 Addend = 0;
4894
4895 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4896 ELFRefKind = AE->getKind();
4897 Expr = AE->getSubExpr();
4898 }
4899
4900 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4901 if (SE) {
4902 // It's a simple symbol reference with no addend.
4903 DarwinRefKind = SE->getKind();
4904 return true;
4905 }
4906
4907 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4908 if (!BE)
4909 return false;
4910
4911 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4912 if (!SE)
4913 return false;
4914 DarwinRefKind = SE->getKind();
4915
4916 if (BE->getOpcode() != MCBinaryExpr::Add &&
4917 BE->getOpcode() != MCBinaryExpr::Sub)
4918 return false;
4919
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004920 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004921 // on here than we can deal with.
4922 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4923 if (!AddendExpr)
4924 return false;
4925
4926 Addend = AddendExpr->getValue();
4927 if (BE->getOpcode() == MCBinaryExpr::Sub)
4928 Addend = -Addend;
4929
4930 // It's some symbol reference + a constant addend, but really
4931 // shouldn't use both Darwin and ELF syntax.
4932 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4933 DarwinRefKind == MCSymbolRefExpr::VK_None;
4934}
4935
4936/// Force static initialization.
4937extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004938 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4939 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4940 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004941}
4942
4943#define GET_REGISTER_MATCHER
4944#define GET_SUBTARGET_FEATURE_NAME
4945#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004946#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004947#include "AArch64GenAsmMatcher.inc"
4948
4949// Define this matcher function after the auto-generated include so we
4950// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004951unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004952 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004953 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004954 // If the kind is a token for a literal immediate, check if our asm
4955 // operand matches. This is for InstAliases which have a fixed-value
4956 // immediate in the syntax.
4957 int64_t ExpectedVal;
4958 switch (Kind) {
4959 default:
4960 return Match_InvalidOperand;
4961 case MCK__35_0:
4962 ExpectedVal = 0;
4963 break;
4964 case MCK__35_1:
4965 ExpectedVal = 1;
4966 break;
4967 case MCK__35_12:
4968 ExpectedVal = 12;
4969 break;
4970 case MCK__35_16:
4971 ExpectedVal = 16;
4972 break;
4973 case MCK__35_2:
4974 ExpectedVal = 2;
4975 break;
4976 case MCK__35_24:
4977 ExpectedVal = 24;
4978 break;
4979 case MCK__35_3:
4980 ExpectedVal = 3;
4981 break;
4982 case MCK__35_32:
4983 ExpectedVal = 32;
4984 break;
4985 case MCK__35_4:
4986 ExpectedVal = 4;
4987 break;
4988 case MCK__35_48:
4989 ExpectedVal = 48;
4990 break;
4991 case MCK__35_6:
4992 ExpectedVal = 6;
4993 break;
4994 case MCK__35_64:
4995 ExpectedVal = 64;
4996 break;
4997 case MCK__35_8:
4998 ExpectedVal = 8;
4999 break;
5000 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005001 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005002 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005003 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005004 if (!CE)
5005 return Match_InvalidOperand;
5006 if (CE->getValue() == ExpectedVal)
5007 return Match_Success;
5008 return Match_InvalidOperand;
5009}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005010
Alex Bradbury58eba092016-11-01 16:32:05 +00005011OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005012AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5013
5014 SMLoc S = getLoc();
5015
5016 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5017 Error(S, "expected register");
5018 return MatchOperand_ParseFail;
5019 }
5020
Sander de Smalen50d87022018-04-19 07:35:08 +00005021 unsigned FirstReg;
5022 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5023 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005024 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005025
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005026 const MCRegisterClass &WRegClass =
5027 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5028 const MCRegisterClass &XRegClass =
5029 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5030
5031 bool isXReg = XRegClass.contains(FirstReg),
5032 isWReg = WRegClass.contains(FirstReg);
5033 if (!isXReg && !isWReg) {
5034 Error(S, "expected first even register of a "
5035 "consecutive same-size even/odd register pair");
5036 return MatchOperand_ParseFail;
5037 }
5038
5039 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5040 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5041
5042 if (FirstEncoding & 0x1) {
5043 Error(S, "expected first even register of a "
5044 "consecutive same-size even/odd register pair");
5045 return MatchOperand_ParseFail;
5046 }
5047
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005048 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005049 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005050 return MatchOperand_ParseFail;
5051 }
5052 // Eat the comma
5053 getParser().Lex();
5054
5055 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005056 unsigned SecondReg;
5057 Res = tryParseScalarRegister(SecondReg);
5058 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005059 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005060
Eugene Zelenko049b0172017-01-06 00:30:53 +00005061 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005062 (isXReg && !XRegClass.contains(SecondReg)) ||
5063 (isWReg && !WRegClass.contains(SecondReg))) {
5064 Error(E,"expected second odd register of a "
5065 "consecutive same-size even/odd register pair");
5066 return MatchOperand_ParseFail;
5067 }
Joel Jones504bf332016-10-24 13:37:13 +00005068
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005069 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005070 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005071 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5072 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5073 } else {
5074 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5075 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5076 }
5077
Florian Hahnc4422242017-11-07 13:07:50 +00005078 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5079 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005080
5081 return MatchOperand_Success;
5082}
Florian Hahn91f11e52017-11-07 16:45:48 +00005083
Sander de Smaleneb896b12018-04-25 09:26:47 +00005084template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005085OperandMatchResultTy
5086AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005087 const SMLoc S = getLoc();
5088 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005089 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005090 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005091
Sander de Smalen8e607342017-11-15 15:44:43 +00005092 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005093 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005094
5095 if (Res != MatchOperand_Success)
5096 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005097
5098 if (ParseSuffix && Kind.empty())
5099 return MatchOperand_NoMatch;
5100
Sander de Smalen73937b72018-04-11 07:36:10 +00005101 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5102 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005103 return MatchOperand_NoMatch;
5104
Sander de Smalen73937b72018-04-11 07:36:10 +00005105 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005106
5107 // No shift/extend is the default.
5108 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5109 Operands.push_back(AArch64Operand::CreateVectorReg(
5110 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5111
Sander de Smalenc33d6682018-06-04 06:40:55 +00005112 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5113 if (Res == MatchOperand_ParseFail)
5114 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005115 return MatchOperand_Success;
5116 }
5117
5118 // Eat the comma
5119 getParser().Lex();
5120
5121 // Match the shift
5122 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5123 Res = tryParseOptionalShiftExtend(ExtOpnd);
5124 if (Res != MatchOperand_Success)
5125 return Res;
5126
5127 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005128 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005129 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5130 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5131 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005132
5133 return MatchOperand_Success;
5134}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005135
5136OperandMatchResultTy
5137AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5138 MCAsmParser &Parser = getParser();
5139
5140 SMLoc SS = getLoc();
5141 const AsmToken &TokE = Parser.getTok();
5142 bool IsHash = TokE.is(AsmToken::Hash);
5143
5144 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5145 return MatchOperand_NoMatch;
5146
5147 int64_t Pattern;
5148 if (IsHash) {
5149 Parser.Lex(); // Eat hash
5150
5151 // Parse the immediate operand.
5152 const MCExpr *ImmVal;
5153 SS = getLoc();
5154 if (Parser.parseExpression(ImmVal))
5155 return MatchOperand_ParseFail;
5156
5157 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5158 if (!MCE)
5159 return MatchOperand_ParseFail;
5160
5161 Pattern = MCE->getValue();
5162 } else {
5163 // Parse the pattern
5164 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5165 if (!Pat)
5166 return MatchOperand_NoMatch;
5167
5168 Parser.Lex();
5169 Pattern = Pat->Encoding;
5170 assert(Pattern >= 0 && Pattern < 32);
5171 }
5172
5173 Operands.push_back(
5174 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5175 SS, getLoc(), getContext()));
5176
5177 return MatchOperand_Success;
5178}