blob: 6eb1b27e682478e884a913eb0083fd2e6ffe0223 [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
Sander de Smalen0325e302018-07-02 07:34:52 +000069enum RegConstraintEqualityTy {
70 EqualsReg,
71 EqualsSuperReg,
72 EqualsSubReg
73};
74
Tim Northover3b0846e2014-05-24 12:50:23 +000075class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000076private:
77 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000078
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000079 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000080 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000081
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000082 AArch64TargetStreamer &getTargetStreamer() {
83 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
84 return static_cast<AArch64TargetStreamer &>(TS);
85 }
86
Rafael Espindola961d4692014-11-11 05:18:41 +000087 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000088
89 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +000090 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +000091 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
92 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +000093 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +000094 bool parseRegister(OperandVector &Operands);
95 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
Sander de Smalenc88f9a12018-04-11 14:10:37 +000096 bool parseNeonVectorList(OperandVector &Operands);
Sander de Smalen18ac8f92018-06-15 15:47:44 +000097 bool parseOptionalMulOperand(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000098 bool parseOperand(OperandVector &Operands, bool isCondCode,
99 bool invertCondCode);
100
Sander de Smalen0325e302018-07-02 07:34:52 +0000101 bool showMatchError(SMLoc Loc, unsigned ErrCode, uint64_t ErrorInfo,
102 OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000103
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +0000104 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +0000105 bool parseDirectiveCPU(SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +0000106 bool parseDirectiveInst(SMLoc L);
107
Tim Northover3b0846e2014-05-24 12:50:23 +0000108 bool parseDirectiveTLSDescCall(SMLoc L);
109
110 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000111 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000112
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000113 bool parseDirectiveReq(StringRef Name, SMLoc L);
114 bool parseDirectiveUnreq(SMLoc L);
115
Tim Northover3b0846e2014-05-24 12:50:23 +0000116 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
117 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
118 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000119 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000120 bool MatchingInlineAsm) override;
121/// @name Auto-generated Match Functions
122/// {
123
124#define GET_ASSEMBLER_HEADER
125#include "AArch64GenAsmMatcher.inc"
126
127 /// }
128
Sander de Smalen50d87022018-04-19 07:35:08 +0000129 OperandMatchResultTy tryParseScalarRegister(unsigned &Reg);
130 OperandMatchResultTy tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +0000131 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000132 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
133 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
134 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
135 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
136 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
Sander de Smalen93380372018-05-14 11:54:41 +0000137 template <bool IsSVEPrefetch = false>
Tim Northover3b0846e2014-05-24 12:50:23 +0000138 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000139 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000140 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
141 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000142 template<bool AddFPZeroAsLiteral>
Tim Northover3b0846e2014-05-24 12:50:23 +0000143 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
Sander de Smalen62770792018-05-25 09:47:52 +0000144 OperandMatchResultTy tryParseImmWithOptionalShift(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000145 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000146 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000147 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000148 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Sander de Smalen0325e302018-07-02 07:34:52 +0000149 template <bool ParseShiftExtend,
150 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg>
Sander de Smalen149916d2018-04-20 07:24:20 +0000151 OperandMatchResultTy tryParseGPROperand(OperandVector &Operands);
Sander de Smaleneb896b12018-04-25 09:26:47 +0000152 template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +0000153 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000154 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000155 template <RegKind VectorKind>
156 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
157 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000158 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000159
160public:
161 enum AArch64MatchResultTy {
162 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
163#define GET_OPERAND_DIAGNOSTIC_TYPES
164#include "AArch64GenAsmMatcher.inc"
165 };
Joel Jones504bf332016-10-24 13:37:13 +0000166 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000167
Akira Hatanakab11ef082015-11-14 06:35:56 +0000168 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000169 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000170 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000171 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000172 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000173 MCStreamer &S = getParser().getStreamer();
174 if (S.getTargetStreamer() == nullptr)
175 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000176
Alex Bradbury0a59f182018-05-23 11:17:20 +0000177 // Alias .hword/.word/xword to the target-independent .2byte/.4byte/.8byte
178 // directives as they have the same form and semantics:
179 /// ::= (.hword | .word | .xword ) [ expression (, expression)* ]
180 Parser.addAliasForDirective(".hword", ".2byte");
181 Parser.addAliasForDirective(".word", ".4byte");
182 Parser.addAliasForDirective(".xword", ".8byte");
183
Tim Northover3b0846e2014-05-24 12:50:23 +0000184 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000185 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000186 }
187
Sander de Smalen0325e302018-07-02 07:34:52 +0000188 bool regsEqual(const MCParsedAsmOperand &Op1,
189 const MCParsedAsmOperand &Op2) const override;
Tim Northover3b0846e2014-05-24 12:50:23 +0000190 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
191 SMLoc NameLoc, OperandVector &Operands) override;
192 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
193 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000194 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000195 unsigned Kind) override;
196
197 static bool classifySymbolRef(const MCExpr *Expr,
198 AArch64MCExpr::VariantKind &ELFRefKind,
199 MCSymbolRefExpr::VariantKind &DarwinRefKind,
200 int64_t &Addend);
201};
Tim Northover3b0846e2014-05-24 12:50:23 +0000202
203/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
204/// instruction.
205class AArch64Operand : public MCParsedAsmOperand {
206private:
207 enum KindTy {
208 k_Immediate,
209 k_ShiftedImm,
210 k_CondCode,
211 k_Register,
212 k_VectorList,
213 k_VectorIndex,
214 k_Token,
215 k_SysReg,
216 k_SysCR,
217 k_Prefetch,
218 k_ShiftExtend,
219 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000220 k_Barrier,
221 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000222 } Kind;
223
224 SMLoc StartLoc, EndLoc;
225
226 struct TokOp {
227 const char *Data;
228 unsigned Length;
229 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
230 };
231
Sander de Smalen149916d2018-04-20 07:24:20 +0000232 // Separate shift/extend operand.
233 struct ShiftExtendOp {
234 AArch64_AM::ShiftExtendType Type;
235 unsigned Amount;
236 bool HasExplicitAmount;
237 };
238
Tim Northover3b0846e2014-05-24 12:50:23 +0000239 struct RegOp {
240 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000241 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000242 int ElementWidth;
Sander de Smalen149916d2018-04-20 07:24:20 +0000243
Sander de Smalen0325e302018-07-02 07:34:52 +0000244 // The register may be allowed as a different register class,
245 // e.g. for GPR64as32 or GPR32as64.
246 RegConstraintEqualityTy EqualityTy;
247
Sander de Smalen149916d2018-04-20 07:24:20 +0000248 // In some cases the shift/extend needs to be explicitly parsed together
249 // with the register, rather than as a separate operand. This is needed
250 // for addressing modes where the instruction as a whole dictates the
251 // scaling/extend, rather than specific bits in the instruction.
252 // By parsing them as a single operand, we avoid the need to pass an
253 // extra operand in all CodeGen patterns (because all operands need to
254 // have an associated value), and we avoid the need to update TableGen to
255 // accept operands that have no associated bits in the instruction.
256 //
257 // An added benefit of parsing them together is that the assembler
258 // can give a sensible diagnostic if the scaling is not correct.
259 //
260 // The default is 'lsl #0' (HasExplicitAmount = false) if no
261 // ShiftExtend is specified.
262 ShiftExtendOp ShiftExtend;
Tim Northover3b0846e2014-05-24 12:50:23 +0000263 };
264
265 struct VectorListOp {
266 unsigned RegNum;
267 unsigned Count;
268 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000269 unsigned ElementWidth;
270 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000271 };
272
273 struct VectorIndexOp {
274 unsigned Val;
275 };
276
277 struct ImmOp {
278 const MCExpr *Val;
279 };
280
281 struct ShiftedImmOp {
282 const MCExpr *Val;
283 unsigned ShiftAmount;
284 };
285
286 struct CondCodeOp {
287 AArch64CC::CondCode Code;
288 };
289
290 struct FPImmOp {
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000291 uint64_t Val; // APFloat value bitcasted to uint64_t.
292 bool IsExact; // describes whether parsed value was exact.
Tim Northover3b0846e2014-05-24 12:50:23 +0000293 };
294
295 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000296 const char *Data;
297 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000298 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000299 };
300
301 struct SysRegOp {
302 const char *Data;
303 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000304 uint32_t MRSReg;
305 uint32_t MSRReg;
306 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000307 };
308
309 struct SysCRImmOp {
310 unsigned Val;
311 };
312
313 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000314 const char *Data;
315 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000316 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000317 };
318
Oliver Stannarda34e4702015-12-01 10:48:51 +0000319 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000320 const char *Data;
321 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000322 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000323 };
324
Tim Northover3b0846e2014-05-24 12:50:23 +0000325 struct ExtendOp {
326 unsigned Val;
327 };
328
329 union {
330 struct TokOp Tok;
331 struct RegOp Reg;
332 struct VectorListOp VectorList;
333 struct VectorIndexOp VectorIndex;
334 struct ImmOp Imm;
335 struct ShiftedImmOp ShiftedImm;
336 struct CondCodeOp CondCode;
337 struct FPImmOp FPImm;
338 struct BarrierOp Barrier;
339 struct SysRegOp SysReg;
340 struct SysCRImmOp SysCRImm;
341 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000342 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000343 struct ShiftExtendOp ShiftExtend;
344 };
345
346 // Keep the MCContext around as the MCExprs may need manipulated during
347 // the add<>Operands() calls.
348 MCContext &Ctx;
349
David Blaikie960ea3f2014-06-08 16:18:35 +0000350public:
David Blaikie9f380a32015-03-16 18:06:57 +0000351 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000352
Tim Northover3b0846e2014-05-24 12:50:23 +0000353 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
354 Kind = o.Kind;
355 StartLoc = o.StartLoc;
356 EndLoc = o.EndLoc;
357 switch (Kind) {
358 case k_Token:
359 Tok = o.Tok;
360 break;
361 case k_Immediate:
362 Imm = o.Imm;
363 break;
364 case k_ShiftedImm:
365 ShiftedImm = o.ShiftedImm;
366 break;
367 case k_CondCode:
368 CondCode = o.CondCode;
369 break;
370 case k_FPImm:
371 FPImm = o.FPImm;
372 break;
373 case k_Barrier:
374 Barrier = o.Barrier;
375 break;
376 case k_Register:
377 Reg = o.Reg;
378 break;
379 case k_VectorList:
380 VectorList = o.VectorList;
381 break;
382 case k_VectorIndex:
383 VectorIndex = o.VectorIndex;
384 break;
385 case k_SysReg:
386 SysReg = o.SysReg;
387 break;
388 case k_SysCR:
389 SysCRImm = o.SysCRImm;
390 break;
391 case k_Prefetch:
392 Prefetch = o.Prefetch;
393 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000394 case k_PSBHint:
395 PSBHint = o.PSBHint;
396 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000397 case k_ShiftExtend:
398 ShiftExtend = o.ShiftExtend;
399 break;
400 }
401 }
402
403 /// getStartLoc - Get the location of the first token of this operand.
404 SMLoc getStartLoc() const override { return StartLoc; }
405 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000406 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000407
408 StringRef getToken() const {
409 assert(Kind == k_Token && "Invalid access!");
410 return StringRef(Tok.Data, Tok.Length);
411 }
412
413 bool isTokenSuffix() const {
414 assert(Kind == k_Token && "Invalid access!");
415 return Tok.IsSuffix;
416 }
417
418 const MCExpr *getImm() const {
419 assert(Kind == k_Immediate && "Invalid access!");
420 return Imm.Val;
421 }
422
423 const MCExpr *getShiftedImmVal() const {
424 assert(Kind == k_ShiftedImm && "Invalid access!");
425 return ShiftedImm.Val;
426 }
427
428 unsigned getShiftedImmShift() const {
429 assert(Kind == k_ShiftedImm && "Invalid access!");
430 return ShiftedImm.ShiftAmount;
431 }
432
433 AArch64CC::CondCode getCondCode() const {
434 assert(Kind == k_CondCode && "Invalid access!");
435 return CondCode.Code;
436 }
437
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000438 APFloat getFPImm() const {
439 assert (Kind == k_FPImm && "Invalid access!");
440 return APFloat(APFloat::IEEEdouble(), APInt(64, FPImm.Val, true));
441 }
442
443 bool getFPImmIsExact() const {
444 assert (Kind == k_FPImm && "Invalid access!");
445 return FPImm.IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +0000446 }
447
448 unsigned getBarrier() const {
449 assert(Kind == k_Barrier && "Invalid access!");
450 return Barrier.Val;
451 }
452
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000453 StringRef getBarrierName() const {
454 assert(Kind == k_Barrier && "Invalid access!");
455 return StringRef(Barrier.Data, Barrier.Length);
456 }
457
Tim Northover3b0846e2014-05-24 12:50:23 +0000458 unsigned getReg() const override {
459 assert(Kind == k_Register && "Invalid access!");
460 return Reg.RegNum;
461 }
462
Sander de Smalen0325e302018-07-02 07:34:52 +0000463 RegConstraintEqualityTy getRegEqualityTy() const {
464 assert(Kind == k_Register && "Invalid access!");
465 return Reg.EqualityTy;
466 }
467
Tim Northover3b0846e2014-05-24 12:50:23 +0000468 unsigned getVectorListStart() const {
469 assert(Kind == k_VectorList && "Invalid access!");
470 return VectorList.RegNum;
471 }
472
473 unsigned getVectorListCount() const {
474 assert(Kind == k_VectorList && "Invalid access!");
475 return VectorList.Count;
476 }
477
478 unsigned getVectorIndex() const {
479 assert(Kind == k_VectorIndex && "Invalid access!");
480 return VectorIndex.Val;
481 }
482
483 StringRef getSysReg() const {
484 assert(Kind == k_SysReg && "Invalid access!");
485 return StringRef(SysReg.Data, SysReg.Length);
486 }
487
Tim Northover3b0846e2014-05-24 12:50:23 +0000488 unsigned getSysCR() const {
489 assert(Kind == k_SysCR && "Invalid access!");
490 return SysCRImm.Val;
491 }
492
493 unsigned getPrefetch() const {
494 assert(Kind == k_Prefetch && "Invalid access!");
495 return Prefetch.Val;
496 }
497
Oliver Stannarda34e4702015-12-01 10:48:51 +0000498 unsigned getPSBHint() const {
499 assert(Kind == k_PSBHint && "Invalid access!");
500 return PSBHint.Val;
501 }
502
503 StringRef getPSBHintName() const {
504 assert(Kind == k_PSBHint && "Invalid access!");
505 return StringRef(PSBHint.Data, PSBHint.Length);
506 }
507
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000508 StringRef getPrefetchName() const {
509 assert(Kind == k_Prefetch && "Invalid access!");
510 return StringRef(Prefetch.Data, Prefetch.Length);
511 }
512
Tim Northover3b0846e2014-05-24 12:50:23 +0000513 AArch64_AM::ShiftExtendType getShiftExtendType() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000514 if (Kind == k_ShiftExtend)
515 return ShiftExtend.Type;
516 if (Kind == k_Register)
517 return Reg.ShiftExtend.Type;
518 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000519 }
520
521 unsigned getShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000522 if (Kind == k_ShiftExtend)
523 return ShiftExtend.Amount;
524 if (Kind == k_Register)
525 return Reg.ShiftExtend.Amount;
526 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000527 }
528
529 bool hasShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000530 if (Kind == k_ShiftExtend)
531 return ShiftExtend.HasExplicitAmount;
532 if (Kind == k_Register)
533 return Reg.ShiftExtend.HasExplicitAmount;
534 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000535 }
536
537 bool isImm() const override { return Kind == k_Immediate; }
538 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000539
Sjoerd Meijera3dad802018-07-06 12:32:33 +0000540 bool isUImm6() const {
541 if (!isImm())
542 return false;
543 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
544 if (!MCE)
545 return false;
546 int64_t Val = MCE->getValue();
547 return (Val >= 0 && Val < 64);
548 }
549
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000550 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
551
Sander de Smalen50ded902018-04-29 17:33:38 +0000552 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
553 return isImmScaled<Bits, Scale>(true);
554 }
555
556 template <int Bits, int Scale> DiagnosticPredicate isUImmScaled() const {
557 return isImmScaled<Bits, Scale>(false);
558 }
559
Sander de Smalenfe17a782018-04-26 12:54:42 +0000560 template <int Bits, int Scale>
Sander de Smalen50ded902018-04-29 17:33:38 +0000561 DiagnosticPredicate isImmScaled(bool Signed) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000562 if (!isImm())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000563 return DiagnosticPredicateTy::NoMatch;
564
Tim Northover3b0846e2014-05-24 12:50:23 +0000565 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
566 if (!MCE)
Sander de Smalenfe17a782018-04-26 12:54:42 +0000567 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000568
Sander de Smalen50ded902018-04-29 17:33:38 +0000569 int64_t MinVal, MaxVal;
570 if (Signed) {
571 int64_t Shift = Bits - 1;
572 MinVal = (int64_t(1) << Shift) * -Scale;
573 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
574 } else {
575 MinVal = 0;
576 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
577 }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000578
Tim Northover3b0846e2014-05-24 12:50:23 +0000579 int64_t Val = MCE->getValue();
Sander de Smalenfe17a782018-04-26 12:54:42 +0000580 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
581 return DiagnosticPredicateTy::Match;
582
583 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +0000584 }
585
Sander de Smalen0325e302018-07-02 07:34:52 +0000586 DiagnosticPredicate isSVEPattern() const {
Sander de Smalen245e0e62018-01-22 10:46:00 +0000587 if (!isImm())
Sander de Smalen0325e302018-07-02 07:34:52 +0000588 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000589 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
590 if (!MCE)
Sander de Smalen0325e302018-07-02 07:34:52 +0000591 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000592 int64_t Val = MCE->getValue();
Sander de Smalen0325e302018-07-02 07:34:52 +0000593 if (Val >= 0 && Val < 32)
594 return DiagnosticPredicateTy::Match;
595 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000596 }
597
Tim Northover3b0846e2014-05-24 12:50:23 +0000598 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
599 AArch64MCExpr::VariantKind ELFRefKind;
600 MCSymbolRefExpr::VariantKind DarwinRefKind;
601 int64_t Addend;
602 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
603 Addend)) {
604 // If we don't understand the expression, assume the best and
605 // let the fixup and relocation code deal with it.
606 return true;
607 }
608
609 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
610 ELFRefKind == AArch64MCExpr::VK_LO12 ||
611 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
612 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
613 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
614 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
615 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
616 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000617 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
618 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
619 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000620 // Note that we don't range-check the addend. It's adjusted modulo page
621 // size when converted, so there is no "out of range" condition when using
622 // @pageoff.
623 return Addend >= 0 && (Addend % Scale) == 0;
624 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
625 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
626 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
627 return Addend == 0;
628 }
629
630 return false;
631 }
632
633 template <int Scale> bool isUImm12Offset() const {
634 if (!isImm())
635 return false;
636
637 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
638 if (!MCE)
639 return isSymbolicUImm12Offset(getImm(), Scale);
640
641 int64_t Val = MCE->getValue();
642 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
643 }
644
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000645 template <int N, int M>
646 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000647 if (!isImm())
648 return false;
649 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
650 if (!MCE)
651 return false;
652 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000653 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000654 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000655
Sander de Smalena1c259c2018-01-29 13:05:38 +0000656 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
657 // a logical immediate can always be represented when inverted.
658 template <typename T>
659 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000660 if (!isImm())
661 return false;
662 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
663 if (!MCE)
664 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000665
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000666 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000667 int64_t SVal = typename std::make_signed<T>::type(Val);
668 int64_t UVal = typename std::make_unsigned<T>::type(Val);
669 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000670 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000671
Sander de Smalena1c259c2018-01-29 13:05:38 +0000672 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000673 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000674
Tim Northover3b0846e2014-05-24 12:50:23 +0000675 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000676
Sander de Smalen62770792018-05-25 09:47:52 +0000677 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
678 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
679 /// immediate that can be shifted by 'Shift'.
680 template <unsigned Width>
681 Optional<std::pair<int64_t, unsigned> > getShiftedVal() const {
682 if (isShiftedImm() && Width == getShiftedImmShift())
683 if (auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
684 return std::make_pair(CE->getValue(), Width);
685
686 if (isImm())
687 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
688 int64_t Val = CE->getValue();
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000689 if ((Val != 0) && (uint64_t(Val >> Width) << Width) == uint64_t(Val))
Sander de Smalen62770792018-05-25 09:47:52 +0000690 return std::make_pair(Val >> Width, Width);
691 else
692 return std::make_pair(Val, 0u);
693 }
694
695 return {};
696 }
697
Tim Northover3b0846e2014-05-24 12:50:23 +0000698 bool isAddSubImm() const {
699 if (!isShiftedImm() && !isImm())
700 return false;
701
702 const MCExpr *Expr;
703
704 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
705 if (isShiftedImm()) {
706 unsigned Shift = ShiftedImm.ShiftAmount;
707 Expr = ShiftedImm.Val;
708 if (Shift != 0 && Shift != 12)
709 return false;
710 } else {
711 Expr = getImm();
712 }
713
714 AArch64MCExpr::VariantKind ELFRefKind;
715 MCSymbolRefExpr::VariantKind DarwinRefKind;
716 int64_t Addend;
717 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
718 DarwinRefKind, Addend)) {
719 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
720 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
721 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
722 || ELFRefKind == AArch64MCExpr::VK_LO12
723 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
724 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
725 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
726 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
727 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
728 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000729 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
730 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
731 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000732 }
733
Sander de Smalen98686c62018-05-29 10:39:49 +0000734 // If it's a constant, it should be a real immediate in range.
Sander de Smalen62770792018-05-25 09:47:52 +0000735 if (auto ShiftedVal = getShiftedVal<12>())
736 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
Diana Picusc93518d2016-10-11 09:17:47 +0000737
738 // If it's an expression, we hope for the best and let the fixup/relocation
739 // code deal with it.
740 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000741 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000742
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000743 bool isAddSubImmNeg() const {
744 if (!isShiftedImm() && !isImm())
745 return false;
746
Sander de Smalen98686c62018-05-29 10:39:49 +0000747 // Otherwise it should be a real negative immediate in range.
748 if (auto ShiftedVal = getShiftedVal<12>())
749 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000750
Sander de Smalen98686c62018-05-29 10:39:49 +0000751 return false;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000752 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000753
Sander de Smalen62770792018-05-25 09:47:52 +0000754 // Signed value in the range -128 to +127. For element widths of
755 // 16 bits or higher it may also be a signed multiple of 256 in the
756 // range -32768 to +32512.
757 // For element-width of 8 bits a range of -128 to 255 is accepted,
758 // since a copy of a byte can be either signed/unsigned.
759 template <typename T>
760 DiagnosticPredicate isSVECpyImm() const {
761 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
762 return DiagnosticPredicateTy::NoMatch;
763
764 bool IsByte =
765 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
766 if (auto ShiftedImm = getShiftedVal<8>())
767 if (!(IsByte && ShiftedImm->second) &&
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000768 AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
769 << ShiftedImm->second))
Sander de Smalen62770792018-05-25 09:47:52 +0000770 return DiagnosticPredicateTy::Match;
771
772 return DiagnosticPredicateTy::NearMatch;
773 }
774
Sander de Smalen98686c62018-05-29 10:39:49 +0000775 // Unsigned value in the range 0 to 255. For element widths of
776 // 16 bits or higher it may also be a signed multiple of 256 in the
777 // range 0 to 65280.
778 template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
779 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
780 return DiagnosticPredicateTy::NoMatch;
781
782 bool IsByte =
783 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
784 if (auto ShiftedImm = getShiftedVal<8>())
785 if (!(IsByte && ShiftedImm->second) &&
786 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
787 << ShiftedImm->second))
788 return DiagnosticPredicateTy::Match;
789
790 return DiagnosticPredicateTy::NearMatch;
791 }
792
Sander de Smalen97ca6b92018-06-01 07:25:46 +0000793 template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
794 if (isLogicalImm<T>() && !isSVECpyImm<T>())
795 return DiagnosticPredicateTy::Match;
796 return DiagnosticPredicateTy::NoMatch;
797 }
798
Tim Northover3b0846e2014-05-24 12:50:23 +0000799 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000800
Tim Northover3b0846e2014-05-24 12:50:23 +0000801 bool isSIMDImmType10() const {
802 if (!isImm())
803 return false;
804 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
805 if (!MCE)
806 return false;
807 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
808 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000809
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000810 template<int N>
811 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000812 if (!isImm())
813 return false;
814 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
815 if (!MCE)
816 return true;
817 int64_t Val = MCE->getValue();
818 if (Val & 0x3)
819 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000820 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
821 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000822 }
823
824 bool
825 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
826 if (!isImm())
827 return false;
828
829 AArch64MCExpr::VariantKind ELFRefKind;
830 MCSymbolRefExpr::VariantKind DarwinRefKind;
831 int64_t Addend;
832 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
833 DarwinRefKind, Addend)) {
834 return false;
835 }
836 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
837 return false;
838
839 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
840 if (ELFRefKind == AllowedModifiers[i])
841 return Addend == 0;
842 }
843
844 return false;
845 }
846
847 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000848 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000849 }
850
851 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000852 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
853 AArch64MCExpr::VK_TPREL_G2,
854 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000855 }
856
857 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000858 return isMovWSymbol({
859 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000860 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
861 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000862 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000863 }
864
865 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000866 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
867 AArch64MCExpr::VK_TPREL_G0,
868 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000869 }
870
871 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000872 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000873 }
874
875 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000876 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000877 }
878
879 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000880 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
881 AArch64MCExpr::VK_TPREL_G1_NC,
882 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000883 }
884
885 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000886 return isMovWSymbol(
887 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
888 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000889 }
890
891 template<int RegWidth, int Shift>
892 bool isMOVZMovAlias() const {
893 if (!isImm()) return false;
894
895 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
896 if (!CE) return false;
897 uint64_t Value = CE->getValue();
898
Tim Northoverdaa1c012016-06-16 01:42:25 +0000899 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000900 }
901
902 template<int RegWidth, int Shift>
903 bool isMOVNMovAlias() const {
904 if (!isImm()) return false;
905
906 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
907 if (!CE) return false;
908 uint64_t Value = CE->getValue();
909
Tim Northoverdaa1c012016-06-16 01:42:25 +0000910 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000911 }
912
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000913 bool isFPImm() const {
914 return Kind == k_FPImm &&
915 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt()) != -1;
916 }
917
Tim Northover3b0846e2014-05-24 12:50:23 +0000918 bool isBarrier() const { return Kind == k_Barrier; }
919 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000920
Tim Northover3b0846e2014-05-24 12:50:23 +0000921 bool isMRSSystemRegister() const {
922 if (!isSysReg()) return false;
923
Tim Northover7cd58932015-01-22 17:23:04 +0000924 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000925 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000926
Tim Northover3b0846e2014-05-24 12:50:23 +0000927 bool isMSRSystemRegister() const {
928 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000929 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000930 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000931
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000932 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000933 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000934 return (SysReg.PStateField == AArch64PState::PAN ||
Sjoerd Meijer173b7f02018-07-03 12:09:20 +0000935 SysReg.PStateField == AArch64PState::DIT ||
Oliver Stannard911ea202015-11-26 15:32:30 +0000936 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000937 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000938
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000939 bool isSystemPStateFieldWithImm0_15() const {
940 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000941 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000942 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000943
Florian Hahnc4422242017-11-07 13:07:50 +0000944 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000945 return Kind == k_Register;
946 }
947
948 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000949 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
950 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000951
Florian Hahnc4422242017-11-07 13:07:50 +0000952 bool isNeonVectorReg() const {
953 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
954 }
955
956 bool isNeonVectorRegLo() const {
957 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000958 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
959 Reg.RegNum);
960 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000961
Sander de Smalencd6be962017-12-20 11:02:42 +0000962 template <unsigned Class> bool isSVEVectorReg() const {
963 RegKind RK;
964 switch (Class) {
965 case AArch64::ZPRRegClassID:
Sander de Smalen8cd1f532018-07-03 15:31:04 +0000966 case AArch64::ZPR_3bRegClassID:
967 case AArch64::ZPR_4bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000968 RK = RegKind::SVEDataVector;
969 break;
970 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000971 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000972 RK = RegKind::SVEPredicateVector;
973 break;
974 default:
975 llvm_unreachable("Unsupport register class");
976 }
977
978 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000979 AArch64MCRegisterClasses[Class].contains(getReg());
980 }
981
Sander de Smalenfd54a782018-06-04 07:07:35 +0000982 template <unsigned Class> bool isFPRasZPR() const {
983 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
984 AArch64MCRegisterClasses[Class].contains(getReg());
985 }
986
Sander de Smalencd6be962017-12-20 11:02:42 +0000987 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +0000988 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
989 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
990 return DiagnosticPredicateTy::NoMatch;
991
992 if (isSVEVectorReg<Class>() &&
993 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
994 return DiagnosticPredicateTy::Match;
995
996 return DiagnosticPredicateTy::NearMatch;
997 }
998
999 template <int ElementWidth, unsigned Class>
1000 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
1001 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
1002 return DiagnosticPredicateTy::NoMatch;
1003
1004 if (isSVEVectorReg<Class>() &&
1005 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
1006 return DiagnosticPredicateTy::Match;
1007
1008 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00001009 }
1010
Sander de Smaleneb896b12018-04-25 09:26:47 +00001011 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +00001012 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
1013 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +00001014 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
1015 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
1016 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001017 return DiagnosticPredicateTy::NoMatch;
1018
Sander de Smalen5861c262018-04-30 07:24:38 +00001019 // Give a more specific diagnostic when the user has explicitly typed in
1020 // a shift-amount that does not match what is expected, but for which
1021 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
1022 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
1023 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
1024 ShiftExtendTy == AArch64_AM::SXTW) &&
1025 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
1026 return DiagnosticPredicateTy::NoMatch;
1027
1028 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001029 return DiagnosticPredicateTy::Match;
1030
1031 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +00001032 }
1033
Tim Northover3b0846e2014-05-24 12:50:23 +00001034 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001035 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001036 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
1037 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001038
Sander de Smalen0325e302018-07-02 07:34:52 +00001039 bool isGPR64as32() const {
1040 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1041 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(Reg.RegNum);
1042 }
1043
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001044 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001045 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001046 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
1047 Reg.RegNum);
1048 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001049
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001050 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001051 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001052 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1053 Reg.RegNum);
1054 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001055
Sam Parker5f934642017-08-31 09:27:04 +00001056 template<int64_t Angle, int64_t Remainder>
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001057 DiagnosticPredicate isComplexRotation() const {
1058 if (!isImm()) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001059
1060 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001061 if (!CE) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001062 uint64_t Value = CE->getValue();
1063
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001064 if (Value % Angle == Remainder && Value <= 270)
1065 return DiagnosticPredicateTy::Match;
1066 return DiagnosticPredicateTy::NearMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001067 }
1068
Sander de Smalen149916d2018-04-20 07:24:20 +00001069 template <unsigned RegClassID> bool isGPR64() const {
1070 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1071 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1072 }
1073
1074 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001075 DiagnosticPredicate isGPR64WithShiftExtend() const {
1076 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1077 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001078
Sander de Smalenfe17a782018-04-26 12:54:42 +00001079 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1080 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1081 return DiagnosticPredicateTy::Match;
1082 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001083 }
1084
Tim Northover3b0846e2014-05-24 12:50:23 +00001085 /// Is this a vector list with the type implicit (presumably attached to the
1086 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001087 template <RegKind VectorKind, unsigned NumRegs>
1088 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001089 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001090 VectorList.NumElements == 0 &&
1091 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001092 }
1093
Sander de Smalen650234b2018-04-12 11:40:52 +00001094 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1095 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001096 bool isTypedVectorList() const {
1097 if (Kind != k_VectorList)
1098 return false;
1099 if (VectorList.Count != NumRegs)
1100 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001101 if (VectorList.RegisterKind != VectorKind)
1102 return false;
1103 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001104 return false;
1105 return VectorList.NumElements == NumElements;
1106 }
1107
Sander de Smalenc33d6682018-06-04 06:40:55 +00001108 template <int Min, int Max>
1109 DiagnosticPredicate isVectorIndex() const {
1110 if (Kind != k_VectorIndex)
1111 return DiagnosticPredicateTy::NoMatch;
1112 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1113 return DiagnosticPredicateTy::Match;
1114 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001115 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001116
Tim Northover3b0846e2014-05-24 12:50:23 +00001117 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001118
Tim Northover3b0846e2014-05-24 12:50:23 +00001119 bool isTokenEqual(StringRef Str) const {
1120 return Kind == k_Token && getToken() == Str;
1121 }
1122 bool isSysCR() const { return Kind == k_SysCR; }
1123 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001124 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001125 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1126 bool isShifter() const {
1127 if (!isShiftExtend())
1128 return false;
1129
1130 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1131 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1132 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1133 ST == AArch64_AM::MSL);
1134 }
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001135
1136 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1137 if (Kind != k_FPImm)
1138 return DiagnosticPredicateTy::NoMatch;
1139
1140 if (getFPImmIsExact()) {
1141 // Lookup the immediate from table of supported immediates.
1142 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1143 assert(Desc && "Unknown enum value");
1144
1145 // Calculate its FP value.
1146 APFloat RealVal(APFloat::IEEEdouble());
1147 if (RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero) !=
1148 APFloat::opOK)
1149 llvm_unreachable("FP immediate is not exact");
1150
1151 if (getFPImm().bitwiseIsEqual(RealVal))
1152 return DiagnosticPredicateTy::Match;
1153 }
1154
1155 return DiagnosticPredicateTy::NearMatch;
1156 }
1157
1158 template <unsigned ImmA, unsigned ImmB>
1159 DiagnosticPredicate isExactFPImm() const {
1160 DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1161 if ((Res = isExactFPImm<ImmA>()))
1162 return DiagnosticPredicateTy::Match;
1163 if ((Res = isExactFPImm<ImmB>()))
1164 return DiagnosticPredicateTy::Match;
1165 return Res;
1166 }
1167
Tim Northover3b0846e2014-05-24 12:50:23 +00001168 bool isExtend() const {
1169 if (!isShiftExtend())
1170 return false;
1171
1172 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1173 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1174 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1175 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1176 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1177 ET == AArch64_AM::LSL) &&
1178 getShiftExtendAmount() <= 4;
1179 }
1180
1181 bool isExtend64() const {
1182 if (!isExtend())
1183 return false;
1184 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1185 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1186 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1187 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001188
Tim Northover3b0846e2014-05-24 12:50:23 +00001189 bool isExtendLSL64() const {
1190 if (!isExtend())
1191 return false;
1192 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1193 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1194 ET == AArch64_AM::LSL) &&
1195 getShiftExtendAmount() <= 4;
1196 }
1197
1198 template<int Width> bool isMemXExtend() const {
1199 if (!isExtend())
1200 return false;
1201 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1202 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1203 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1204 getShiftExtendAmount() == 0);
1205 }
1206
1207 template<int Width> bool isMemWExtend() const {
1208 if (!isExtend())
1209 return false;
1210 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1211 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1212 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1213 getShiftExtendAmount() == 0);
1214 }
1215
1216 template <unsigned width>
1217 bool isArithmeticShifter() const {
1218 if (!isShifter())
1219 return false;
1220
1221 // An arithmetic shifter is LSL, LSR, or ASR.
1222 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1223 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1224 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1225 }
1226
1227 template <unsigned width>
1228 bool isLogicalShifter() const {
1229 if (!isShifter())
1230 return false;
1231
1232 // A logical shifter is LSL, LSR, ASR or ROR.
1233 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1234 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1235 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1236 getShiftExtendAmount() < width;
1237 }
1238
1239 bool isMovImm32Shifter() const {
1240 if (!isShifter())
1241 return false;
1242
1243 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1244 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1245 if (ST != AArch64_AM::LSL)
1246 return false;
1247 uint64_t Val = getShiftExtendAmount();
1248 return (Val == 0 || Val == 16);
1249 }
1250
1251 bool isMovImm64Shifter() const {
1252 if (!isShifter())
1253 return false;
1254
1255 // A MOVi shifter is LSL of 0 or 16.
1256 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1257 if (ST != AArch64_AM::LSL)
1258 return false;
1259 uint64_t Val = getShiftExtendAmount();
1260 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1261 }
1262
1263 bool isLogicalVecShifter() const {
1264 if (!isShifter())
1265 return false;
1266
1267 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1268 unsigned Shift = getShiftExtendAmount();
1269 return getShiftExtendType() == AArch64_AM::LSL &&
1270 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1271 }
1272
1273 bool isLogicalVecHalfWordShifter() const {
1274 if (!isLogicalVecShifter())
1275 return false;
1276
1277 // A logical vector shifter is a left shift by 0 or 8.
1278 unsigned Shift = getShiftExtendAmount();
1279 return getShiftExtendType() == AArch64_AM::LSL &&
1280 (Shift == 0 || Shift == 8);
1281 }
1282
1283 bool isMoveVecShifter() const {
1284 if (!isShiftExtend())
1285 return false;
1286
1287 // A logical vector shifter is a left shift by 8 or 16.
1288 unsigned Shift = getShiftExtendAmount();
1289 return getShiftExtendType() == AArch64_AM::MSL &&
1290 (Shift == 8 || Shift == 16);
1291 }
1292
1293 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1294 // to LDUR/STUR when the offset is not legal for the former but is for
1295 // the latter. As such, in addition to checking for being a legal unscaled
1296 // address, also check that it is not a legal scaled address. This avoids
1297 // ambiguity in the matcher.
1298 template<int Width>
1299 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001300 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001301 }
1302
1303 bool isAdrpLabel() const {
1304 // Validation was handled during parsing, so we just sanity check that
1305 // something didn't go haywire.
1306 if (!isImm())
1307 return false;
1308
1309 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1310 int64_t Val = CE->getValue();
1311 int64_t Min = - (4096 * (1LL << (21 - 1)));
1312 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1313 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1314 }
1315
1316 return true;
1317 }
1318
1319 bool isAdrLabel() const {
1320 // Validation was handled during parsing, so we just sanity check that
1321 // something didn't go haywire.
1322 if (!isImm())
1323 return false;
1324
1325 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1326 int64_t Val = CE->getValue();
1327 int64_t Min = - (1LL << (21 - 1));
1328 int64_t Max = ((1LL << (21 - 1)) - 1);
1329 return Val >= Min && Val <= Max;
1330 }
1331
1332 return true;
1333 }
1334
1335 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1336 // Add as immediates when possible. Null MCExpr = 0.
1337 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001338 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001339 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001340 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001341 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001342 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001343 }
1344
1345 void addRegOperands(MCInst &Inst, unsigned N) const {
1346 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001347 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001348 }
1349
1350 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1351 assert(N == 1 && "Invalid number of operands!");
1352 assert(
1353 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1354
1355 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1356 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1357 RI->getEncodingValue(getReg()));
1358
Jim Grosbache9119e42015-05-13 18:37:00 +00001359 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001360 }
1361
Sander de Smalen0325e302018-07-02 07:34:52 +00001362 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1363 assert(N == 1 && "Invalid number of operands!");
1364 assert(
1365 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(getReg()));
1366
1367 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1368 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID).getRegister(
1369 RI->getEncodingValue(getReg()));
1370
1371 Inst.addOperand(MCOperand::createReg(Reg));
1372 }
1373
Sander de Smalenfd54a782018-06-04 07:07:35 +00001374 template <int Width>
1375 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1376 unsigned Base;
1377 switch (Width) {
1378 case 8: Base = AArch64::B0; break;
1379 case 16: Base = AArch64::H0; break;
1380 case 32: Base = AArch64::S0; break;
1381 case 64: Base = AArch64::D0; break;
1382 case 128: Base = AArch64::Q0; break;
1383 default:
1384 llvm_unreachable("Unsupported width");
1385 }
1386 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1387 }
1388
Tim Northover3b0846e2014-05-24 12:50:23 +00001389 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1390 assert(N == 1 && "Invalid number of operands!");
1391 assert(
1392 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001393 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001394 }
1395
1396 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1397 assert(N == 1 && "Invalid number of operands!");
1398 assert(
1399 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001400 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001401 }
1402
1403 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1404 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001405 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001406 }
1407
Sander de Smalen525e3222018-04-12 13:19:32 +00001408 enum VecListIndexType {
1409 VecListIdx_DReg = 0,
1410 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001411 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001412 };
1413
1414 template <VecListIndexType RegTy, unsigned NumRegs>
1415 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001416 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001417 static const unsigned FirstRegs[][5] = {
1418 /* DReg */ { AArch64::Q0,
1419 AArch64::D0, AArch64::D0_D1,
1420 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1421 /* QReg */ { AArch64::Q0,
1422 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001423 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1424 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001425 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001426 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001427 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001428
Sander de Smalen7a210db2018-04-16 10:46:18 +00001429 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1430 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001431
Sander de Smalen525e3222018-04-12 13:19:32 +00001432 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1433 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1434 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001435 }
1436
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001437 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001438 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001439 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001440 }
1441
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001442 template <unsigned ImmIs0, unsigned ImmIs1>
1443 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1444 assert(N == 1 && "Invalid number of operands!");
1445 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1446 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1447 }
1448
Tim Northover3b0846e2014-05-24 12:50:23 +00001449 void addImmOperands(MCInst &Inst, unsigned N) const {
1450 assert(N == 1 && "Invalid number of operands!");
1451 // If this is a pageoff symrefexpr with an addend, adjust the addend
1452 // to be only the page-offset portion. Otherwise, just add the expr
1453 // as-is.
1454 addExpr(Inst, getImm());
1455 }
1456
Sander de Smalen62770792018-05-25 09:47:52 +00001457 template <int Shift>
1458 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001459 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001460 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1461 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1462 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1463 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001464 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001465 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001466 } else {
1467 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001468 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001469 }
1470 }
1471
Sander de Smalen62770792018-05-25 09:47:52 +00001472 template <int Shift>
1473 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001474 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001475 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1476 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1477 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1478 } else
1479 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001480 }
1481
Tim Northover3b0846e2014-05-24 12:50:23 +00001482 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1483 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001484 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001485 }
1486
1487 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1488 assert(N == 1 && "Invalid number of operands!");
1489 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1490 if (!MCE)
1491 addExpr(Inst, getImm());
1492 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001493 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001494 }
1495
1496 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1497 addImmOperands(Inst, N);
1498 }
1499
1500 template<int Scale>
1501 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1502 assert(N == 1 && "Invalid number of operands!");
1503 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1504
1505 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001506 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001507 return;
1508 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001509 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001510 }
1511
Sjoerd Meijera3dad802018-07-06 12:32:33 +00001512 void addUImm6Operands(MCInst &Inst, unsigned N) const {
1513 assert(N == 1 && "Invalid number of operands!");
1514 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1515 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1516 }
1517
Sander de Smalen5c625982018-04-13 12:56:14 +00001518 template <int Scale>
1519 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1520 assert(N == 1 && "Invalid number of operands!");
1521 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1522 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1523 }
1524
Sander de Smalena1c259c2018-01-29 13:05:38 +00001525 template <typename T>
1526 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001527 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001528 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001529 typename std::make_unsigned<T>::type Val = MCE->getValue();
1530 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001531 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001532 }
1533
Sander de Smalena1c259c2018-01-29 13:05:38 +00001534 template <typename T>
1535 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001536 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001537 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001538 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1539 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001540 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001541 }
1542
Tim Northover3b0846e2014-05-24 12:50:23 +00001543 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1544 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001545 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001546 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001547 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001548 }
1549
1550 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1551 // Branch operands don't encode the low bits, so shift them off
1552 // here. If it's a label, however, just put it on directly as there's
1553 // not enough information now to do anything.
1554 assert(N == 1 && "Invalid number of operands!");
1555 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1556 if (!MCE) {
1557 addExpr(Inst, getImm());
1558 return;
1559 }
1560 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001561 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001562 }
1563
1564 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1565 // Branch operands don't encode the low bits, so shift them off
1566 // here. If it's a label, however, just put it on directly as there's
1567 // not enough information now to do anything.
1568 assert(N == 1 && "Invalid number of operands!");
1569 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1570 if (!MCE) {
1571 addExpr(Inst, getImm());
1572 return;
1573 }
1574 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001575 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001576 }
1577
1578 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1579 // Branch operands don't encode the low bits, so shift them off
1580 // here. If it's a label, however, just put it on directly as there's
1581 // not enough information now to do anything.
1582 assert(N == 1 && "Invalid number of operands!");
1583 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1584 if (!MCE) {
1585 addExpr(Inst, getImm());
1586 return;
1587 }
1588 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001589 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001590 }
1591
1592 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1593 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001594 Inst.addOperand(MCOperand::createImm(
1595 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
Tim Northover3b0846e2014-05-24 12:50:23 +00001596 }
1597
1598 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1599 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001600 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001601 }
1602
1603 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1604 assert(N == 1 && "Invalid number of operands!");
1605
Jim Grosbache9119e42015-05-13 18:37:00 +00001606 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001607 }
1608
1609 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1610 assert(N == 1 && "Invalid number of operands!");
1611
Jim Grosbache9119e42015-05-13 18:37:00 +00001612 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001613 }
1614
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001615 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1616 assert(N == 1 && "Invalid number of operands!");
1617
1618 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1619 }
1620
1621 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001622 assert(N == 1 && "Invalid number of operands!");
1623
Jim Grosbache9119e42015-05-13 18:37:00 +00001624 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001625 }
1626
1627 void addSysCROperands(MCInst &Inst, unsigned N) const {
1628 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001629 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001630 }
1631
1632 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1633 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001634 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001635 }
1636
Oliver Stannarda34e4702015-12-01 10:48:51 +00001637 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1638 assert(N == 1 && "Invalid number of operands!");
1639 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1640 }
1641
Tim Northover3b0846e2014-05-24 12:50:23 +00001642 void addShifterOperands(MCInst &Inst, unsigned N) const {
1643 assert(N == 1 && "Invalid number of operands!");
1644 unsigned Imm =
1645 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001646 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001647 }
1648
1649 void addExtendOperands(MCInst &Inst, unsigned N) const {
1650 assert(N == 1 && "Invalid number of operands!");
1651 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1652 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1653 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001654 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001655 }
1656
1657 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1658 assert(N == 1 && "Invalid number of operands!");
1659 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1660 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1661 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001662 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001663 }
1664
1665 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1666 assert(N == 2 && "Invalid number of operands!");
1667 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1668 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001669 Inst.addOperand(MCOperand::createImm(IsSigned));
1670 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001671 }
1672
1673 // For 8-bit load/store instructions with a register offset, both the
1674 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1675 // they're disambiguated by whether the shift was explicit or implicit rather
1676 // than its size.
1677 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1678 assert(N == 2 && "Invalid number of operands!");
1679 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1680 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001681 Inst.addOperand(MCOperand::createImm(IsSigned));
1682 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001683 }
1684
1685 template<int Shift>
1686 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1687 assert(N == 1 && "Invalid number of operands!");
1688
1689 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1690 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001691 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001692 }
1693
1694 template<int Shift>
1695 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1696 assert(N == 1 && "Invalid number of operands!");
1697
1698 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1699 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001700 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001701 }
1702
Sam Parker5f934642017-08-31 09:27:04 +00001703 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1704 assert(N == 1 && "Invalid number of operands!");
1705 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1706 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1707 }
1708
1709 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1710 assert(N == 1 && "Invalid number of operands!");
1711 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1712 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1713 }
1714
Tim Northover3b0846e2014-05-24 12:50:23 +00001715 void print(raw_ostream &OS) const override;
1716
David Blaikie960ea3f2014-06-08 16:18:35 +00001717 static std::unique_ptr<AArch64Operand>
1718 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1719 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001720 Op->Tok.Data = Str.data();
1721 Op->Tok.Length = Str.size();
1722 Op->Tok.IsSuffix = IsSuffix;
1723 Op->StartLoc = S;
1724 Op->EndLoc = S;
1725 return Op;
1726 }
1727
David Blaikie960ea3f2014-06-08 16:18:35 +00001728 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001729 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
Sander de Smalen0325e302018-07-02 07:34:52 +00001730 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
Sander de Smalen149916d2018-04-20 07:24:20 +00001731 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1732 unsigned ShiftAmount = 0,
1733 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001734 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001735 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001736 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001737 Op->Reg.ElementWidth = 0;
Sander de Smalen0325e302018-07-02 07:34:52 +00001738 Op->Reg.EqualityTy = EqTy;
Sander de Smalen149916d2018-04-20 07:24:20 +00001739 Op->Reg.ShiftExtend.Type = ExtTy;
1740 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1741 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001742 Op->StartLoc = S;
1743 Op->EndLoc = E;
1744 return Op;
1745 }
1746
David Blaikie960ea3f2014-06-08 16:18:35 +00001747 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001748 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001749 SMLoc S, SMLoc E, MCContext &Ctx,
1750 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1751 unsigned ShiftAmount = 0,
1752 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001753 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1754 Kind == RegKind::SVEPredicateVector) &&
1755 "Invalid vector kind");
Sander de Smalen0325e302018-07-02 07:34:52 +00001756 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
Sander de Smalen149916d2018-04-20 07:24:20 +00001757 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001758 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001759 return Op;
1760 }
1761
1762 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001763 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001764 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1765 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001766 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001767 Op->VectorList.RegNum = RegNum;
1768 Op->VectorList.Count = Count;
1769 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001770 Op->VectorList.ElementWidth = ElementWidth;
1771 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001772 Op->StartLoc = S;
1773 Op->EndLoc = E;
1774 return Op;
1775 }
1776
David Blaikie960ea3f2014-06-08 16:18:35 +00001777 static std::unique_ptr<AArch64Operand>
1778 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1779 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001780 Op->VectorIndex.Val = Idx;
1781 Op->StartLoc = S;
1782 Op->EndLoc = E;
1783 return Op;
1784 }
1785
David Blaikie960ea3f2014-06-08 16:18:35 +00001786 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1787 SMLoc E, MCContext &Ctx) {
1788 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001789 Op->Imm.Val = Val;
1790 Op->StartLoc = S;
1791 Op->EndLoc = E;
1792 return Op;
1793 }
1794
David Blaikie960ea3f2014-06-08 16:18:35 +00001795 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1796 unsigned ShiftAmount,
1797 SMLoc S, SMLoc E,
1798 MCContext &Ctx) {
1799 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001800 Op->ShiftedImm .Val = Val;
1801 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1802 Op->StartLoc = S;
1803 Op->EndLoc = E;
1804 return Op;
1805 }
1806
David Blaikie960ea3f2014-06-08 16:18:35 +00001807 static std::unique_ptr<AArch64Operand>
1808 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1809 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001810 Op->CondCode.Code = Code;
1811 Op->StartLoc = S;
1812 Op->EndLoc = E;
1813 return Op;
1814 }
1815
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001816 static std::unique_ptr<AArch64Operand>
1817 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001818 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001819 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
1820 Op->FPImm.IsExact = IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +00001821 Op->StartLoc = S;
1822 Op->EndLoc = S;
1823 return Op;
1824 }
1825
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001826 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1827 StringRef Str,
1828 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001829 MCContext &Ctx) {
1830 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001831 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001832 Op->Barrier.Data = Str.data();
1833 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001834 Op->StartLoc = S;
1835 Op->EndLoc = S;
1836 return Op;
1837 }
1838
Tim Northover7cd58932015-01-22 17:23:04 +00001839 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1840 uint32_t MRSReg,
1841 uint32_t MSRReg,
1842 uint32_t PStateField,
1843 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001844 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001845 Op->SysReg.Data = Str.data();
1846 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001847 Op->SysReg.MRSReg = MRSReg;
1848 Op->SysReg.MSRReg = MSRReg;
1849 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001850 Op->StartLoc = S;
1851 Op->EndLoc = S;
1852 return Op;
1853 }
1854
David Blaikie960ea3f2014-06-08 16:18:35 +00001855 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1856 SMLoc E, MCContext &Ctx) {
1857 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001858 Op->SysCRImm.Val = Val;
1859 Op->StartLoc = S;
1860 Op->EndLoc = E;
1861 return Op;
1862 }
1863
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001864 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1865 StringRef Str,
1866 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001867 MCContext &Ctx) {
1868 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001869 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001870 Op->Barrier.Data = Str.data();
1871 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001872 Op->StartLoc = S;
1873 Op->EndLoc = S;
1874 return Op;
1875 }
1876
Oliver Stannarda34e4702015-12-01 10:48:51 +00001877 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1878 StringRef Str,
1879 SMLoc S,
1880 MCContext &Ctx) {
1881 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1882 Op->PSBHint.Val = Val;
1883 Op->PSBHint.Data = Str.data();
1884 Op->PSBHint.Length = Str.size();
1885 Op->StartLoc = S;
1886 Op->EndLoc = S;
1887 return Op;
1888 }
1889
David Blaikie960ea3f2014-06-08 16:18:35 +00001890 static std::unique_ptr<AArch64Operand>
1891 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1892 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1893 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001894 Op->ShiftExtend.Type = ShOp;
1895 Op->ShiftExtend.Amount = Val;
1896 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1897 Op->StartLoc = S;
1898 Op->EndLoc = E;
1899 return Op;
1900 }
1901};
1902
1903} // end anonymous namespace.
1904
1905void AArch64Operand::print(raw_ostream &OS) const {
1906 switch (Kind) {
1907 case k_FPImm:
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001908 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
1909 if (!getFPImmIsExact())
1910 OS << " (inexact)";
1911 OS << ">";
Tim Northover3b0846e2014-05-24 12:50:23 +00001912 break;
1913 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001914 StringRef Name = getBarrierName();
1915 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001916 OS << "<barrier " << Name << ">";
1917 else
1918 OS << "<barrier invalid #" << getBarrier() << ">";
1919 break;
1920 }
1921 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001922 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001923 break;
1924 case k_ShiftedImm: {
1925 unsigned Shift = getShiftedImmShift();
1926 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001927 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001928 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1929 break;
1930 }
1931 case k_CondCode:
1932 OS << "<condcode " << getCondCode() << ">";
1933 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001934 case k_VectorList: {
1935 OS << "<vectorlist ";
1936 unsigned Reg = getVectorListStart();
1937 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1938 OS << Reg + i << " ";
1939 OS << ">";
1940 break;
1941 }
1942 case k_VectorIndex:
1943 OS << "<vectorindex " << getVectorIndex() << ">";
1944 break;
1945 case k_SysReg:
1946 OS << "<sysreg: " << getSysReg() << '>';
1947 break;
1948 case k_Token:
1949 OS << "'" << getToken() << "'";
1950 break;
1951 case k_SysCR:
1952 OS << "c" << getSysCR();
1953 break;
1954 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001955 StringRef Name = getPrefetchName();
1956 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001957 OS << "<prfop " << Name << ">";
1958 else
1959 OS << "<prfop invalid #" << getPrefetch() << ">";
1960 break;
1961 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001962 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001963 OS << getPSBHintName();
1964 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00001965 case k_Register:
1966 OS << "<register " << getReg() << ">";
1967 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
1968 break;
1969 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001970 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001971 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1972 << getShiftExtendAmount();
1973 if (!hasShiftExtendAmount())
1974 OS << "<imp>";
1975 OS << '>';
1976 break;
1977 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001978}
1979
1980/// @name Auto-generated Match Functions
1981/// {
1982
1983static unsigned MatchRegisterName(StringRef Name);
1984
1985/// }
1986
Florian Hahnc4422242017-11-07 13:07:50 +00001987static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001988 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001989 .Case("v0", AArch64::Q0)
1990 .Case("v1", AArch64::Q1)
1991 .Case("v2", AArch64::Q2)
1992 .Case("v3", AArch64::Q3)
1993 .Case("v4", AArch64::Q4)
1994 .Case("v5", AArch64::Q5)
1995 .Case("v6", AArch64::Q6)
1996 .Case("v7", AArch64::Q7)
1997 .Case("v8", AArch64::Q8)
1998 .Case("v9", AArch64::Q9)
1999 .Case("v10", AArch64::Q10)
2000 .Case("v11", AArch64::Q11)
2001 .Case("v12", AArch64::Q12)
2002 .Case("v13", AArch64::Q13)
2003 .Case("v14", AArch64::Q14)
2004 .Case("v15", AArch64::Q15)
2005 .Case("v16", AArch64::Q16)
2006 .Case("v17", AArch64::Q17)
2007 .Case("v18", AArch64::Q18)
2008 .Case("v19", AArch64::Q19)
2009 .Case("v20", AArch64::Q20)
2010 .Case("v21", AArch64::Q21)
2011 .Case("v22", AArch64::Q22)
2012 .Case("v23", AArch64::Q23)
2013 .Case("v24", AArch64::Q24)
2014 .Case("v25", AArch64::Q25)
2015 .Case("v26", AArch64::Q26)
2016 .Case("v27", AArch64::Q27)
2017 .Case("v28", AArch64::Q28)
2018 .Case("v29", AArch64::Q29)
2019 .Case("v30", AArch64::Q30)
2020 .Case("v31", AArch64::Q31)
2021 .Default(0);
2022}
2023
Sander de Smalen73937b72018-04-11 07:36:10 +00002024/// Returns an optional pair of (#elements, element-width) if Suffix
2025/// is a valid vector kind. Where the number of elements in a vector
2026/// or the vector width is implicit or explicitly unknown (but still a
2027/// valid suffix kind), 0 is used.
2028static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2029 RegKind VectorKind) {
2030 std::pair<int, int> Res = {-1, -1};
2031
2032 switch (VectorKind) {
2033 case RegKind::NeonVector:
2034 Res =
2035 StringSwitch<std::pair<int, int>>(Suffix.lower())
2036 .Case("", {0, 0})
2037 .Case(".1d", {1, 64})
2038 .Case(".1q", {1, 128})
2039 // '.2h' needed for fp16 scalar pairwise reductions
2040 .Case(".2h", {2, 16})
2041 .Case(".2s", {2, 32})
2042 .Case(".2d", {2, 64})
2043 // '.4b' is another special case for the ARMv8.2a dot product
2044 // operand
2045 .Case(".4b", {4, 8})
2046 .Case(".4h", {4, 16})
2047 .Case(".4s", {4, 32})
2048 .Case(".8b", {8, 8})
2049 .Case(".8h", {8, 16})
2050 .Case(".16b", {16, 8})
2051 // Accept the width neutral ones, too, for verbose syntax. If those
2052 // aren't used in the right places, the token operand won't match so
2053 // all will work out.
2054 .Case(".b", {0, 8})
2055 .Case(".h", {0, 16})
2056 .Case(".s", {0, 32})
2057 .Case(".d", {0, 64})
2058 .Default({-1, -1});
2059 break;
2060 case RegKind::SVEPredicateVector:
2061 case RegKind::SVEDataVector:
2062 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2063 .Case("", {0, 0})
2064 .Case(".b", {0, 8})
2065 .Case(".h", {0, 16})
2066 .Case(".s", {0, 32})
2067 .Case(".d", {0, 64})
2068 .Case(".q", {0, 128})
2069 .Default({-1, -1});
2070 break;
2071 default:
2072 llvm_unreachable("Unsupported RegKind");
2073 }
2074
2075 if (Res == std::make_pair(-1, -1))
2076 return Optional<std::pair<int, int>>();
2077
2078 return Optional<std::pair<int, int>>(Res);
2079}
2080
2081static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2082 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002083}
2084
Florian Hahn91f11e52017-11-07 16:45:48 +00002085static unsigned matchSVEDataVectorRegName(StringRef Name) {
2086 return StringSwitch<unsigned>(Name.lower())
2087 .Case("z0", AArch64::Z0)
2088 .Case("z1", AArch64::Z1)
2089 .Case("z2", AArch64::Z2)
2090 .Case("z3", AArch64::Z3)
2091 .Case("z4", AArch64::Z4)
2092 .Case("z5", AArch64::Z5)
2093 .Case("z6", AArch64::Z6)
2094 .Case("z7", AArch64::Z7)
2095 .Case("z8", AArch64::Z8)
2096 .Case("z9", AArch64::Z9)
2097 .Case("z10", AArch64::Z10)
2098 .Case("z11", AArch64::Z11)
2099 .Case("z12", AArch64::Z12)
2100 .Case("z13", AArch64::Z13)
2101 .Case("z14", AArch64::Z14)
2102 .Case("z15", AArch64::Z15)
2103 .Case("z16", AArch64::Z16)
2104 .Case("z17", AArch64::Z17)
2105 .Case("z18", AArch64::Z18)
2106 .Case("z19", AArch64::Z19)
2107 .Case("z20", AArch64::Z20)
2108 .Case("z21", AArch64::Z21)
2109 .Case("z22", AArch64::Z22)
2110 .Case("z23", AArch64::Z23)
2111 .Case("z24", AArch64::Z24)
2112 .Case("z25", AArch64::Z25)
2113 .Case("z26", AArch64::Z26)
2114 .Case("z27", AArch64::Z27)
2115 .Case("z28", AArch64::Z28)
2116 .Case("z29", AArch64::Z29)
2117 .Case("z30", AArch64::Z30)
2118 .Case("z31", AArch64::Z31)
2119 .Default(0);
2120}
2121
Sander de Smalencd6be962017-12-20 11:02:42 +00002122static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2123 return StringSwitch<unsigned>(Name.lower())
2124 .Case("p0", AArch64::P0)
2125 .Case("p1", AArch64::P1)
2126 .Case("p2", AArch64::P2)
2127 .Case("p3", AArch64::P3)
2128 .Case("p4", AArch64::P4)
2129 .Case("p5", AArch64::P5)
2130 .Case("p6", AArch64::P6)
2131 .Case("p7", AArch64::P7)
2132 .Case("p8", AArch64::P8)
2133 .Case("p9", AArch64::P9)
2134 .Case("p10", AArch64::P10)
2135 .Case("p11", AArch64::P11)
2136 .Case("p12", AArch64::P12)
2137 .Case("p13", AArch64::P13)
2138 .Case("p14", AArch64::P14)
2139 .Case("p15", AArch64::P15)
2140 .Default(0);
2141}
2142
Tim Northover3b0846e2014-05-24 12:50:23 +00002143bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2144 SMLoc &EndLoc) {
2145 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002146 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002147 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002148 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002149}
2150
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002151// Matches a register name or register alias previously defined by '.req'
2152unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002153 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002154 unsigned RegNum = 0;
2155 if ((RegNum = matchSVEDataVectorRegName(Name)))
2156 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2157
Sander de Smalencd6be962017-12-20 11:02:42 +00002158 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2159 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2160
Sander de Smalenc067c302017-12-20 09:45:45 +00002161 if ((RegNum = MatchNeonVectorRegName(Name)))
2162 return Kind == RegKind::NeonVector ? RegNum : 0;
2163
2164 // The parsed register must be of RegKind Scalar
2165 if ((RegNum = MatchRegisterName(Name)))
2166 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002167
Florian Hahnc4422242017-11-07 13:07:50 +00002168 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002169 // Handle a few common aliases of registers.
2170 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2171 .Case("fp", AArch64::FP)
2172 .Case("lr", AArch64::LR)
2173 .Case("x31", AArch64::XZR)
2174 .Case("w31", AArch64::WZR)
2175 .Default(0))
2176 return Kind == RegKind::Scalar ? RegNum : 0;
2177
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002178 // Check for aliases registered via .req. Canonicalize to lower case.
2179 // That's more consistent since register names are case insensitive, and
2180 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2181 auto Entry = RegisterReqs.find(Name.lower());
2182 if (Entry == RegisterReqs.end())
2183 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002184
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002185 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002186 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002187 RegNum = Entry->getValue().second;
2188 }
2189 return RegNum;
2190}
2191
Sander de Smalen50d87022018-04-19 07:35:08 +00002192/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002193/// Identifier when called, and if it is a register name the token is eaten and
2194/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002195OperandMatchResultTy
2196AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002197 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002198 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002199 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002200 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002201
2202 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002203 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2204 if (Reg == 0)
2205 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002206
Sander de Smalen50d87022018-04-19 07:35:08 +00002207 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002208 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002209 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002210}
2211
Tim Northover3b0846e2014-05-24 12:50:23 +00002212/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002213OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002214AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002215 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002216 SMLoc S = getLoc();
2217
2218 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2219 Error(S, "Expected cN operand where 0 <= N <= 15");
2220 return MatchOperand_ParseFail;
2221 }
2222
2223 StringRef Tok = Parser.getTok().getIdentifier();
2224 if (Tok[0] != 'c' && Tok[0] != 'C') {
2225 Error(S, "Expected cN operand where 0 <= N <= 15");
2226 return MatchOperand_ParseFail;
2227 }
2228
2229 uint32_t CRNum;
2230 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2231 if (BadNum || CRNum > 15) {
2232 Error(S, "Expected cN operand where 0 <= N <= 15");
2233 return MatchOperand_ParseFail;
2234 }
2235
2236 Parser.Lex(); // Eat identifier token.
2237 Operands.push_back(
2238 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2239 return MatchOperand_Success;
2240}
2241
2242/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002243template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002244OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002245AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002246 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002247 SMLoc S = getLoc();
2248 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002249
2250 auto LookupByName = [](StringRef N) {
2251 if (IsSVEPrefetch) {
2252 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2253 return Optional<unsigned>(Res->Encoding);
2254 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2255 return Optional<unsigned>(Res->Encoding);
2256 return Optional<unsigned>();
2257 };
2258
2259 auto LookupByEncoding = [](unsigned E) {
2260 if (IsSVEPrefetch) {
2261 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2262 return Optional<StringRef>(Res->Name);
2263 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2264 return Optional<StringRef>(Res->Name);
2265 return Optional<StringRef>();
2266 };
2267 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2268
Tim Northover3b0846e2014-05-24 12:50:23 +00002269 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002270 // Eat optional hash.
2271 if (parseOptionalToken(AsmToken::Hash) ||
2272 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002273 const MCExpr *ImmVal;
2274 if (getParser().parseExpression(ImmVal))
2275 return MatchOperand_ParseFail;
2276
2277 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2278 if (!MCE) {
2279 TokError("immediate value expected for prefetch operand");
2280 return MatchOperand_ParseFail;
2281 }
2282 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002283 if (prfop > MaxVal) {
2284 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2285 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002286 return MatchOperand_ParseFail;
2287 }
2288
Sander de Smalen93380372018-05-14 11:54:41 +00002289 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002290 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002291 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002292 return MatchOperand_Success;
2293 }
2294
2295 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002296 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002297 return MatchOperand_ParseFail;
2298 }
2299
Sander de Smalen93380372018-05-14 11:54:41 +00002300 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002301 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002302 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002303 return MatchOperand_ParseFail;
2304 }
2305
2306 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002307 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002308 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002309 return MatchOperand_Success;
2310}
2311
Oliver Stannarda34e4702015-12-01 10:48:51 +00002312/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002313OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002314AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2315 MCAsmParser &Parser = getParser();
2316 SMLoc S = getLoc();
2317 const AsmToken &Tok = Parser.getTok();
2318 if (Tok.isNot(AsmToken::Identifier)) {
2319 TokError("invalid operand for instruction");
2320 return MatchOperand_ParseFail;
2321 }
2322
Tim Northovere6ae6762016-07-05 21:23:04 +00002323 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2324 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002325 TokError("invalid operand for instruction");
2326 return MatchOperand_ParseFail;
2327 }
2328
2329 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002330 Operands.push_back(AArch64Operand::CreatePSBHint(
2331 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002332 return MatchOperand_Success;
2333}
2334
Tim Northover3b0846e2014-05-24 12:50:23 +00002335/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2336/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002337OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002338AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002339 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002340 SMLoc S = getLoc();
2341 const MCExpr *Expr;
2342
2343 if (Parser.getTok().is(AsmToken::Hash)) {
2344 Parser.Lex(); // Eat hash token.
2345 }
2346
2347 if (parseSymbolicImmVal(Expr))
2348 return MatchOperand_ParseFail;
2349
2350 AArch64MCExpr::VariantKind ELFRefKind;
2351 MCSymbolRefExpr::VariantKind DarwinRefKind;
2352 int64_t Addend;
2353 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2354 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2355 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2356 // No modifier was specified at all; this is the syntax for an ELF basic
2357 // ADRP relocation (unfortunately).
2358 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002359 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002360 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2361 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2362 Addend != 0) {
2363 Error(S, "gotpage label reference not allowed an addend");
2364 return MatchOperand_ParseFail;
2365 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2366 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2367 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2368 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2369 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2370 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2371 // The operand must be an @page or @gotpage qualified symbolref.
2372 Error(S, "page or gotpage label reference expected");
2373 return MatchOperand_ParseFail;
2374 }
2375 }
2376
2377 // We have either a label reference possibly with addend or an immediate. The
2378 // addend is a raw value here. The linker will adjust it to only reference the
2379 // page.
2380 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2381 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2382
2383 return MatchOperand_Success;
2384}
2385
2386/// tryParseAdrLabel - Parse and validate a source label for the ADR
2387/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002388OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002389AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2390 SMLoc S = getLoc();
2391 const MCExpr *Expr;
2392
Nirav Davee833c6c2016-11-08 18:31:04 +00002393 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002394 if (getParser().parseExpression(Expr))
2395 return MatchOperand_ParseFail;
2396
2397 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2398 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2399
2400 return MatchOperand_Success;
2401}
2402
2403/// tryParseFPImm - A floating point immediate expression operand.
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002404template<bool AddFPZeroAsLiteral>
Alex Bradbury58eba092016-11-01 16:32:05 +00002405OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002406AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002407 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002408 SMLoc S = getLoc();
2409
Nirav Davee833c6c2016-11-08 18:31:04 +00002410 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002411
2412 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002413 bool isNegative = parseOptionalToken(AsmToken::Minus);
2414
Tim Northover3b0846e2014-05-24 12:50:23 +00002415 const AsmToken &Tok = Parser.getTok();
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002416 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2417 if (!Hash)
2418 return MatchOperand_NoMatch;
2419 TokError("invalid floating point immediate");
2420 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002421 }
2422
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002423 // Parse hexadecimal representation.
2424 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2425 if (Tok.getIntVal() > 255 || isNegative) {
2426 TokError("encoded floating point value out of range");
2427 return MatchOperand_ParseFail;
2428 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002429
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002430 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2431 Operands.push_back(
2432 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2433 } else {
2434 // Parse FP representation.
2435 APFloat RealVal(APFloat::IEEEdouble());
2436 auto Status =
2437 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2438 if (isNegative)
2439 RealVal.changeSign();
2440
2441 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2442 Operands.push_back(
2443 AArch64Operand::CreateToken("#0", false, S, getContext()));
2444 Operands.push_back(
2445 AArch64Operand::CreateToken(".0", false, S, getContext()));
2446 } else
2447 Operands.push_back(AArch64Operand::CreateFPImm(
2448 RealVal, Status == APFloat::opOK, S, getContext()));
2449 }
2450
2451 Parser.Lex(); // Eat the token.
2452
2453 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002454}
2455
Sander de Smalen62770792018-05-25 09:47:52 +00002456/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2457/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002458OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002459AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002460 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002461 SMLoc S = getLoc();
2462
2463 if (Parser.getTok().is(AsmToken::Hash))
2464 Parser.Lex(); // Eat '#'
2465 else if (Parser.getTok().isNot(AsmToken::Integer))
2466 // Operand should start from # or should be integer, emit error otherwise.
2467 return MatchOperand_NoMatch;
2468
2469 const MCExpr *Imm;
2470 if (parseSymbolicImmVal(Imm))
2471 return MatchOperand_ParseFail;
2472 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002473 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002474 Operands.push_back(
2475 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002476 return MatchOperand_Success;
2477 }
2478
2479 // Eat ','
2480 Parser.Lex();
2481
2482 // The optional operand must be "lsl #N" where N is non-negative.
2483 if (!Parser.getTok().is(AsmToken::Identifier) ||
2484 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2485 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2486 return MatchOperand_ParseFail;
2487 }
2488
2489 // Eat 'lsl'
2490 Parser.Lex();
2491
Nirav Davee833c6c2016-11-08 18:31:04 +00002492 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002493
2494 if (Parser.getTok().isNot(AsmToken::Integer)) {
2495 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2496 return MatchOperand_ParseFail;
2497 }
2498
2499 int64_t ShiftAmount = Parser.getTok().getIntVal();
2500
2501 if (ShiftAmount < 0) {
2502 Error(Parser.getTok().getLoc(), "positive shift amount required");
2503 return MatchOperand_ParseFail;
2504 }
2505 Parser.Lex(); // Eat the number
2506
Sander de Smalen62770792018-05-25 09:47:52 +00002507 // Just in case the optional lsl #0 is used for immediates other than zero.
2508 if (ShiftAmount == 0 && Imm != 0) {
2509 SMLoc E = Parser.getTok().getLoc();
2510 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2511 return MatchOperand_Success;
2512 }
2513
Tim Northover3b0846e2014-05-24 12:50:23 +00002514 SMLoc E = Parser.getTok().getLoc();
2515 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2516 S, E, getContext()));
2517 return MatchOperand_Success;
2518}
2519
2520/// parseCondCodeString - Parse a Condition Code string.
2521AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2522 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2523 .Case("eq", AArch64CC::EQ)
2524 .Case("ne", AArch64CC::NE)
2525 .Case("cs", AArch64CC::HS)
2526 .Case("hs", AArch64CC::HS)
2527 .Case("cc", AArch64CC::LO)
2528 .Case("lo", AArch64CC::LO)
2529 .Case("mi", AArch64CC::MI)
2530 .Case("pl", AArch64CC::PL)
2531 .Case("vs", AArch64CC::VS)
2532 .Case("vc", AArch64CC::VC)
2533 .Case("hi", AArch64CC::HI)
2534 .Case("ls", AArch64CC::LS)
2535 .Case("ge", AArch64CC::GE)
2536 .Case("lt", AArch64CC::LT)
2537 .Case("gt", AArch64CC::GT)
2538 .Case("le", AArch64CC::LE)
2539 .Case("al", AArch64CC::AL)
2540 .Case("nv", AArch64CC::NV)
2541 .Default(AArch64CC::Invalid);
Sander de Smalene31e6d42018-07-04 08:50:49 +00002542
2543 if (CC == AArch64CC::Invalid &&
2544 getSTI().getFeatureBits()[AArch64::FeatureSVE])
2545 CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2546 .Case("none", AArch64CC::EQ)
2547 .Case("any", AArch64CC::NE)
2548 .Case("nlast", AArch64CC::HS)
2549 .Case("last", AArch64CC::LO)
2550 .Case("first", AArch64CC::MI)
2551 .Case("nfrst", AArch64CC::PL)
2552 .Case("pmore", AArch64CC::HI)
2553 .Case("plast", AArch64CC::LS)
2554 .Case("tcont", AArch64CC::GE)
2555 .Case("tstop", AArch64CC::LT)
2556 .Default(AArch64CC::Invalid);
2557
Tim Northover3b0846e2014-05-24 12:50:23 +00002558 return CC;
2559}
2560
2561/// parseCondCode - Parse a Condition Code operand.
2562bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2563 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002564 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002565 SMLoc S = getLoc();
2566 const AsmToken &Tok = Parser.getTok();
2567 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2568
2569 StringRef Cond = Tok.getString();
2570 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2571 if (CC == AArch64CC::Invalid)
2572 return TokError("invalid condition code");
2573 Parser.Lex(); // Eat identifier token.
2574
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002575 if (invertCondCode) {
2576 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2577 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002578 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002579 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002580
2581 Operands.push_back(
2582 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2583 return false;
2584}
2585
2586/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2587/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002588OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002589AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002590 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002591 const AsmToken &Tok = Parser.getTok();
2592 std::string LowerID = Tok.getString().lower();
2593 AArch64_AM::ShiftExtendType ShOp =
2594 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2595 .Case("lsl", AArch64_AM::LSL)
2596 .Case("lsr", AArch64_AM::LSR)
2597 .Case("asr", AArch64_AM::ASR)
2598 .Case("ror", AArch64_AM::ROR)
2599 .Case("msl", AArch64_AM::MSL)
2600 .Case("uxtb", AArch64_AM::UXTB)
2601 .Case("uxth", AArch64_AM::UXTH)
2602 .Case("uxtw", AArch64_AM::UXTW)
2603 .Case("uxtx", AArch64_AM::UXTX)
2604 .Case("sxtb", AArch64_AM::SXTB)
2605 .Case("sxth", AArch64_AM::SXTH)
2606 .Case("sxtw", AArch64_AM::SXTW)
2607 .Case("sxtx", AArch64_AM::SXTX)
2608 .Default(AArch64_AM::InvalidShiftExtend);
2609
2610 if (ShOp == AArch64_AM::InvalidShiftExtend)
2611 return MatchOperand_NoMatch;
2612
2613 SMLoc S = Tok.getLoc();
2614 Parser.Lex();
2615
Nirav Davee833c6c2016-11-08 18:31:04 +00002616 bool Hash = parseOptionalToken(AsmToken::Hash);
2617
Tim Northover3b0846e2014-05-24 12:50:23 +00002618 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2619 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2620 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2621 ShOp == AArch64_AM::MSL) {
2622 // We expect a number here.
2623 TokError("expected #imm after shift specifier");
2624 return MatchOperand_ParseFail;
2625 }
2626
Chad Rosier2ff37b82016-12-27 16:58:09 +00002627 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002628 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2629 Operands.push_back(
2630 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2631 return MatchOperand_Success;
2632 }
2633
Chad Rosier2ff37b82016-12-27 16:58:09 +00002634 // Make sure we do actually have a number, identifier or a parenthesized
2635 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002636 SMLoc E = Parser.getTok().getLoc();
2637 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002638 !Parser.getTok().is(AsmToken::LParen) &&
2639 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002640 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002641 return MatchOperand_ParseFail;
2642 }
2643
2644 const MCExpr *ImmVal;
2645 if (getParser().parseExpression(ImmVal))
2646 return MatchOperand_ParseFail;
2647
2648 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2649 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002650 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002651 return MatchOperand_ParseFail;
2652 }
2653
Jim Grosbach57fd2622014-09-23 22:16:02 +00002654 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002655 Operands.push_back(AArch64Operand::CreateShiftExtend(
2656 ShOp, MCE->getValue(), true, S, E, getContext()));
2657 return MatchOperand_Success;
2658}
2659
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002660static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2661 if (FBS[AArch64::HasV8_1aOps])
2662 Str += "ARMv8.1a";
2663 else if (FBS[AArch64::HasV8_2aOps])
2664 Str += "ARMv8.2a";
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002665 else if (FBS[AArch64::HasV8_3aOps])
2666 Str += "ARMv8.3a";
2667 else if (FBS[AArch64::HasV8_4aOps])
2668 Str += "ARMv8.4a";
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002669 else
2670 Str += "(unknown)";
2671}
2672
2673void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2674 SMLoc S) {
2675 const uint16_t Op2 = Encoding & 7;
2676 const uint16_t Cm = (Encoding & 0x78) >> 3;
2677 const uint16_t Cn = (Encoding & 0x780) >> 7;
2678 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2679
2680 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2681
2682 Operands.push_back(
2683 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2684 Operands.push_back(
2685 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2686 Operands.push_back(
2687 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2688 Expr = MCConstantExpr::create(Op2, getContext());
2689 Operands.push_back(
2690 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2691}
2692
Tim Northover3b0846e2014-05-24 12:50:23 +00002693/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2694/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2695bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2696 OperandVector &Operands) {
2697 if (Name.find('.') != StringRef::npos)
2698 return TokError("invalid operand");
2699
2700 Mnemonic = Name;
2701 Operands.push_back(
2702 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2703
Rafael Espindola961d4692014-11-11 05:18:41 +00002704 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002705 const AsmToken &Tok = Parser.getTok();
2706 StringRef Op = Tok.getString();
2707 SMLoc S = Tok.getLoc();
2708
Tim Northover3b0846e2014-05-24 12:50:23 +00002709 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002710 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2711 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002712 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002713 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2714 std::string Str("IC " + std::string(IC->Name) + " requires ");
2715 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2716 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002717 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002718 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002719 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002720 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2721 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002722 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002723 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2724 std::string Str("DC " + std::string(DC->Name) + " requires ");
2725 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2726 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002727 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002728 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002729 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002730 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2731 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002732 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002733 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2734 std::string Str("AT " + std::string(AT->Name) + " requires ");
2735 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2736 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002737 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002738 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002739 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002740 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2741 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002742 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002743 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2744 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2745 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2746 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002747 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002748 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002749 }
2750
Tim Northover3b0846e2014-05-24 12:50:23 +00002751 Parser.Lex(); // Eat operand.
2752
2753 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2754 bool HasRegister = false;
2755
2756 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002757 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002758 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2759 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002760 HasRegister = true;
2761 }
2762
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002763 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002764 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002765 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002766 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002767
Nirav Davee833c6c2016-11-08 18:31:04 +00002768 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2769 return true;
2770
Tim Northover3b0846e2014-05-24 12:50:23 +00002771 return false;
2772}
2773
Alex Bradbury58eba092016-11-01 16:32:05 +00002774OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002775AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002776 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002777 const AsmToken &Tok = Parser.getTok();
2778
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002779 if (Mnemonic == "tsb" && Tok.isNot(AsmToken::Identifier)) {
2780 TokError("'csync' operand expected");
2781 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002782 // Can be either a #imm style literal or an option name
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002783 } else if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002784 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002785 const MCExpr *ImmVal;
2786 SMLoc ExprLoc = getLoc();
2787 if (getParser().parseExpression(ImmVal))
2788 return MatchOperand_ParseFail;
2789 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2790 if (!MCE) {
2791 Error(ExprLoc, "immediate value expected for barrier operand");
2792 return MatchOperand_ParseFail;
2793 }
2794 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2795 Error(ExprLoc, "barrier operand out of range");
2796 return MatchOperand_ParseFail;
2797 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002798 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2799 Operands.push_back(AArch64Operand::CreateBarrier(
2800 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002801 return MatchOperand_Success;
2802 }
2803
2804 if (Tok.isNot(AsmToken::Identifier)) {
2805 TokError("invalid operand for instruction");
2806 return MatchOperand_ParseFail;
2807 }
2808
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002809 auto TSB = AArch64TSB::lookupTSBByName(Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00002810 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002811 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2812 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002813 TokError("'sy' or #imm operand expected");
2814 return MatchOperand_ParseFail;
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002815 // The only valid named option for TSB is 'csync'
2816 } else if (Mnemonic == "tsb" && (!TSB || TSB->Encoding != AArch64TSB::csync)) {
2817 TokError("'csync' operand expected");
2818 return MatchOperand_ParseFail;
2819 } else if (!DB && !TSB) {
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002820 TokError("invalid barrier option name");
2821 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002822 }
2823
Tim Northovere6ae6762016-07-05 21:23:04 +00002824 Operands.push_back(AArch64Operand::CreateBarrier(
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002825 DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002826 Parser.Lex(); // Consume the option
2827
2828 return MatchOperand_Success;
2829}
2830
Alex Bradbury58eba092016-11-01 16:32:05 +00002831OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002832AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002833 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002834 const AsmToken &Tok = Parser.getTok();
2835
2836 if (Tok.isNot(AsmToken::Identifier))
2837 return MatchOperand_NoMatch;
2838
Tim Northovere6ae6762016-07-05 21:23:04 +00002839 int MRSReg, MSRReg;
2840 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2841 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2842 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2843 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2844 } else
2845 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002846
Tim Northovere6ae6762016-07-05 21:23:04 +00002847 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2848 unsigned PStateImm = -1;
2849 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2850 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002851
Tim Northovere6ae6762016-07-05 21:23:04 +00002852 Operands.push_back(
2853 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2854 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002855 Parser.Lex(); // Eat identifier
2856
2857 return MatchOperand_Success;
2858}
2859
Florian Hahnc4422242017-11-07 13:07:50 +00002860/// tryParseNeonVectorRegister - Parse a vector register operand.
2861bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002862 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002863 if (Parser.getTok().isNot(AsmToken::Identifier))
2864 return true;
2865
2866 SMLoc S = getLoc();
2867 // Check for a vector register specifier first.
2868 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002869 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002870 OperandMatchResultTy Res =
2871 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2872 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002873 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002874
2875 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2876 if (!KindRes)
2877 return true;
2878
2879 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002880 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002881 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2882 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002883
Tim Northover3b0846e2014-05-24 12:50:23 +00002884 // If there was an explicit qualifier, that goes on as a literal text
2885 // operand.
2886 if (!Kind.empty())
2887 Operands.push_back(
2888 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2889
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002890 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2891}
2892
2893OperandMatchResultTy
2894AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002895 SMLoc SIdx = getLoc();
2896 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002897 const MCExpr *ImmVal;
2898 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002899 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002900 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2901 if (!MCE) {
2902 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002903 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002904 }
2905
2906 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002907
Nirav Davee833c6c2016-11-08 18:31:04 +00002908 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002909 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002910
2911 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2912 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002913 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002914 }
2915
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002916 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002917}
2918
Sander de Smalen73937b72018-04-11 07:36:10 +00002919// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002920// optional kind specifier. If it is a register specifier, eat the token
2921// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002922OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002923AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002924 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002925 MCAsmParser &Parser = getParser();
2926 const AsmToken &Tok = Parser.getTok();
2927
Florian Hahn91f11e52017-11-07 16:45:48 +00002928 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002929 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002930
2931 StringRef Name = Tok.getString();
2932 // If there is a kind specifier, it's separated from the register name by
2933 // a '.'.
2934 size_t Start = 0, Next = Name.find('.');
2935 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002936 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002937
2938 if (RegNum) {
2939 if (Next != StringRef::npos) {
2940 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002941 if (!isValidVectorKind(Kind, MatchKind)) {
2942 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002943 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002944 }
2945 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002946 Parser.Lex(); // Eat the register token.
2947
2948 Reg = RegNum;
2949 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002950 }
2951
Sander de Smalen8e607342017-11-15 15:44:43 +00002952 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002953}
2954
Sander de Smalencd6be962017-12-20 11:02:42 +00002955/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2956OperandMatchResultTy
2957AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2958 // Check for a SVE predicate register specifier first.
2959 const SMLoc S = getLoc();
2960 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002961 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002962 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002963 if (Res != MatchOperand_Success)
2964 return Res;
2965
Sander de Smalen73937b72018-04-11 07:36:10 +00002966 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2967 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002968 return MatchOperand_NoMatch;
2969
Sander de Smalen73937b72018-04-11 07:36:10 +00002970 unsigned ElementWidth = KindRes->second;
2971 Operands.push_back(AArch64Operand::CreateVectorReg(
2972 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2973 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002974
Sander de Smalen7868e742018-01-09 11:17:06 +00002975 // Not all predicates are followed by a '/m' or '/z'.
2976 MCAsmParser &Parser = getParser();
2977 if (Parser.getTok().isNot(AsmToken::Slash))
2978 return MatchOperand_Success;
2979
2980 // But when they do they shouldn't have an element type suffix.
2981 if (!Kind.empty()) {
2982 Error(S, "not expecting size suffix");
2983 return MatchOperand_ParseFail;
2984 }
2985
2986 // Add a literal slash as operand
2987 Operands.push_back(
2988 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2989
2990 Parser.Lex(); // Eat the slash.
2991
2992 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002993 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002994 if (Pred != "z" && Pred != "m") {
2995 Error(getLoc(), "expecting 'm' or 'z' predication");
2996 return MatchOperand_ParseFail;
2997 }
2998
2999 // Add zero/merge token.
3000 const char *ZM = Pred == "z" ? "z" : "m";
3001 Operands.push_back(
3002 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
3003
3004 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00003005 return MatchOperand_Success;
3006}
3007
Sander de Smalen50d87022018-04-19 07:35:08 +00003008/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00003009bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003010 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00003011 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00003012 return false;
3013
Sander de Smalen149916d2018-04-20 07:24:20 +00003014 // Otherwise try for a scalar register.
3015 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
3016 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003017
Sander de Smalen149916d2018-04-20 07:24:20 +00003018 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003019}
3020
3021bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003022 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003023 bool HasELFModifier = false;
3024 AArch64MCExpr::VariantKind RefKind;
3025
Nirav Davee833c6c2016-11-08 18:31:04 +00003026 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003027 HasELFModifier = true;
3028
Nirav Davee833c6c2016-11-08 18:31:04 +00003029 if (Parser.getTok().isNot(AsmToken::Identifier))
3030 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003031
3032 std::string LowerCase = Parser.getTok().getIdentifier().lower();
3033 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
3034 .Case("lo12", AArch64MCExpr::VK_LO12)
3035 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
3036 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
3037 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
3038 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
3039 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
3040 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
3041 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
3042 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
3043 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
3044 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
3045 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
3046 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
3047 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3048 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3049 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3050 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3051 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3052 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3053 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3054 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3055 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3056 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3057 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3058 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3059 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3060 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3061 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3062 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3063 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3064 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3065 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3066 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3067 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3068 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003069 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3070 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00003071 .Default(AArch64MCExpr::VK_INVALID);
3072
Nirav Davee833c6c2016-11-08 18:31:04 +00003073 if (RefKind == AArch64MCExpr::VK_INVALID)
3074 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003075
3076 Parser.Lex(); // Eat identifier
3077
Nirav Davee833c6c2016-11-08 18:31:04 +00003078 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003079 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003080 }
3081
3082 if (getParser().parseExpression(ImmVal))
3083 return true;
3084
3085 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003086 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003087
3088 return false;
3089}
3090
Sander de Smalen650234b2018-04-12 11:40:52 +00003091template <RegKind VectorKind>
3092OperandMatchResultTy
3093AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3094 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003095 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003096 if (!Parser.getTok().is(AsmToken::LCurly))
3097 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003098
3099 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003100 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003101 bool NoMatchIsError) {
3102 auto RegTok = Parser.getTok();
3103 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3104 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003105 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003106 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003107 llvm_unreachable("Expected a valid vector kind");
3108 }
3109
Sander de Smalen650234b2018-04-12 11:40:52 +00003110 if (RegTok.isNot(AsmToken::Identifier) ||
3111 ParseRes == MatchOperand_ParseFail ||
3112 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3113 Error(Loc, "vector register expected");
3114 return MatchOperand_ParseFail;
3115 }
3116
3117 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003118 };
3119
Tim Northover3b0846e2014-05-24 12:50:23 +00003120 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003121 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003122 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003123
Tim Northover3b0846e2014-05-24 12:50:23 +00003124 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003125 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003126 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3127
3128 // Put back the original left bracket if there was no match, so that
3129 // different types of list-operands can be matched (e.g. SVE, Neon).
3130 if (ParseRes == MatchOperand_NoMatch)
3131 Parser.getLexer().UnLex(LCurly);
3132
3133 if (ParseRes != MatchOperand_Success)
3134 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003135
Tim Northover3b0846e2014-05-24 12:50:23 +00003136 int64_t PrevReg = FirstReg;
3137 unsigned Count = 1;
3138
Nirav Davee833c6c2016-11-08 18:31:04 +00003139 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003140 SMLoc Loc = getLoc();
3141 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003142
Sander de Smalen50d87022018-04-19 07:35:08 +00003143 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003144 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3145 if (ParseRes != MatchOperand_Success)
3146 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003147
Tim Northover3b0846e2014-05-24 12:50:23 +00003148 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003149 if (Kind != NextKind) {
3150 Error(Loc, "mismatched register size suffix");
3151 return MatchOperand_ParseFail;
3152 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003153
3154 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3155
3156 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003157 Error(Loc, "invalid number of vectors");
3158 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003159 }
3160
3161 Count += Space;
3162 }
3163 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003164 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003165 SMLoc Loc = getLoc();
3166 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003167 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003168 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3169 if (ParseRes != MatchOperand_Success)
3170 return ParseRes;
3171
Tim Northover3b0846e2014-05-24 12:50:23 +00003172 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003173 if (Kind != NextKind) {
3174 Error(Loc, "mismatched register size suffix");
3175 return MatchOperand_ParseFail;
3176 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003177
3178 // Registers must be incremental (with wraparound at 31)
3179 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003180 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3181 Error(Loc, "registers must be sequential");
3182 return MatchOperand_ParseFail;
3183 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003184
3185 PrevReg = Reg;
3186 ++Count;
3187 }
3188 }
3189
Nirav Davee833c6c2016-11-08 18:31:04 +00003190 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003191 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003192
Sander de Smalen650234b2018-04-12 11:40:52 +00003193 if (Count > 4) {
3194 Error(S, "invalid number of vectors");
3195 return MatchOperand_ParseFail;
3196 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003197
3198 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003199 unsigned ElementWidth = 0;
3200 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003201 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003202 std::tie(NumElements, ElementWidth) = *VK;
3203 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003204
3205 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003206 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3207 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003208
Sander de Smalen650234b2018-04-12 11:40:52 +00003209 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003210}
3211
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003212/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3213bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003214 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3215 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003216 return true;
3217
3218 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3219}
3220
Alex Bradbury58eba092016-11-01 16:32:05 +00003221OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003222AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003223 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003224
Sander de Smalen50d87022018-04-19 07:35:08 +00003225 unsigned RegNum;
3226 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3227 if (Res != MatchOperand_Success)
3228 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003229
Nirav Davee833c6c2016-11-08 18:31:04 +00003230 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003231 Operands.push_back(AArch64Operand::CreateReg(
3232 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003233 return MatchOperand_Success;
3234 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003235
Nirav Davee833c6c2016-11-08 18:31:04 +00003236 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003237
Sander de Smalen50d87022018-04-19 07:35:08 +00003238 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003239 Error(getLoc(), "index must be absent or #0");
3240 return MatchOperand_ParseFail;
3241 }
3242
3243 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003244 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003245 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3246 Error(getLoc(), "index must be absent or #0");
3247 return MatchOperand_ParseFail;
3248 }
3249
Sander de Smalen50d87022018-04-19 07:35:08 +00003250 Operands.push_back(AArch64Operand::CreateReg(
3251 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003252 return MatchOperand_Success;
3253}
3254
Sander de Smalen0325e302018-07-02 07:34:52 +00003255template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
Sander de Smalen149916d2018-04-20 07:24:20 +00003256OperandMatchResultTy
3257AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3258 SMLoc StartLoc = getLoc();
3259
3260 unsigned RegNum;
3261 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3262 if (Res != MatchOperand_Success)
3263 return Res;
3264
3265 // No shift/extend is the default.
3266 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3267 Operands.push_back(AArch64Operand::CreateReg(
Sander de Smalen0325e302018-07-02 07:34:52 +00003268 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
Sander de Smalen149916d2018-04-20 07:24:20 +00003269 return MatchOperand_Success;
3270 }
3271
3272 // Eat the comma
3273 getParser().Lex();
3274
3275 // Match the shift
3276 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3277 Res = tryParseOptionalShiftExtend(ExtOpnd);
3278 if (Res != MatchOperand_Success)
3279 return Res;
3280
3281 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
Sander de Smalen0325e302018-07-02 07:34:52 +00003282 Operands.push_back(AArch64Operand::CreateReg(
3283 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3284 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3285 Ext->hasShiftExtendAmount()));
Sander de Smalen149916d2018-04-20 07:24:20 +00003286
3287 return MatchOperand_Success;
3288}
3289
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003290bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
Sander de Smalen5c625982018-04-13 12:56:14 +00003291 MCAsmParser &Parser = getParser();
3292
3293 // Some SVE instructions have a decoration after the immediate, i.e.
3294 // "mul vl". We parse them here and add tokens, which must be present in the
3295 // asm string in the tablegen instruction.
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003296 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3297 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
Sander de Smalen5c625982018-04-13 12:56:14 +00003298 if (!Parser.getTok().getString().equals_lower("mul") ||
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003299 !(NextIsVL || NextIsHash))
Sander de Smalen5c625982018-04-13 12:56:14 +00003300 return true;
3301
Sander de Smalen5c625982018-04-13 12:56:14 +00003302 Operands.push_back(
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003303 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
Sander de Smalen5c625982018-04-13 12:56:14 +00003304 Parser.Lex(); // Eat the "mul"
3305
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003306 if (NextIsVL) {
3307 Operands.push_back(
3308 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3309 Parser.Lex(); // Eat the "vl"
3310 return false;
3311 }
Sander de Smalen5c625982018-04-13 12:56:14 +00003312
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003313 if (NextIsHash) {
3314 Parser.Lex(); // Eat the #
3315 SMLoc S = getLoc();
3316
3317 // Parse immediate operand.
3318 const MCExpr *ImmVal;
3319 if (!Parser.parseExpression(ImmVal))
3320 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3321 Operands.push_back(AArch64Operand::CreateImm(
3322 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3323 getContext()));
3324 return MatchOperand_Success;
3325 }
3326 }
3327
3328 return Error(getLoc(), "expected 'vl' or '#<imm>'");
Sander de Smalen5c625982018-04-13 12:56:14 +00003329}
3330
Tim Northover3b0846e2014-05-24 12:50:23 +00003331/// parseOperand - Parse a arm instruction operand. For now this parses the
3332/// operand regardless of the mnemonic.
3333bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3334 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003335 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003336
3337 OperandMatchResultTy ResTy =
3338 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3339
Tim Northover3b0846e2014-05-24 12:50:23 +00003340 // Check if the current operand has a custom associated parser, if so, try to
3341 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003342 if (ResTy == MatchOperand_Success)
3343 return false;
3344 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3345 // there was a match, but an error occurred, in which case, just return that
3346 // the operand parsing failed.
3347 if (ResTy == MatchOperand_ParseFail)
3348 return true;
3349
3350 // Nothing custom, so do general case parsing.
3351 SMLoc S, E;
3352 switch (getLexer().getKind()) {
3353 default: {
3354 SMLoc S = getLoc();
3355 const MCExpr *Expr;
3356 if (parseSymbolicImmVal(Expr))
3357 return Error(S, "invalid operand");
3358
3359 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3360 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3361 return false;
3362 }
3363 case AsmToken::LBrac: {
3364 SMLoc Loc = Parser.getTok().getLoc();
3365 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3366 getContext()));
3367 Parser.Lex(); // Eat '['
3368
3369 // There's no comma after a '[', so we can parse the next operand
3370 // immediately.
3371 return parseOperand(Operands, false, false);
3372 }
3373 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003374 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003375 case AsmToken::Identifier: {
3376 // If we're expecting a Condition Code operand, then just parse that.
3377 if (isCondCode)
3378 return parseCondCode(Operands, invertCondCode);
3379
3380 // If it's a register name, parse it.
3381 if (!parseRegister(Operands))
3382 return false;
3383
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003384 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3385 // by SVE instructions.
3386 if (!parseOptionalMulOperand(Operands))
Sander de Smalen5c625982018-04-13 12:56:14 +00003387 return false;
3388
Tim Northover3b0846e2014-05-24 12:50:23 +00003389 // This could be an optional "shift" or "extend" operand.
3390 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3391 // We can only continue if no tokens were eaten.
3392 if (GotShift != MatchOperand_NoMatch)
3393 return GotShift;
3394
3395 // This was not a register so parse other operands that start with an
3396 // identifier (like labels) as expressions and create them as immediates.
3397 const MCExpr *IdVal;
3398 S = getLoc();
3399 if (getParser().parseExpression(IdVal))
3400 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003401 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3402 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3403 return false;
3404 }
3405 case AsmToken::Integer:
3406 case AsmToken::Real:
3407 case AsmToken::Hash: {
3408 // #42 -> immediate.
3409 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003410
3411 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003412
3413 // Parse a negative sign
3414 bool isNegative = false;
3415 if (Parser.getTok().is(AsmToken::Minus)) {
3416 isNegative = true;
3417 // We need to consume this token only when we have a Real, otherwise
3418 // we let parseSymbolicImmVal take care of it
3419 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3420 Parser.Lex();
3421 }
3422
3423 // The only Real that should come through here is a literal #0.0 for
3424 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3425 // so convert the value.
3426 const AsmToken &Tok = Parser.getTok();
3427 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003428 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003429 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3430 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3431 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
Sander de Smalen8fcc3f52018-07-03 09:07:23 +00003432 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
Tim Northover3b0846e2014-05-24 12:50:23 +00003433 return TokError("unexpected floating point literal");
3434 else if (IntVal != 0 || isNegative)
3435 return TokError("expected floating-point constant #0.0");
3436 Parser.Lex(); // Eat the token.
3437
3438 Operands.push_back(
3439 AArch64Operand::CreateToken("#0", false, S, getContext()));
3440 Operands.push_back(
3441 AArch64Operand::CreateToken(".0", false, S, getContext()));
3442 return false;
3443 }
3444
3445 const MCExpr *ImmVal;
3446 if (parseSymbolicImmVal(ImmVal))
3447 return true;
3448
3449 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3450 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3451 return false;
3452 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003453 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003454 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003455 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003456 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003457 Parser.Lex(); // Eat '='
3458 const MCExpr *SubExprVal;
3459 if (getParser().parseExpression(SubExprVal))
3460 return true;
3461
David Peixottoae5ba762014-07-18 16:05:14 +00003462 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003463 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003464 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003465
3466 bool IsXReg =
3467 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3468 Operands[1]->getReg());
3469
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003470 MCContext& Ctx = getContext();
3471 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3472 // 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 +00003473 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003474 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3475 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3476 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3477 ShiftAmt += 16;
3478 Imm >>= 16;
3479 }
3480 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3481 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3482 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003483 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003484 if (ShiftAmt)
3485 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3486 ShiftAmt, true, S, E, Ctx));
3487 return false;
3488 }
David Peixottoae5ba762014-07-18 16:05:14 +00003489 APInt Simm = APInt(64, Imm << ShiftAmt);
3490 // check if the immediate is an unsigned or signed 32-bit int for W regs
3491 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3492 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003493 }
3494 // 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 +00003495 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003496 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003497 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3498 return false;
3499 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003500 }
3501}
3502
Sander de Smalen0325e302018-07-02 07:34:52 +00003503bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3504 const MCParsedAsmOperand &Op2) const {
3505 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3506 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3507 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3508 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3509 return MCTargetAsmParser::regsEqual(Op1, Op2);
3510
3511 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3512 "Testing equality of non-scalar registers not supported");
3513
3514 // Check if a registers match their sub/super register classes.
3515 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3516 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3517 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3518 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3519 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3520 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3521 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3522 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3523
3524 return false;
3525}
3526
Tim Northover3b0846e2014-05-24 12:50:23 +00003527/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3528/// operands.
3529bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3530 StringRef Name, SMLoc NameLoc,
3531 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003532 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003533 Name = StringSwitch<StringRef>(Name.lower())
3534 .Case("beq", "b.eq")
3535 .Case("bne", "b.ne")
3536 .Case("bhs", "b.hs")
3537 .Case("bcs", "b.cs")
3538 .Case("blo", "b.lo")
3539 .Case("bcc", "b.cc")
3540 .Case("bmi", "b.mi")
3541 .Case("bpl", "b.pl")
3542 .Case("bvs", "b.vs")
3543 .Case("bvc", "b.vc")
3544 .Case("bhi", "b.hi")
3545 .Case("bls", "b.ls")
3546 .Case("bge", "b.ge")
3547 .Case("blt", "b.lt")
3548 .Case("bgt", "b.gt")
3549 .Case("ble", "b.le")
3550 .Case("bal", "b.al")
3551 .Case("bnv", "b.nv")
3552 .Default(Name);
3553
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003554 // First check for the AArch64-specific .req directive.
3555 if (Parser.getTok().is(AsmToken::Identifier) &&
3556 Parser.getTok().getIdentifier() == ".req") {
3557 parseDirectiveReq(Name, NameLoc);
3558 // We always return 'error' for this, as we're done with this
3559 // statement and don't need to match the 'instruction."
3560 return true;
3561 }
3562
Tim Northover3b0846e2014-05-24 12:50:23 +00003563 // Create the leading tokens for the mnemonic, split by '.' characters.
3564 size_t Start = 0, Next = Name.find('.');
3565 StringRef Head = Name.slice(Start, Next);
3566
3567 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003568 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3569 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003570
3571 Operands.push_back(
3572 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3573 Mnemonic = Head;
3574
3575 // Handle condition codes for a branch mnemonic
3576 if (Head == "b" && Next != StringRef::npos) {
3577 Start = Next;
3578 Next = Name.find('.', Start + 1);
3579 Head = Name.slice(Start + 1, Next);
3580
3581 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3582 (Head.data() - Name.data()));
3583 AArch64CC::CondCode CC = parseCondCodeString(Head);
3584 if (CC == AArch64CC::Invalid)
3585 return Error(SuffixLoc, "invalid condition code");
3586 Operands.push_back(
3587 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3588 Operands.push_back(
3589 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3590 }
3591
3592 // Add the remaining tokens in the mnemonic.
3593 while (Next != StringRef::npos) {
3594 Start = Next;
3595 Next = Name.find('.', Start + 1);
3596 Head = Name.slice(Start, Next);
3597 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3598 (Head.data() - Name.data()) + 1);
3599 Operands.push_back(
3600 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3601 }
3602
3603 // Conditional compare instructions have a Condition Code operand, which needs
3604 // to be parsed and an immediate operand created.
3605 bool condCodeFourthOperand =
3606 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3607 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3608 Head == "csinc" || Head == "csinv" || Head == "csneg");
3609
3610 // These instructions are aliases to some of the conditional select
3611 // instructions. However, the condition code is inverted in the aliased
3612 // instruction.
3613 //
3614 // FIXME: Is this the correct way to handle these? Or should the parser
3615 // generate the aliased instructions directly?
3616 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3617 bool condCodeThirdOperand =
3618 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3619
3620 // Read the remaining operands.
3621 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3622 // Read the first operand.
3623 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003624 return true;
3625 }
3626
3627 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003628 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003629 // Parse and remember the operand.
3630 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3631 (N == 3 && condCodeThirdOperand) ||
3632 (N == 2 && condCodeSecondOperand),
3633 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003634 return true;
3635 }
3636
3637 // After successfully parsing some operands there are two special cases to
3638 // consider (i.e. notional operands not separated by commas). Both are due
3639 // to memory specifiers:
3640 // + An RBrac will end an address for load/store/prefetch
3641 // + An '!' will indicate a pre-indexed operation.
3642 //
3643 // It's someone else's responsibility to make sure these tokens are sane
3644 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003645
Nirav Davee833c6c2016-11-08 18:31:04 +00003646 SMLoc RLoc = Parser.getTok().getLoc();
3647 if (parseOptionalToken(AsmToken::RBrac))
3648 Operands.push_back(
3649 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3650 SMLoc ELoc = Parser.getTok().getLoc();
3651 if (parseOptionalToken(AsmToken::Exclaim))
3652 Operands.push_back(
3653 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003654
3655 ++N;
3656 }
3657 }
3658
Nirav Davee833c6c2016-11-08 18:31:04 +00003659 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3660 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003661
Tim Northover3b0846e2014-05-24 12:50:23 +00003662 return false;
3663}
3664
3665// FIXME: This entire function is a giant hack to provide us with decent
3666// operand range validation/diagnostics until TableGen/MC can be extended
3667// to support autogeneration of this kind of validation.
3668bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3669 SmallVectorImpl<SMLoc> &Loc) {
3670 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3671 // Check for indexed addressing modes w/ the base register being the
3672 // same as a destination/source register or pair load where
3673 // the Rt == Rt2. All of those are undefined behaviour.
3674 switch (Inst.getOpcode()) {
3675 case AArch64::LDPSWpre:
3676 case AArch64::LDPWpost:
3677 case AArch64::LDPWpre:
3678 case AArch64::LDPXpost:
3679 case AArch64::LDPXpre: {
3680 unsigned Rt = Inst.getOperand(1).getReg();
3681 unsigned Rt2 = Inst.getOperand(2).getReg();
3682 unsigned Rn = Inst.getOperand(3).getReg();
3683 if (RI->isSubRegisterEq(Rn, Rt))
3684 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3685 "is also a destination");
3686 if (RI->isSubRegisterEq(Rn, Rt2))
3687 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3688 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003689 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003690 }
3691 case AArch64::LDPDi:
3692 case AArch64::LDPQi:
3693 case AArch64::LDPSi:
3694 case AArch64::LDPSWi:
3695 case AArch64::LDPWi:
3696 case AArch64::LDPXi: {
3697 unsigned Rt = Inst.getOperand(0).getReg();
3698 unsigned Rt2 = Inst.getOperand(1).getReg();
3699 if (Rt == Rt2)
3700 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3701 break;
3702 }
3703 case AArch64::LDPDpost:
3704 case AArch64::LDPDpre:
3705 case AArch64::LDPQpost:
3706 case AArch64::LDPQpre:
3707 case AArch64::LDPSpost:
3708 case AArch64::LDPSpre:
3709 case AArch64::LDPSWpost: {
3710 unsigned Rt = Inst.getOperand(1).getReg();
3711 unsigned Rt2 = Inst.getOperand(2).getReg();
3712 if (Rt == Rt2)
3713 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3714 break;
3715 }
3716 case AArch64::STPDpost:
3717 case AArch64::STPDpre:
3718 case AArch64::STPQpost:
3719 case AArch64::STPQpre:
3720 case AArch64::STPSpost:
3721 case AArch64::STPSpre:
3722 case AArch64::STPWpost:
3723 case AArch64::STPWpre:
3724 case AArch64::STPXpost:
3725 case AArch64::STPXpre: {
3726 unsigned Rt = Inst.getOperand(1).getReg();
3727 unsigned Rt2 = Inst.getOperand(2).getReg();
3728 unsigned Rn = Inst.getOperand(3).getReg();
3729 if (RI->isSubRegisterEq(Rn, Rt))
3730 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3731 "is also a source");
3732 if (RI->isSubRegisterEq(Rn, Rt2))
3733 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3734 "is also a source");
3735 break;
3736 }
3737 case AArch64::LDRBBpre:
3738 case AArch64::LDRBpre:
3739 case AArch64::LDRHHpre:
3740 case AArch64::LDRHpre:
3741 case AArch64::LDRSBWpre:
3742 case AArch64::LDRSBXpre:
3743 case AArch64::LDRSHWpre:
3744 case AArch64::LDRSHXpre:
3745 case AArch64::LDRSWpre:
3746 case AArch64::LDRWpre:
3747 case AArch64::LDRXpre:
3748 case AArch64::LDRBBpost:
3749 case AArch64::LDRBpost:
3750 case AArch64::LDRHHpost:
3751 case AArch64::LDRHpost:
3752 case AArch64::LDRSBWpost:
3753 case AArch64::LDRSBXpost:
3754 case AArch64::LDRSHWpost:
3755 case AArch64::LDRSHXpost:
3756 case AArch64::LDRSWpost:
3757 case AArch64::LDRWpost:
3758 case AArch64::LDRXpost: {
3759 unsigned Rt = Inst.getOperand(1).getReg();
3760 unsigned Rn = Inst.getOperand(2).getReg();
3761 if (RI->isSubRegisterEq(Rn, Rt))
3762 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3763 "is also a source");
3764 break;
3765 }
3766 case AArch64::STRBBpost:
3767 case AArch64::STRBpost:
3768 case AArch64::STRHHpost:
3769 case AArch64::STRHpost:
3770 case AArch64::STRWpost:
3771 case AArch64::STRXpost:
3772 case AArch64::STRBBpre:
3773 case AArch64::STRBpre:
3774 case AArch64::STRHHpre:
3775 case AArch64::STRHpre:
3776 case AArch64::STRWpre:
3777 case AArch64::STRXpre: {
3778 unsigned Rt = Inst.getOperand(1).getReg();
3779 unsigned Rn = Inst.getOperand(2).getReg();
3780 if (RI->isSubRegisterEq(Rn, Rt))
3781 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3782 "is also a source");
3783 break;
3784 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003785 case AArch64::STXRB:
3786 case AArch64::STXRH:
3787 case AArch64::STXRW:
3788 case AArch64::STXRX:
3789 case AArch64::STLXRB:
3790 case AArch64::STLXRH:
3791 case AArch64::STLXRW:
3792 case AArch64::STLXRX: {
3793 unsigned Rs = Inst.getOperand(0).getReg();
3794 unsigned Rt = Inst.getOperand(1).getReg();
3795 unsigned Rn = Inst.getOperand(2).getReg();
3796 if (RI->isSubRegisterEq(Rt, Rs) ||
3797 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3798 return Error(Loc[0],
3799 "unpredictable STXR instruction, status is also a source");
3800 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003801 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003802 case AArch64::STXPW:
3803 case AArch64::STXPX:
3804 case AArch64::STLXPW:
3805 case AArch64::STLXPX: {
3806 unsigned Rs = Inst.getOperand(0).getReg();
3807 unsigned Rt1 = Inst.getOperand(1).getReg();
3808 unsigned Rt2 = Inst.getOperand(2).getReg();
3809 unsigned Rn = Inst.getOperand(3).getReg();
3810 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3811 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3812 return Error(Loc[0],
3813 "unpredictable STXP instruction, status is also a source");
3814 break;
3815 }
3816 }
3817
Tim Northover3b0846e2014-05-24 12:50:23 +00003818
3819 // Now check immediate ranges. Separate from the above as there is overlap
3820 // in the instructions being checked and this keeps the nested conditionals
3821 // to a minimum.
3822 switch (Inst.getOpcode()) {
3823 case AArch64::ADDSWri:
3824 case AArch64::ADDSXri:
3825 case AArch64::ADDWri:
3826 case AArch64::ADDXri:
3827 case AArch64::SUBSWri:
3828 case AArch64::SUBSXri:
3829 case AArch64::SUBWri:
3830 case AArch64::SUBXri: {
3831 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3832 // some slight duplication here.
3833 if (Inst.getOperand(2).isExpr()) {
3834 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3835 AArch64MCExpr::VariantKind ELFRefKind;
3836 MCSymbolRefExpr::VariantKind DarwinRefKind;
3837 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003838 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3839
3840 // Only allow these with ADDXri.
3841 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3842 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3843 Inst.getOpcode() == AArch64::ADDXri)
3844 return false;
3845
3846 // Only allow these with ADDXri/ADDWri
3847 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3848 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3849 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3850 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3851 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3852 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3853 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003854 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3855 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3856 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003857 (Inst.getOpcode() == AArch64::ADDXri ||
3858 Inst.getOpcode() == AArch64::ADDWri))
3859 return false;
3860
3861 // Don't allow symbol refs in the immediate field otherwise
3862 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3863 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3864 // 'cmp w0, 'borked')
3865 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003866 }
Diana Picusc93518d2016-10-11 09:17:47 +00003867 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003868 }
3869 return false;
3870 }
3871 default:
3872 return false;
3873 }
3874}
3875
Craig Topper05515562017-10-26 06:46:41 +00003876static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3877 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003878
3879bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
Sander de Smalen0325e302018-07-02 07:34:52 +00003880 uint64_t ErrorInfo,
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003881 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003882 switch (ErrCode) {
Sander de Smalen0325e302018-07-02 07:34:52 +00003883 case Match_InvalidTiedOperand: {
3884 RegConstraintEqualityTy EqTy =
3885 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
3886 .getRegEqualityTy();
3887 switch (EqTy) {
3888 case RegConstraintEqualityTy::EqualsSubReg:
3889 return Error(Loc, "operand must be 64-bit form of destination register");
3890 case RegConstraintEqualityTy::EqualsSuperReg:
3891 return Error(Loc, "operand must be 32-bit form of destination register");
3892 case RegConstraintEqualityTy::EqualsReg:
3893 return Error(Loc, "operand must match destination register");
3894 }
Simon Pilgrim6dc45e62018-07-05 09:48:01 +00003895 llvm_unreachable("Unknown RegConstraintEqualityTy");
Sander de Smalen0325e302018-07-02 07:34:52 +00003896 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003897 case Match_MissingFeature:
3898 return Error(Loc,
3899 "instruction requires a CPU feature not currently enabled");
3900 case Match_InvalidOperand:
3901 return Error(Loc, "invalid operand for instruction");
3902 case Match_InvalidSuffix:
3903 return Error(Loc, "invalid type suffix for instruction");
3904 case Match_InvalidCondCode:
3905 return Error(Loc, "expected AArch64 condition code");
3906 case Match_AddSubRegExtendSmall:
3907 return Error(Loc,
3908 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3909 case Match_AddSubRegExtendLarge:
3910 return Error(Loc,
3911 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3912 case Match_AddSubSecondSource:
3913 return Error(Loc,
3914 "expected compatible register, symbol or integer in range [0, 4095]");
3915 case Match_LogicalSecondSource:
3916 return Error(Loc, "expected compatible register or logical immediate");
3917 case Match_InvalidMovImm32Shift:
3918 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3919 case Match_InvalidMovImm64Shift:
3920 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3921 case Match_AddSubRegShift32:
3922 return Error(Loc,
3923 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3924 case Match_AddSubRegShift64:
3925 return Error(Loc,
3926 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3927 case Match_InvalidFPImm:
3928 return Error(Loc,
3929 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003930 case Match_InvalidMemoryIndexedSImm6:
3931 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003932 case Match_InvalidMemoryIndexedSImm5:
3933 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003934 case Match_InvalidMemoryIndexed1SImm4:
3935 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003936 case Match_InvalidMemoryIndexed2SImm4:
3937 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003938 case Match_InvalidMemoryIndexed3SImm4:
3939 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003940 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00003941 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00003942 case Match_InvalidMemoryIndexed16SImm4:
3943 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00003944 case Match_InvalidMemoryIndexed1SImm6:
3945 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen592718f2018-07-05 07:54:10 +00003946 case Match_InvalidMemoryIndexedSImm8:
3947 return Error(Loc, "index must be an integer in range [-128, 127].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003948 case Match_InvalidMemoryIndexedSImm9:
3949 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00003950 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00003951 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003952 case Match_InvalidMemoryIndexed4SImm7:
3953 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3954 case Match_InvalidMemoryIndexed8SImm7:
3955 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3956 case Match_InvalidMemoryIndexed16SImm7:
3957 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00003958 case Match_InvalidMemoryIndexed8UImm5:
3959 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
3960 case Match_InvalidMemoryIndexed4UImm5:
3961 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
3962 case Match_InvalidMemoryIndexed2UImm5:
3963 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00003964 case Match_InvalidMemoryIndexed8UImm6:
3965 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
3966 case Match_InvalidMemoryIndexed4UImm6:
3967 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
3968 case Match_InvalidMemoryIndexed2UImm6:
3969 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
3970 case Match_InvalidMemoryIndexed1UImm6:
3971 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003972 case Match_InvalidMemoryWExtend8:
3973 return Error(Loc,
3974 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3975 case Match_InvalidMemoryWExtend16:
3976 return Error(Loc,
3977 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3978 case Match_InvalidMemoryWExtend32:
3979 return Error(Loc,
3980 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3981 case Match_InvalidMemoryWExtend64:
3982 return Error(Loc,
3983 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3984 case Match_InvalidMemoryWExtend128:
3985 return Error(Loc,
3986 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3987 case Match_InvalidMemoryXExtend8:
3988 return Error(Loc,
3989 "expected 'lsl' or 'sxtx' with optional shift of #0");
3990 case Match_InvalidMemoryXExtend16:
3991 return Error(Loc,
3992 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3993 case Match_InvalidMemoryXExtend32:
3994 return Error(Loc,
3995 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3996 case Match_InvalidMemoryXExtend64:
3997 return Error(Loc,
3998 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3999 case Match_InvalidMemoryXExtend128:
4000 return Error(Loc,
4001 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
4002 case Match_InvalidMemoryIndexed1:
4003 return Error(Loc, "index must be an integer in range [0, 4095].");
4004 case Match_InvalidMemoryIndexed2:
4005 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
4006 case Match_InvalidMemoryIndexed4:
4007 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
4008 case Match_InvalidMemoryIndexed8:
4009 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
4010 case Match_InvalidMemoryIndexed16:
4011 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004012 case Match_InvalidImm0_1:
4013 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004014 case Match_InvalidImm0_7:
4015 return Error(Loc, "immediate must be an integer in range [0, 7].");
4016 case Match_InvalidImm0_15:
4017 return Error(Loc, "immediate must be an integer in range [0, 15].");
4018 case Match_InvalidImm0_31:
4019 return Error(Loc, "immediate must be an integer in range [0, 31].");
4020 case Match_InvalidImm0_63:
4021 return Error(Loc, "immediate must be an integer in range [0, 63].");
4022 case Match_InvalidImm0_127:
4023 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004024 case Match_InvalidImm0_255:
4025 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004026 case Match_InvalidImm0_65535:
4027 return Error(Loc, "immediate must be an integer in range [0, 65535].");
4028 case Match_InvalidImm1_8:
4029 return Error(Loc, "immediate must be an integer in range [1, 8].");
4030 case Match_InvalidImm1_16:
4031 return Error(Loc, "immediate must be an integer in range [1, 16].");
4032 case Match_InvalidImm1_32:
4033 return Error(Loc, "immediate must be an integer in range [1, 32].");
4034 case Match_InvalidImm1_64:
4035 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00004036 case Match_InvalidSVEAddSubImm8:
4037 return Error(Loc, "immediate must be an integer in range [0, 255]"
4038 " with a shift amount of 0");
4039 case Match_InvalidSVEAddSubImm16:
4040 case Match_InvalidSVEAddSubImm32:
4041 case Match_InvalidSVEAddSubImm64:
4042 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
4043 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004044 case Match_InvalidSVECpyImm8:
4045 return Error(Loc, "immediate must be an integer in range [-128, 255]"
4046 " with a shift amount of 0");
4047 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00004048 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4049 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004050 case Match_InvalidSVECpyImm32:
4051 case Match_InvalidSVECpyImm64:
4052 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4053 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004054 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004055 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004056 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00004057 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004058 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00004059 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004060 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004061 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004062 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004063 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004064 case Match_InvalidSVEIndexRange0_63:
4065 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4066 case Match_InvalidSVEIndexRange0_31:
4067 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4068 case Match_InvalidSVEIndexRange0_15:
4069 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4070 case Match_InvalidSVEIndexRange0_7:
4071 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4072 case Match_InvalidSVEIndexRange0_3:
4073 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004074 case Match_InvalidLabel:
4075 return Error(Loc, "expected label or encodable integer pc offset");
4076 case Match_MRS:
4077 return Error(Loc, "expected readable system register");
4078 case Match_MSR:
4079 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00004080 case Match_InvalidComplexRotationEven:
4081 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4082 case Match_InvalidComplexRotationOdd:
4083 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004084 case Match_MnemonicFail: {
4085 std::string Suggestion = AArch64MnemonicSpellCheck(
4086 ((AArch64Operand &)*Operands[0]).getToken(),
4087 ComputeAvailableFeatures(STI->getFeatureBits()));
4088 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4089 }
Sander de Smalen367694b2018-04-20 08:54:49 +00004090 case Match_InvalidGPR64shifted8:
4091 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4092 case Match_InvalidGPR64shifted16:
4093 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4094 case Match_InvalidGPR64shifted32:
4095 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4096 case Match_InvalidGPR64shifted64:
4097 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4098 case Match_InvalidGPR64NoXZRshifted8:
4099 return Error(Loc, "register must be x0..x30 without shift");
4100 case Match_InvalidGPR64NoXZRshifted16:
4101 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4102 case Match_InvalidGPR64NoXZRshifted32:
4103 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4104 case Match_InvalidGPR64NoXZRshifted64:
4105 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004106 case Match_InvalidZPR32UXTW8:
4107 case Match_InvalidZPR32SXTW8:
4108 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4109 case Match_InvalidZPR32UXTW16:
4110 case Match_InvalidZPR32SXTW16:
4111 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4112 case Match_InvalidZPR32UXTW32:
4113 case Match_InvalidZPR32SXTW32:
4114 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4115 case Match_InvalidZPR32UXTW64:
4116 case Match_InvalidZPR32SXTW64:
4117 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4118 case Match_InvalidZPR64UXTW8:
4119 case Match_InvalidZPR64SXTW8:
4120 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4121 case Match_InvalidZPR64UXTW16:
4122 case Match_InvalidZPR64SXTW16:
4123 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4124 case Match_InvalidZPR64UXTW32:
4125 case Match_InvalidZPR64SXTW32:
4126 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4127 case Match_InvalidZPR64UXTW64:
4128 case Match_InvalidZPR64SXTW64:
4129 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
4130 case Match_InvalidZPR64LSL8:
4131 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4132 case Match_InvalidZPR64LSL16:
4133 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4134 case Match_InvalidZPR64LSL32:
4135 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4136 case Match_InvalidZPR64LSL64:
4137 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00004138 case Match_InvalidZPR0:
4139 return Error(Loc, "expected register without element width sufix");
4140 case Match_InvalidZPR8:
4141 case Match_InvalidZPR16:
4142 case Match_InvalidZPR32:
4143 case Match_InvalidZPR64:
4144 case Match_InvalidZPR128:
4145 return Error(Loc, "invalid element width");
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004146 case Match_InvalidZPR_3b8:
4147 return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b");
4148 case Match_InvalidZPR_3b16:
4149 return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h");
4150 case Match_InvalidZPR_3b32:
4151 return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s");
4152 case Match_InvalidZPR_4b16:
4153 return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h");
4154 case Match_InvalidZPR_4b32:
4155 return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s");
4156 case Match_InvalidZPR_4b64:
4157 return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004158 case Match_InvalidSVEPattern:
4159 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004160 case Match_InvalidSVEPredicateAnyReg:
4161 case Match_InvalidSVEPredicateBReg:
4162 case Match_InvalidSVEPredicateHReg:
4163 case Match_InvalidSVEPredicateSReg:
4164 case Match_InvalidSVEPredicateDReg:
4165 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004166 case Match_InvalidSVEPredicate3bAnyReg:
4167 case Match_InvalidSVEPredicate3bBReg:
4168 case Match_InvalidSVEPredicate3bHReg:
4169 case Match_InvalidSVEPredicate3bSReg:
4170 case Match_InvalidSVEPredicate3bDReg:
4171 return Error(Loc, "restricted predicate has range [0, 7].");
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004172 case Match_InvalidSVEExactFPImmOperandHalfOne:
4173 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4174 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4175 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4176 case Match_InvalidSVEExactFPImmOperandZeroOne:
4177 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004178 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004179 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004180 }
4181}
4182
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004183static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004184
4185bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4186 OperandVector &Operands,
4187 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004188 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004189 bool MatchingInlineAsm) {
4190 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004191 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4192 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004193
David Blaikie960ea3f2014-06-08 16:18:35 +00004194 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004195 unsigned NumOperands = Operands.size();
4196
4197 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004198 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4199 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004200 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004201 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004202 if (Op3CE) {
4203 uint64_t Op3Val = Op3CE->getValue();
4204 uint64_t NewOp3Val = 0;
4205 uint64_t NewOp4Val = 0;
4206 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004207 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004208 NewOp3Val = (32 - Op3Val) & 0x1f;
4209 NewOp4Val = 31 - Op3Val;
4210 } else {
4211 NewOp3Val = (64 - Op3Val) & 0x3f;
4212 NewOp4Val = 63 - Op3Val;
4213 }
4214
Jim Grosbach13760bd2015-05-30 01:25:56 +00004215 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4216 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004217
4218 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004219 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004220 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004221 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4222 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4223 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004224 }
4225 }
Tim Northover03b99f62015-04-30 18:28:58 +00004226 } else if (NumOperands == 4 && Tok == "bfc") {
4227 // FIXME: Horrible hack to handle BFC->BFM alias.
4228 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4229 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4230 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4231
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004232 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004233 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4234 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4235
4236 if (LSBCE && WidthCE) {
4237 uint64_t LSB = LSBCE->getValue();
4238 uint64_t Width = WidthCE->getValue();
4239
4240 uint64_t RegWidth = 0;
4241 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4242 Op1.getReg()))
4243 RegWidth = 64;
4244 else
4245 RegWidth = 32;
4246
4247 if (LSB >= RegWidth)
4248 return Error(LSBOp.getStartLoc(),
4249 "expected integer in range [0, 31]");
4250 if (Width < 1 || Width > RegWidth)
4251 return Error(WidthOp.getStartLoc(),
4252 "expected integer in range [1, 32]");
4253
4254 uint64_t ImmR = 0;
4255 if (RegWidth == 32)
4256 ImmR = (32 - LSB) & 0x1f;
4257 else
4258 ImmR = (64 - LSB) & 0x3f;
4259
4260 uint64_t ImmS = Width - 1;
4261
4262 if (ImmR != 0 && ImmS >= ImmR)
4263 return Error(WidthOp.getStartLoc(),
4264 "requested insert overflows register");
4265
Jim Grosbach13760bd2015-05-30 01:25:56 +00004266 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4267 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004268 Operands[0] = AArch64Operand::CreateToken(
4269 "bfm", false, Op.getStartLoc(), getContext());
4270 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004271 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4272 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004273 Operands[3] = AArch64Operand::CreateImm(
4274 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4275 Operands.emplace_back(
4276 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4277 WidthOp.getEndLoc(), getContext()));
4278 }
4279 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004280 } else if (NumOperands == 5) {
4281 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4282 // UBFIZ -> UBFM aliases.
4283 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004284 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4285 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4286 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004287
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004288 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004289 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4290 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004291
4292 if (Op3CE && Op4CE) {
4293 uint64_t Op3Val = Op3CE->getValue();
4294 uint64_t Op4Val = Op4CE->getValue();
4295
4296 uint64_t RegWidth = 0;
4297 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004298 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004299 RegWidth = 64;
4300 else
4301 RegWidth = 32;
4302
4303 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004304 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004305 "expected integer in range [0, 31]");
4306 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004307 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004308 "expected integer in range [1, 32]");
4309
4310 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004311 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004312 NewOp3Val = (32 - Op3Val) & 0x1f;
4313 else
4314 NewOp3Val = (64 - Op3Val) & 0x3f;
4315
4316 uint64_t NewOp4Val = Op4Val - 1;
4317
4318 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004319 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004320 "requested insert overflows register");
4321
4322 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004323 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004324 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004325 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004326 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004327 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004328 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004329 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004330 if (Tok == "bfi")
4331 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004332 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004333 else if (Tok == "sbfiz")
4334 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004335 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004336 else if (Tok == "ubfiz")
4337 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004338 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004339 else
4340 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004341 }
4342 }
4343
4344 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4345 // UBFX -> UBFM aliases.
4346 } else if (NumOperands == 5 &&
4347 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004348 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4349 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4350 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004351
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004352 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004353 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4354 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004355
4356 if (Op3CE && Op4CE) {
4357 uint64_t Op3Val = Op3CE->getValue();
4358 uint64_t Op4Val = Op4CE->getValue();
4359
4360 uint64_t RegWidth = 0;
4361 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004362 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004363 RegWidth = 64;
4364 else
4365 RegWidth = 32;
4366
4367 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004368 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004369 "expected integer in range [0, 31]");
4370 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004371 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004372 "expected integer in range [1, 32]");
4373
4374 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4375
4376 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004377 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004378 "requested extract overflows register");
4379
4380 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004381 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004382 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004383 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004384 if (Tok == "bfxil")
4385 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004386 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004387 else if (Tok == "sbfx")
4388 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004389 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004390 else if (Tok == "ubfx")
4391 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004392 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004393 else
4394 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004395 }
4396 }
4397 }
4398 }
Tim Northover9097a072017-12-18 10:36:00 +00004399
4400 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4401 // instruction for FP registers correctly in some rare circumstances. Convert
4402 // it to a safe instruction and warn (because silently changing someone's
4403 // assembly is rude).
4404 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4405 NumOperands == 4 && Tok == "movi") {
4406 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4407 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4408 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4409 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4410 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4411 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4412 if (Suffix.lower() == ".2d" &&
4413 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4414 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4415 " correctly on this CPU, converting to equivalent movi.16b");
4416 // Switch the suffix to .16b.
4417 unsigned Idx = Op1.isToken() ? 1 : 2;
4418 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4419 getContext());
4420 }
4421 }
4422 }
4423
Tim Northover3b0846e2014-05-24 12:50:23 +00004424 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4425 // InstAlias can't quite handle this since the reg classes aren't
4426 // subclasses.
4427 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4428 // The source register can be Wn here, but the matcher expects a
4429 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004430 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004431 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004432 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004433 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4434 Op.getStartLoc(), Op.getEndLoc(),
4435 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004436 }
4437 }
4438 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4439 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004440 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004441 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004442 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004443 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004444 // The source register can be Wn here, but the matcher expects a
4445 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004446 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004447 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004448 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004449 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4450 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004451 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004452 }
4453 }
4454 }
4455 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4456 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004457 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004458 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004459 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004460 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004461 // The source register can be Wn here, but the matcher expects a
4462 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004463 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004464 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004465 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004466 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4467 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004468 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004469 }
4470 }
4471 }
4472
Tim Northover3b0846e2014-05-24 12:50:23 +00004473 MCInst Inst;
4474 // First try to match against the secondary set of tables containing the
4475 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4476 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004477 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004478
4479 // If that fails, try against the alternate table containing long-form NEON:
4480 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004481 if (MatchResult != Match_Success) {
4482 // But first, save the short-form match result: we can use it in case the
4483 // long-form match also fails.
4484 auto ShortFormNEONErrorInfo = ErrorInfo;
4485 auto ShortFormNEONMatchResult = MatchResult;
4486
Tim Northover3b0846e2014-05-24 12:50:23 +00004487 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004488 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004489
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004490 // Now, both matches failed, and the long-form match failed on the mnemonic
4491 // suffix token operand. The short-form match failure is probably more
4492 // relevant: use it instead.
4493 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004494 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004495 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4496 MatchResult = ShortFormNEONMatchResult;
4497 ErrorInfo = ShortFormNEONErrorInfo;
4498 }
4499 }
4500
Tim Northover3b0846e2014-05-24 12:50:23 +00004501 switch (MatchResult) {
4502 case Match_Success: {
4503 // Perform range checking and other semantic validations
4504 SmallVector<SMLoc, 8> OperandLocs;
4505 NumOperands = Operands.size();
4506 for (unsigned i = 1; i < NumOperands; ++i)
4507 OperandLocs.push_back(Operands[i]->getStartLoc());
4508 if (validateInstruction(Inst, OperandLocs))
4509 return true;
4510
4511 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004512 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004513 return false;
4514 }
4515 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004516 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004517 // Special case the error message for the very common case where only
4518 // a single subtarget feature is missing (neon, e.g.).
4519 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004520 uint64_t Mask = 1;
4521 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4522 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004523 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004524 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004525 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004526 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004527 }
4528 return Error(IDLoc, Msg);
4529 }
4530 case Match_MnemonicFail:
Sander de Smalen0325e302018-07-02 07:34:52 +00004531 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004532 case Match_InvalidOperand: {
4533 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004534
Tim Northover26bb14e2014-08-18 11:49:42 +00004535 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004536 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004537 return Error(IDLoc, "too few operands for instruction",
4538 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004539
David Blaikie960ea3f2014-06-08 16:18:35 +00004540 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004541 if (ErrorLoc == SMLoc())
4542 ErrorLoc = IDLoc;
4543 }
4544 // If the match failed on a suffix token operand, tweak the diagnostic
4545 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004546 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4547 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004548 MatchResult = Match_InvalidSuffix;
4549
Sander de Smalen0325e302018-07-02 07:34:52 +00004550 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004551 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004552 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004553 case Match_InvalidMemoryIndexed1:
4554 case Match_InvalidMemoryIndexed2:
4555 case Match_InvalidMemoryIndexed4:
4556 case Match_InvalidMemoryIndexed8:
4557 case Match_InvalidMemoryIndexed16:
4558 case Match_InvalidCondCode:
4559 case Match_AddSubRegExtendSmall:
4560 case Match_AddSubRegExtendLarge:
4561 case Match_AddSubSecondSource:
4562 case Match_LogicalSecondSource:
4563 case Match_AddSubRegShift32:
4564 case Match_AddSubRegShift64:
4565 case Match_InvalidMovImm32Shift:
4566 case Match_InvalidMovImm64Shift:
4567 case Match_InvalidFPImm:
4568 case Match_InvalidMemoryWExtend8:
4569 case Match_InvalidMemoryWExtend16:
4570 case Match_InvalidMemoryWExtend32:
4571 case Match_InvalidMemoryWExtend64:
4572 case Match_InvalidMemoryWExtend128:
4573 case Match_InvalidMemoryXExtend8:
4574 case Match_InvalidMemoryXExtend16:
4575 case Match_InvalidMemoryXExtend32:
4576 case Match_InvalidMemoryXExtend64:
4577 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004578 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004579 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004580 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004581 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004582 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004583 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004584 case Match_InvalidMemoryIndexed4SImm7:
4585 case Match_InvalidMemoryIndexed8SImm7:
4586 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004587 case Match_InvalidMemoryIndexed8UImm5:
4588 case Match_InvalidMemoryIndexed4UImm5:
4589 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004590 case Match_InvalidMemoryIndexed1UImm6:
4591 case Match_InvalidMemoryIndexed2UImm6:
4592 case Match_InvalidMemoryIndexed4UImm6:
4593 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004594 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004595 case Match_InvalidMemoryIndexedSImm5:
Sander de Smalen592718f2018-07-05 07:54:10 +00004596 case Match_InvalidMemoryIndexedSImm8:
Tim Northover3b0846e2014-05-24 12:50:23 +00004597 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004598 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004599 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004600 case Match_InvalidImm0_7:
4601 case Match_InvalidImm0_15:
4602 case Match_InvalidImm0_31:
4603 case Match_InvalidImm0_63:
4604 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004605 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004606 case Match_InvalidImm0_65535:
4607 case Match_InvalidImm1_8:
4608 case Match_InvalidImm1_16:
4609 case Match_InvalidImm1_32:
4610 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004611 case Match_InvalidSVEAddSubImm8:
4612 case Match_InvalidSVEAddSubImm16:
4613 case Match_InvalidSVEAddSubImm32:
4614 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004615 case Match_InvalidSVECpyImm8:
4616 case Match_InvalidSVECpyImm16:
4617 case Match_InvalidSVECpyImm32:
4618 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004619 case Match_InvalidIndexRange1_1:
4620 case Match_InvalidIndexRange0_15:
4621 case Match_InvalidIndexRange0_7:
4622 case Match_InvalidIndexRange0_3:
4623 case Match_InvalidIndexRange0_1:
4624 case Match_InvalidSVEIndexRange0_63:
4625 case Match_InvalidSVEIndexRange0_31:
4626 case Match_InvalidSVEIndexRange0_15:
4627 case Match_InvalidSVEIndexRange0_7:
4628 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004629 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004630 case Match_InvalidComplexRotationEven:
4631 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004632 case Match_InvalidGPR64shifted8:
4633 case Match_InvalidGPR64shifted16:
4634 case Match_InvalidGPR64shifted32:
4635 case Match_InvalidGPR64shifted64:
4636 case Match_InvalidGPR64NoXZRshifted8:
4637 case Match_InvalidGPR64NoXZRshifted16:
4638 case Match_InvalidGPR64NoXZRshifted32:
4639 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004640 case Match_InvalidZPR32UXTW8:
4641 case Match_InvalidZPR32UXTW16:
4642 case Match_InvalidZPR32UXTW32:
4643 case Match_InvalidZPR32UXTW64:
4644 case Match_InvalidZPR32SXTW8:
4645 case Match_InvalidZPR32SXTW16:
4646 case Match_InvalidZPR32SXTW32:
4647 case Match_InvalidZPR32SXTW64:
4648 case Match_InvalidZPR64UXTW8:
4649 case Match_InvalidZPR64SXTW8:
4650 case Match_InvalidZPR64UXTW16:
4651 case Match_InvalidZPR64SXTW16:
4652 case Match_InvalidZPR64UXTW32:
4653 case Match_InvalidZPR64SXTW32:
4654 case Match_InvalidZPR64UXTW64:
4655 case Match_InvalidZPR64SXTW64:
4656 case Match_InvalidZPR64LSL8:
4657 case Match_InvalidZPR64LSL16:
4658 case Match_InvalidZPR64LSL32:
4659 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004660 case Match_InvalidZPR0:
4661 case Match_InvalidZPR8:
4662 case Match_InvalidZPR16:
4663 case Match_InvalidZPR32:
4664 case Match_InvalidZPR64:
4665 case Match_InvalidZPR128:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004666 case Match_InvalidZPR_3b8:
4667 case Match_InvalidZPR_3b16:
4668 case Match_InvalidZPR_3b32:
4669 case Match_InvalidZPR_4b16:
4670 case Match_InvalidZPR_4b32:
4671 case Match_InvalidZPR_4b64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004672 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004673 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004674 case Match_InvalidSVEPredicateBReg:
4675 case Match_InvalidSVEPredicateHReg:
4676 case Match_InvalidSVEPredicateSReg:
4677 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004678 case Match_InvalidSVEPredicate3bAnyReg:
4679 case Match_InvalidSVEPredicate3bBReg:
4680 case Match_InvalidSVEPredicate3bHReg:
4681 case Match_InvalidSVEPredicate3bSReg:
4682 case Match_InvalidSVEPredicate3bDReg:
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004683 case Match_InvalidSVEExactFPImmOperandHalfOne:
4684 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4685 case Match_InvalidSVEExactFPImmOperandZeroOne:
Tim Northover3b0846e2014-05-24 12:50:23 +00004686 case Match_MSR:
4687 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004688 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004689 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004690 // Any time we get here, there's nothing fancy to do. Just get the
4691 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004692 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004693 if (ErrorLoc == SMLoc())
4694 ErrorLoc = IDLoc;
Sander de Smalen0325e302018-07-02 07:34:52 +00004695 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004696 }
4697 }
4698
4699 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004700}
4701
4702/// ParseDirective parses the arm specific directives
4703bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004704 const MCObjectFileInfo::Environment Format =
4705 getContext().getObjectFileInfo()->getObjectFileType();
4706 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4707 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004708
Tim Northover3b0846e2014-05-24 12:50:23 +00004709 StringRef IDVal = DirectiveID.getIdentifier();
4710 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004711 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004712 parseDirectiveArch(Loc);
4713 else if (IDVal == ".cpu")
4714 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00004715 else if (IDVal == ".tlsdesccall")
4716 parseDirectiveTLSDescCall(Loc);
4717 else if (IDVal == ".ltorg" || IDVal == ".pool")
4718 parseDirectiveLtorg(Loc);
4719 else if (IDVal == ".unreq")
4720 parseDirectiveUnreq(Loc);
4721 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004722 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004723 parseDirectiveInst(Loc);
4724 else
4725 return true;
4726 } else if (IDVal == MCLOHDirectiveName())
4727 parseDirectiveLOH(IDVal, Loc);
4728 else
4729 return true;
4730 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004731}
4732
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004733static const struct {
4734 const char *Name;
4735 const FeatureBitset Features;
4736} ExtensionMap[] = {
4737 { "crc", {AArch64::FeatureCRC} },
4738 { "crypto", {AArch64::FeatureCrypto} },
4739 { "fp", {AArch64::FeatureFPARMv8} },
4740 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004741 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004742 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004743
4744 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004745 { "pan", {} },
4746 { "lor", {} },
4747 { "rdma", {} },
4748 { "profile", {} },
4749};
4750
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004751/// parseDirectiveArch
4752/// ::= .arch token
4753bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4754 SMLoc ArchLoc = getLoc();
4755
4756 StringRef Arch, ExtensionString;
4757 std::tie(Arch, ExtensionString) =
4758 getParser().parseStringToEndOfStatement().trim().split('+');
4759
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004760 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4761 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004762 return Error(ArchLoc, "unknown arch name");
4763
4764 if (parseToken(AsmToken::EndOfStatement))
4765 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004766
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004767 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004768 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004769 AArch64::getArchFeatures(ID, AArch64Features);
4770 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4771 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004772
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004773 MCSubtargetInfo &STI = copySTI();
4774 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4775 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4776
4777 SmallVector<StringRef, 4> RequestedExtensions;
4778 if (!ExtensionString.empty())
4779 ExtensionString.split(RequestedExtensions, '+');
4780
4781 FeatureBitset Features = STI.getFeatureBits();
4782 for (auto Name : RequestedExtensions) {
4783 bool EnableFeature = true;
4784
4785 if (Name.startswith_lower("no")) {
4786 EnableFeature = false;
4787 Name = Name.substr(2);
4788 }
4789
4790 for (const auto &Extension : ExtensionMap) {
4791 if (Extension.Name != Name)
4792 continue;
4793
4794 if (Extension.Features.none())
4795 report_fatal_error("unsupported architectural extension: " + Name);
4796
4797 FeatureBitset ToggleFeatures = EnableFeature
4798 ? (~Features & Extension.Features)
4799 : ( Features & Extension.Features);
4800 uint64_t Features =
4801 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4802 setAvailableFeatures(Features);
4803 break;
4804 }
4805 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004806 return false;
4807}
4808
Tim Northover8b96c7e2017-05-15 19:42:15 +00004809static SMLoc incrementLoc(SMLoc L, int Offset) {
4810 return SMLoc::getFromPointer(L.getPointer() + Offset);
4811}
4812
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004813/// parseDirectiveCPU
4814/// ::= .cpu id
4815bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004816 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004817
4818 StringRef CPU, ExtensionString;
4819 std::tie(CPU, ExtensionString) =
4820 getParser().parseStringToEndOfStatement().trim().split('+');
4821
Nirav Davee833c6c2016-11-08 18:31:04 +00004822 if (parseToken(AsmToken::EndOfStatement))
4823 return true;
4824
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004825 SmallVector<StringRef, 4> RequestedExtensions;
4826 if (!ExtensionString.empty())
4827 ExtensionString.split(RequestedExtensions, '+');
4828
4829 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4830 // once that is tablegen'ed
4831 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004832 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004833 return false;
4834 }
4835
4836 MCSubtargetInfo &STI = copySTI();
4837 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004838 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004839
4840 FeatureBitset Features = STI.getFeatureBits();
4841 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004842 // Advance source location past '+'.
4843 CurLoc = incrementLoc(CurLoc, 1);
4844
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004845 bool EnableFeature = true;
4846
4847 if (Name.startswith_lower("no")) {
4848 EnableFeature = false;
4849 Name = Name.substr(2);
4850 }
4851
Tim Northover8b96c7e2017-05-15 19:42:15 +00004852 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004853 for (const auto &Extension : ExtensionMap) {
4854 if (Extension.Name != Name)
4855 continue;
4856
4857 if (Extension.Features.none())
4858 report_fatal_error("unsupported architectural extension: " + Name);
4859
4860 FeatureBitset ToggleFeatures = EnableFeature
4861 ? (~Features & Extension.Features)
4862 : ( Features & Extension.Features);
4863 uint64_t Features =
4864 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4865 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004866 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004867
4868 break;
4869 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004870
4871 if (!FoundExtension)
4872 Error(CurLoc, "unsupported architectural extension");
4873
4874 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004875 }
4876 return false;
4877}
4878
Chad Rosierdcd2a302014-10-22 20:35:57 +00004879/// parseDirectiveInst
4880/// ::= .inst opcode [, ...]
4881bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004882 if (getLexer().is(AsmToken::EndOfStatement))
4883 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004884
Nirav Davee833c6c2016-11-08 18:31:04 +00004885 auto parseOp = [&]() -> bool {
4886 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004887 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004888 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4889 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004890 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004891 if (check(!Value, L, "expected constant expression"))
4892 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004893 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004894 return false;
4895 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004896
Nirav Davee833c6c2016-11-08 18:31:04 +00004897 if (parseMany(parseOp))
4898 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004899 return false;
4900}
4901
Tim Northover3b0846e2014-05-24 12:50:23 +00004902// parseDirectiveTLSDescCall:
4903// ::= .tlsdesccall symbol
4904bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4905 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004906 if (check(getParser().parseIdentifier(Name), L,
4907 "expected symbol after directive") ||
4908 parseToken(AsmToken::EndOfStatement))
4909 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004910
Jim Grosbach6f482002015-05-18 18:43:14 +00004911 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004912 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4913 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004914
4915 MCInst Inst;
4916 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004917 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004918
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004919 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004920 return false;
4921}
4922
4923/// ::= .loh <lohName | lohId> label1, ..., labelN
4924/// The number of arguments depends on the loh identifier.
4925bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004926 MCLOHType Kind;
4927 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4928 if (getParser().getTok().isNot(AsmToken::Integer))
4929 return TokError("expected an identifier or a number in directive");
4930 // We successfully get a numeric value for the identifier.
4931 // Check if it is valid.
4932 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004933 if (Id <= -1U && !isValidMCLOHType(Id))
4934 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004935 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004936 } else {
4937 StringRef Name = getTok().getIdentifier();
4938 // We successfully parse an identifier.
4939 // Check if it is a recognized one.
4940 int Id = MCLOHNameToId(Name);
4941
4942 if (Id == -1)
4943 return TokError("invalid identifier in directive");
4944 Kind = (MCLOHType)Id;
4945 }
4946 // Consume the identifier.
4947 Lex();
4948 // Get the number of arguments of this LOH.
4949 int NbArgs = MCLOHIdToNbArgs(Kind);
4950
4951 assert(NbArgs != -1 && "Invalid number of arguments");
4952
4953 SmallVector<MCSymbol *, 3> Args;
4954 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4955 StringRef Name;
4956 if (getParser().parseIdentifier(Name))
4957 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004958 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004959
4960 if (Idx + 1 == NbArgs)
4961 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004962 if (parseToken(AsmToken::Comma,
4963 "unexpected token in '" + Twine(IDVal) + "' directive"))
4964 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004965 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004966 if (parseToken(AsmToken::EndOfStatement,
4967 "unexpected token in '" + Twine(IDVal) + "' directive"))
4968 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004969
4970 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4971 return false;
4972}
4973
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004974/// parseDirectiveLtorg
4975/// ::= .ltorg | .pool
4976bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004977 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4978 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004979 getTargetStreamer().emitCurrentConstantPool();
4980 return false;
4981}
4982
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004983/// parseDirectiveReq
4984/// ::= name .req registername
4985bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004986 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004987 Parser.Lex(); // Eat the '.req' token.
4988 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004989 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004990 unsigned RegNum;
4991 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004992
Sander de Smalen50d87022018-04-19 07:35:08 +00004993 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004994 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004995 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004996 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004997
Sander de Smalen50d87022018-04-19 07:35:08 +00004998 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004999 return true;
5000
Sander de Smalen50d87022018-04-19 07:35:08 +00005001 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00005002 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005003 }
5004
Sander de Smalen50d87022018-04-19 07:35:08 +00005005 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005006 StringRef Kind;
5007 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005008 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00005009 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005010
Sander de Smalen50d87022018-04-19 07:35:08 +00005011 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00005012 return true;
5013
Sander de Smalen50d87022018-04-19 07:35:08 +00005014 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00005015 return Error(SRegLoc,
5016 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00005017 }
5018
Sander de Smalen50d87022018-04-19 07:35:08 +00005019 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00005020 StringRef Kind;
5021 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005022 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00005023
Sander de Smalen50d87022018-04-19 07:35:08 +00005024 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00005025 return true;
5026
Sander de Smalen50d87022018-04-19 07:35:08 +00005027 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00005028 return Error(SRegLoc,
5029 "sve predicate register without type specifier expected");
5030 }
5031
Sander de Smalen50d87022018-04-19 07:35:08 +00005032 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00005033 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005034
5035 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00005036 if (parseToken(AsmToken::EndOfStatement,
5037 "unexpected input in .req directive"))
5038 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005039
Sander de Smalen8e607342017-11-15 15:44:43 +00005040 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00005041 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005042 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
5043
Nirav Dave2364748a2016-09-16 18:30:20 +00005044 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005045}
5046
5047/// parseDirectiveUneq
5048/// ::= .unreq registername
5049bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005050 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00005051 if (getTok().isNot(AsmToken::Identifier))
5052 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005053 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
5054 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00005055 if (parseToken(AsmToken::EndOfStatement))
5056 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005057 return false;
5058}
5059
Tim Northover3b0846e2014-05-24 12:50:23 +00005060bool
5061AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
5062 AArch64MCExpr::VariantKind &ELFRefKind,
5063 MCSymbolRefExpr::VariantKind &DarwinRefKind,
5064 int64_t &Addend) {
5065 ELFRefKind = AArch64MCExpr::VK_INVALID;
5066 DarwinRefKind = MCSymbolRefExpr::VK_None;
5067 Addend = 0;
5068
5069 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5070 ELFRefKind = AE->getKind();
5071 Expr = AE->getSubExpr();
5072 }
5073
5074 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5075 if (SE) {
5076 // It's a simple symbol reference with no addend.
5077 DarwinRefKind = SE->getKind();
5078 return true;
5079 }
5080
5081 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
5082 if (!BE)
5083 return false;
5084
5085 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
5086 if (!SE)
5087 return false;
5088 DarwinRefKind = SE->getKind();
5089
5090 if (BE->getOpcode() != MCBinaryExpr::Add &&
5091 BE->getOpcode() != MCBinaryExpr::Sub)
5092 return false;
5093
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00005094 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00005095 // on here than we can deal with.
5096 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
5097 if (!AddendExpr)
5098 return false;
5099
5100 Addend = AddendExpr->getValue();
5101 if (BE->getOpcode() == MCBinaryExpr::Sub)
5102 Addend = -Addend;
5103
5104 // It's some symbol reference + a constant addend, but really
5105 // shouldn't use both Darwin and ELF syntax.
5106 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5107 DarwinRefKind == MCSymbolRefExpr::VK_None;
5108}
5109
5110/// Force static initialization.
5111extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00005112 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5113 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5114 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00005115}
5116
5117#define GET_REGISTER_MATCHER
5118#define GET_SUBTARGET_FEATURE_NAME
5119#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00005120#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00005121#include "AArch64GenAsmMatcher.inc"
5122
5123// Define this matcher function after the auto-generated include so we
5124// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00005125unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00005126 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005127 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00005128 // If the kind is a token for a literal immediate, check if our asm
5129 // operand matches. This is for InstAliases which have a fixed-value
5130 // immediate in the syntax.
5131 int64_t ExpectedVal;
5132 switch (Kind) {
5133 default:
5134 return Match_InvalidOperand;
5135 case MCK__35_0:
5136 ExpectedVal = 0;
5137 break;
5138 case MCK__35_1:
5139 ExpectedVal = 1;
5140 break;
5141 case MCK__35_12:
5142 ExpectedVal = 12;
5143 break;
5144 case MCK__35_16:
5145 ExpectedVal = 16;
5146 break;
5147 case MCK__35_2:
5148 ExpectedVal = 2;
5149 break;
5150 case MCK__35_24:
5151 ExpectedVal = 24;
5152 break;
5153 case MCK__35_3:
5154 ExpectedVal = 3;
5155 break;
5156 case MCK__35_32:
5157 ExpectedVal = 32;
5158 break;
5159 case MCK__35_4:
5160 ExpectedVal = 4;
5161 break;
5162 case MCK__35_48:
5163 ExpectedVal = 48;
5164 break;
5165 case MCK__35_6:
5166 ExpectedVal = 6;
5167 break;
5168 case MCK__35_64:
5169 ExpectedVal = 64;
5170 break;
5171 case MCK__35_8:
5172 ExpectedVal = 8;
5173 break;
5174 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005175 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005176 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005177 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005178 if (!CE)
5179 return Match_InvalidOperand;
5180 if (CE->getValue() == ExpectedVal)
5181 return Match_Success;
5182 return Match_InvalidOperand;
5183}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005184
Alex Bradbury58eba092016-11-01 16:32:05 +00005185OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005186AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5187
5188 SMLoc S = getLoc();
5189
5190 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5191 Error(S, "expected register");
5192 return MatchOperand_ParseFail;
5193 }
5194
Sander de Smalen50d87022018-04-19 07:35:08 +00005195 unsigned FirstReg;
5196 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5197 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005198 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005199
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005200 const MCRegisterClass &WRegClass =
5201 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5202 const MCRegisterClass &XRegClass =
5203 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5204
5205 bool isXReg = XRegClass.contains(FirstReg),
5206 isWReg = WRegClass.contains(FirstReg);
5207 if (!isXReg && !isWReg) {
5208 Error(S, "expected first even register of a "
5209 "consecutive same-size even/odd register pair");
5210 return MatchOperand_ParseFail;
5211 }
5212
5213 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5214 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5215
5216 if (FirstEncoding & 0x1) {
5217 Error(S, "expected first even register of a "
5218 "consecutive same-size even/odd register pair");
5219 return MatchOperand_ParseFail;
5220 }
5221
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005222 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005223 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005224 return MatchOperand_ParseFail;
5225 }
5226 // Eat the comma
5227 getParser().Lex();
5228
5229 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005230 unsigned SecondReg;
5231 Res = tryParseScalarRegister(SecondReg);
5232 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005233 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005234
Eugene Zelenko049b0172017-01-06 00:30:53 +00005235 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005236 (isXReg && !XRegClass.contains(SecondReg)) ||
5237 (isWReg && !WRegClass.contains(SecondReg))) {
5238 Error(E,"expected second odd register of a "
5239 "consecutive same-size even/odd register pair");
5240 return MatchOperand_ParseFail;
5241 }
Joel Jones504bf332016-10-24 13:37:13 +00005242
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005243 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005244 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005245 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5246 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5247 } else {
5248 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5249 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5250 }
5251
Florian Hahnc4422242017-11-07 13:07:50 +00005252 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5253 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005254
5255 return MatchOperand_Success;
5256}
Florian Hahn91f11e52017-11-07 16:45:48 +00005257
Sander de Smaleneb896b12018-04-25 09:26:47 +00005258template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005259OperandMatchResultTy
5260AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005261 const SMLoc S = getLoc();
5262 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005263 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005264 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005265
Sander de Smalen8e607342017-11-15 15:44:43 +00005266 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005267 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005268
5269 if (Res != MatchOperand_Success)
5270 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005271
5272 if (ParseSuffix && Kind.empty())
5273 return MatchOperand_NoMatch;
5274
Sander de Smalen73937b72018-04-11 07:36:10 +00005275 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5276 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005277 return MatchOperand_NoMatch;
5278
Sander de Smalen73937b72018-04-11 07:36:10 +00005279 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005280
5281 // No shift/extend is the default.
5282 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5283 Operands.push_back(AArch64Operand::CreateVectorReg(
5284 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5285
Sander de Smalenc33d6682018-06-04 06:40:55 +00005286 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5287 if (Res == MatchOperand_ParseFail)
5288 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005289 return MatchOperand_Success;
5290 }
5291
5292 // Eat the comma
5293 getParser().Lex();
5294
5295 // Match the shift
5296 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5297 Res = tryParseOptionalShiftExtend(ExtOpnd);
5298 if (Res != MatchOperand_Success)
5299 return Res;
5300
5301 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005302 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005303 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5304 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5305 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005306
5307 return MatchOperand_Success;
5308}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005309
5310OperandMatchResultTy
5311AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5312 MCAsmParser &Parser = getParser();
5313
5314 SMLoc SS = getLoc();
5315 const AsmToken &TokE = Parser.getTok();
5316 bool IsHash = TokE.is(AsmToken::Hash);
5317
5318 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5319 return MatchOperand_NoMatch;
5320
5321 int64_t Pattern;
5322 if (IsHash) {
5323 Parser.Lex(); // Eat hash
5324
5325 // Parse the immediate operand.
5326 const MCExpr *ImmVal;
5327 SS = getLoc();
5328 if (Parser.parseExpression(ImmVal))
5329 return MatchOperand_ParseFail;
5330
5331 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5332 if (!MCE)
5333 return MatchOperand_ParseFail;
5334
5335 Pattern = MCE->getValue();
5336 } else {
5337 // Parse the pattern
5338 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5339 if (!Pat)
5340 return MatchOperand_NoMatch;
5341
5342 Parser.Lex();
5343 Pattern = Pat->Encoding;
5344 assert(Pattern >= 0 && Pattern < 32);
5345 }
5346
5347 Operands.push_back(
5348 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5349 SS, getLoc(), getContext()));
5350
5351 return MatchOperand_Success;
5352}