blob: bef18d7127300ac963b4c63ddca9a2a710e297f2 [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
540 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
541
Sander de Smalen50ded902018-04-29 17:33:38 +0000542 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
543 return isImmScaled<Bits, Scale>(true);
544 }
545
546 template <int Bits, int Scale> DiagnosticPredicate isUImmScaled() const {
547 return isImmScaled<Bits, Scale>(false);
548 }
549
Sander de Smalenfe17a782018-04-26 12:54:42 +0000550 template <int Bits, int Scale>
Sander de Smalen50ded902018-04-29 17:33:38 +0000551 DiagnosticPredicate isImmScaled(bool Signed) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000552 if (!isImm())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000553 return DiagnosticPredicateTy::NoMatch;
554
Tim Northover3b0846e2014-05-24 12:50:23 +0000555 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
556 if (!MCE)
Sander de Smalenfe17a782018-04-26 12:54:42 +0000557 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000558
Sander de Smalen50ded902018-04-29 17:33:38 +0000559 int64_t MinVal, MaxVal;
560 if (Signed) {
561 int64_t Shift = Bits - 1;
562 MinVal = (int64_t(1) << Shift) * -Scale;
563 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
564 } else {
565 MinVal = 0;
566 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
567 }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000568
Tim Northover3b0846e2014-05-24 12:50:23 +0000569 int64_t Val = MCE->getValue();
Sander de Smalenfe17a782018-04-26 12:54:42 +0000570 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
571 return DiagnosticPredicateTy::Match;
572
573 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +0000574 }
575
Sander de Smalen0325e302018-07-02 07:34:52 +0000576 DiagnosticPredicate isSVEPattern() const {
Sander de Smalen245e0e62018-01-22 10:46:00 +0000577 if (!isImm())
Sander de Smalen0325e302018-07-02 07:34:52 +0000578 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000579 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
580 if (!MCE)
Sander de Smalen0325e302018-07-02 07:34:52 +0000581 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000582 int64_t Val = MCE->getValue();
Sander de Smalen0325e302018-07-02 07:34:52 +0000583 if (Val >= 0 && Val < 32)
584 return DiagnosticPredicateTy::Match;
585 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000586 }
587
Tim Northover3b0846e2014-05-24 12:50:23 +0000588 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
589 AArch64MCExpr::VariantKind ELFRefKind;
590 MCSymbolRefExpr::VariantKind DarwinRefKind;
591 int64_t Addend;
592 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
593 Addend)) {
594 // If we don't understand the expression, assume the best and
595 // let the fixup and relocation code deal with it.
596 return true;
597 }
598
599 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
600 ELFRefKind == AArch64MCExpr::VK_LO12 ||
601 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
602 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
603 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
604 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
605 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
606 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000607 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
608 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
609 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000610 // Note that we don't range-check the addend. It's adjusted modulo page
611 // size when converted, so there is no "out of range" condition when using
612 // @pageoff.
613 return Addend >= 0 && (Addend % Scale) == 0;
614 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
615 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
616 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
617 return Addend == 0;
618 }
619
620 return false;
621 }
622
623 template <int Scale> bool isUImm12Offset() const {
624 if (!isImm())
625 return false;
626
627 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
628 if (!MCE)
629 return isSymbolicUImm12Offset(getImm(), Scale);
630
631 int64_t Val = MCE->getValue();
632 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
633 }
634
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000635 template <int N, int M>
636 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000637 if (!isImm())
638 return false;
639 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
640 if (!MCE)
641 return false;
642 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000643 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000644 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000645
Sander de Smalena1c259c2018-01-29 13:05:38 +0000646 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
647 // a logical immediate can always be represented when inverted.
648 template <typename T>
649 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000650 if (!isImm())
651 return false;
652 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
653 if (!MCE)
654 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000655
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000656 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000657 int64_t SVal = typename std::make_signed<T>::type(Val);
658 int64_t UVal = typename std::make_unsigned<T>::type(Val);
659 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000660 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000661
Sander de Smalena1c259c2018-01-29 13:05:38 +0000662 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000663 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000664
Tim Northover3b0846e2014-05-24 12:50:23 +0000665 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000666
Sander de Smalen62770792018-05-25 09:47:52 +0000667 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
668 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
669 /// immediate that can be shifted by 'Shift'.
670 template <unsigned Width>
671 Optional<std::pair<int64_t, unsigned> > getShiftedVal() const {
672 if (isShiftedImm() && Width == getShiftedImmShift())
673 if (auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
674 return std::make_pair(CE->getValue(), Width);
675
676 if (isImm())
677 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
678 int64_t Val = CE->getValue();
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000679 if ((Val != 0) && (uint64_t(Val >> Width) << Width) == uint64_t(Val))
Sander de Smalen62770792018-05-25 09:47:52 +0000680 return std::make_pair(Val >> Width, Width);
681 else
682 return std::make_pair(Val, 0u);
683 }
684
685 return {};
686 }
687
Tim Northover3b0846e2014-05-24 12:50:23 +0000688 bool isAddSubImm() const {
689 if (!isShiftedImm() && !isImm())
690 return false;
691
692 const MCExpr *Expr;
693
694 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
695 if (isShiftedImm()) {
696 unsigned Shift = ShiftedImm.ShiftAmount;
697 Expr = ShiftedImm.Val;
698 if (Shift != 0 && Shift != 12)
699 return false;
700 } else {
701 Expr = getImm();
702 }
703
704 AArch64MCExpr::VariantKind ELFRefKind;
705 MCSymbolRefExpr::VariantKind DarwinRefKind;
706 int64_t Addend;
707 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
708 DarwinRefKind, Addend)) {
709 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
710 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
711 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
712 || ELFRefKind == AArch64MCExpr::VK_LO12
713 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
714 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
715 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
716 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
717 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
718 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000719 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
720 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
721 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000722 }
723
Sander de Smalen98686c62018-05-29 10:39:49 +0000724 // If it's a constant, it should be a real immediate in range.
Sander de Smalen62770792018-05-25 09:47:52 +0000725 if (auto ShiftedVal = getShiftedVal<12>())
726 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
Diana Picusc93518d2016-10-11 09:17:47 +0000727
728 // If it's an expression, we hope for the best and let the fixup/relocation
729 // code deal with it.
730 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000731 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000732
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000733 bool isAddSubImmNeg() const {
734 if (!isShiftedImm() && !isImm())
735 return false;
736
Sander de Smalen98686c62018-05-29 10:39:49 +0000737 // Otherwise it should be a real negative immediate in range.
738 if (auto ShiftedVal = getShiftedVal<12>())
739 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000740
Sander de Smalen98686c62018-05-29 10:39:49 +0000741 return false;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000742 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000743
Sander de Smalen62770792018-05-25 09:47:52 +0000744 // Signed value in the range -128 to +127. For element widths of
745 // 16 bits or higher it may also be a signed multiple of 256 in the
746 // range -32768 to +32512.
747 // For element-width of 8 bits a range of -128 to 255 is accepted,
748 // since a copy of a byte can be either signed/unsigned.
749 template <typename T>
750 DiagnosticPredicate isSVECpyImm() const {
751 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
752 return DiagnosticPredicateTy::NoMatch;
753
754 bool IsByte =
755 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
756 if (auto ShiftedImm = getShiftedVal<8>())
757 if (!(IsByte && ShiftedImm->second) &&
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000758 AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
759 << ShiftedImm->second))
Sander de Smalen62770792018-05-25 09:47:52 +0000760 return DiagnosticPredicateTy::Match;
761
762 return DiagnosticPredicateTy::NearMatch;
763 }
764
Sander de Smalen98686c62018-05-29 10:39:49 +0000765 // Unsigned value in the range 0 to 255. For element widths of
766 // 16 bits or higher it may also be a signed multiple of 256 in the
767 // range 0 to 65280.
768 template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
769 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
770 return DiagnosticPredicateTy::NoMatch;
771
772 bool IsByte =
773 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
774 if (auto ShiftedImm = getShiftedVal<8>())
775 if (!(IsByte && ShiftedImm->second) &&
776 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
777 << ShiftedImm->second))
778 return DiagnosticPredicateTy::Match;
779
780 return DiagnosticPredicateTy::NearMatch;
781 }
782
Sander de Smalen97ca6b92018-06-01 07:25:46 +0000783 template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
784 if (isLogicalImm<T>() && !isSVECpyImm<T>())
785 return DiagnosticPredicateTy::Match;
786 return DiagnosticPredicateTy::NoMatch;
787 }
788
Tim Northover3b0846e2014-05-24 12:50:23 +0000789 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000790
Tim Northover3b0846e2014-05-24 12:50:23 +0000791 bool isSIMDImmType10() const {
792 if (!isImm())
793 return false;
794 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
795 if (!MCE)
796 return false;
797 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
798 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000799
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000800 template<int N>
801 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000802 if (!isImm())
803 return false;
804 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
805 if (!MCE)
806 return true;
807 int64_t Val = MCE->getValue();
808 if (Val & 0x3)
809 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000810 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
811 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000812 }
813
814 bool
815 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
816 if (!isImm())
817 return false;
818
819 AArch64MCExpr::VariantKind ELFRefKind;
820 MCSymbolRefExpr::VariantKind DarwinRefKind;
821 int64_t Addend;
822 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
823 DarwinRefKind, Addend)) {
824 return false;
825 }
826 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
827 return false;
828
829 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
830 if (ELFRefKind == AllowedModifiers[i])
831 return Addend == 0;
832 }
833
834 return false;
835 }
836
837 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000838 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000839 }
840
841 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000842 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
843 AArch64MCExpr::VK_TPREL_G2,
844 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000845 }
846
847 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000848 return isMovWSymbol({
849 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000850 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
851 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000852 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000853 }
854
855 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000856 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
857 AArch64MCExpr::VK_TPREL_G0,
858 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000859 }
860
861 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000862 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000863 }
864
865 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000866 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000867 }
868
869 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000870 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
871 AArch64MCExpr::VK_TPREL_G1_NC,
872 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000873 }
874
875 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000876 return isMovWSymbol(
877 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
878 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000879 }
880
881 template<int RegWidth, int Shift>
882 bool isMOVZMovAlias() const {
883 if (!isImm()) return false;
884
885 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
886 if (!CE) return false;
887 uint64_t Value = CE->getValue();
888
Tim Northoverdaa1c012016-06-16 01:42:25 +0000889 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000890 }
891
892 template<int RegWidth, int Shift>
893 bool isMOVNMovAlias() const {
894 if (!isImm()) return false;
895
896 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
897 if (!CE) return false;
898 uint64_t Value = CE->getValue();
899
Tim Northoverdaa1c012016-06-16 01:42:25 +0000900 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000901 }
902
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000903 bool isFPImm() const {
904 return Kind == k_FPImm &&
905 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt()) != -1;
906 }
907
Tim Northover3b0846e2014-05-24 12:50:23 +0000908 bool isBarrier() const { return Kind == k_Barrier; }
909 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000910
Tim Northover3b0846e2014-05-24 12:50:23 +0000911 bool isMRSSystemRegister() const {
912 if (!isSysReg()) return false;
913
Tim Northover7cd58932015-01-22 17:23:04 +0000914 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000915 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000916
Tim Northover3b0846e2014-05-24 12:50:23 +0000917 bool isMSRSystemRegister() const {
918 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000919 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000920 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000921
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000922 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000923 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000924 return (SysReg.PStateField == AArch64PState::PAN ||
925 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000926 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000927
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000928 bool isSystemPStateFieldWithImm0_15() const {
929 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000930 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000931 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000932
Florian Hahnc4422242017-11-07 13:07:50 +0000933 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000934 return Kind == k_Register;
935 }
936
937 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000938 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
939 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000940
Florian Hahnc4422242017-11-07 13:07:50 +0000941 bool isNeonVectorReg() const {
942 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
943 }
944
945 bool isNeonVectorRegLo() const {
946 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000947 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
948 Reg.RegNum);
949 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000950
Sander de Smalencd6be962017-12-20 11:02:42 +0000951 template <unsigned Class> bool isSVEVectorReg() const {
952 RegKind RK;
953 switch (Class) {
954 case AArch64::ZPRRegClassID:
955 RK = RegKind::SVEDataVector;
956 break;
957 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000958 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000959 RK = RegKind::SVEPredicateVector;
960 break;
961 default:
962 llvm_unreachable("Unsupport register class");
963 }
964
965 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000966 AArch64MCRegisterClasses[Class].contains(getReg());
967 }
968
Sander de Smalenfd54a782018-06-04 07:07:35 +0000969 template <unsigned Class> bool isFPRasZPR() const {
970 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
971 AArch64MCRegisterClasses[Class].contains(getReg());
972 }
973
Sander de Smalencd6be962017-12-20 11:02:42 +0000974 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +0000975 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
976 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
977 return DiagnosticPredicateTy::NoMatch;
978
979 if (isSVEVectorReg<Class>() &&
980 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
981 return DiagnosticPredicateTy::Match;
982
983 return DiagnosticPredicateTy::NearMatch;
984 }
985
986 template <int ElementWidth, unsigned Class>
987 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
988 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
989 return DiagnosticPredicateTy::NoMatch;
990
991 if (isSVEVectorReg<Class>() &&
992 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
993 return DiagnosticPredicateTy::Match;
994
995 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +0000996 }
997
Sander de Smaleneb896b12018-04-25 09:26:47 +0000998 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +0000999 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
1000 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +00001001 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
1002 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
1003 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001004 return DiagnosticPredicateTy::NoMatch;
1005
Sander de Smalen5861c262018-04-30 07:24:38 +00001006 // Give a more specific diagnostic when the user has explicitly typed in
1007 // a shift-amount that does not match what is expected, but for which
1008 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
1009 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
1010 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
1011 ShiftExtendTy == AArch64_AM::SXTW) &&
1012 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
1013 return DiagnosticPredicateTy::NoMatch;
1014
1015 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001016 return DiagnosticPredicateTy::Match;
1017
1018 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +00001019 }
1020
Tim Northover3b0846e2014-05-24 12:50:23 +00001021 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001022 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001023 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
1024 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001025
Sander de Smalen0325e302018-07-02 07:34:52 +00001026 bool isGPR64as32() const {
1027 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1028 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(Reg.RegNum);
1029 }
1030
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001031 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001032 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001033 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
1034 Reg.RegNum);
1035 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001036
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001037 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001038 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001039 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1040 Reg.RegNum);
1041 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001042
Sam Parker5f934642017-08-31 09:27:04 +00001043 template<int64_t Angle, int64_t Remainder>
1044 bool isComplexRotation() const {
1045 if (!isImm()) return false;
1046
1047 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1048 if (!CE) return false;
1049 uint64_t Value = CE->getValue();
1050
1051 return (Value % Angle == Remainder && Value <= 270);
1052 }
1053
Sander de Smalen149916d2018-04-20 07:24:20 +00001054 template <unsigned RegClassID> bool isGPR64() const {
1055 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1056 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1057 }
1058
1059 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001060 DiagnosticPredicate isGPR64WithShiftExtend() const {
1061 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1062 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001063
Sander de Smalenfe17a782018-04-26 12:54:42 +00001064 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1065 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1066 return DiagnosticPredicateTy::Match;
1067 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001068 }
1069
Tim Northover3b0846e2014-05-24 12:50:23 +00001070 /// Is this a vector list with the type implicit (presumably attached to the
1071 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001072 template <RegKind VectorKind, unsigned NumRegs>
1073 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001074 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001075 VectorList.NumElements == 0 &&
1076 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001077 }
1078
Sander de Smalen650234b2018-04-12 11:40:52 +00001079 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1080 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001081 bool isTypedVectorList() const {
1082 if (Kind != k_VectorList)
1083 return false;
1084 if (VectorList.Count != NumRegs)
1085 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001086 if (VectorList.RegisterKind != VectorKind)
1087 return false;
1088 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001089 return false;
1090 return VectorList.NumElements == NumElements;
1091 }
1092
Sander de Smalenc33d6682018-06-04 06:40:55 +00001093 template <int Min, int Max>
1094 DiagnosticPredicate isVectorIndex() const {
1095 if (Kind != k_VectorIndex)
1096 return DiagnosticPredicateTy::NoMatch;
1097 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1098 return DiagnosticPredicateTy::Match;
1099 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001100 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001101
Tim Northover3b0846e2014-05-24 12:50:23 +00001102 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001103
Tim Northover3b0846e2014-05-24 12:50:23 +00001104 bool isTokenEqual(StringRef Str) const {
1105 return Kind == k_Token && getToken() == Str;
1106 }
1107 bool isSysCR() const { return Kind == k_SysCR; }
1108 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001109 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001110 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1111 bool isShifter() const {
1112 if (!isShiftExtend())
1113 return false;
1114
1115 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1116 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1117 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1118 ST == AArch64_AM::MSL);
1119 }
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001120
1121 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1122 if (Kind != k_FPImm)
1123 return DiagnosticPredicateTy::NoMatch;
1124
1125 if (getFPImmIsExact()) {
1126 // Lookup the immediate from table of supported immediates.
1127 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1128 assert(Desc && "Unknown enum value");
1129
1130 // Calculate its FP value.
1131 APFloat RealVal(APFloat::IEEEdouble());
1132 if (RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero) !=
1133 APFloat::opOK)
1134 llvm_unreachable("FP immediate is not exact");
1135
1136 if (getFPImm().bitwiseIsEqual(RealVal))
1137 return DiagnosticPredicateTy::Match;
1138 }
1139
1140 return DiagnosticPredicateTy::NearMatch;
1141 }
1142
1143 template <unsigned ImmA, unsigned ImmB>
1144 DiagnosticPredicate isExactFPImm() const {
1145 DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1146 if ((Res = isExactFPImm<ImmA>()))
1147 return DiagnosticPredicateTy::Match;
1148 if ((Res = isExactFPImm<ImmB>()))
1149 return DiagnosticPredicateTy::Match;
1150 return Res;
1151 }
1152
Tim Northover3b0846e2014-05-24 12:50:23 +00001153 bool isExtend() const {
1154 if (!isShiftExtend())
1155 return false;
1156
1157 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1158 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1159 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1160 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1161 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1162 ET == AArch64_AM::LSL) &&
1163 getShiftExtendAmount() <= 4;
1164 }
1165
1166 bool isExtend64() const {
1167 if (!isExtend())
1168 return false;
1169 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1170 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1171 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1172 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001173
Tim Northover3b0846e2014-05-24 12:50:23 +00001174 bool isExtendLSL64() const {
1175 if (!isExtend())
1176 return false;
1177 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1178 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1179 ET == AArch64_AM::LSL) &&
1180 getShiftExtendAmount() <= 4;
1181 }
1182
1183 template<int Width> bool isMemXExtend() const {
1184 if (!isExtend())
1185 return false;
1186 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1187 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1188 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1189 getShiftExtendAmount() == 0);
1190 }
1191
1192 template<int Width> bool isMemWExtend() const {
1193 if (!isExtend())
1194 return false;
1195 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1196 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1197 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1198 getShiftExtendAmount() == 0);
1199 }
1200
1201 template <unsigned width>
1202 bool isArithmeticShifter() const {
1203 if (!isShifter())
1204 return false;
1205
1206 // An arithmetic shifter is LSL, LSR, or ASR.
1207 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1208 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1209 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1210 }
1211
1212 template <unsigned width>
1213 bool isLogicalShifter() const {
1214 if (!isShifter())
1215 return false;
1216
1217 // A logical shifter is LSL, LSR, ASR or ROR.
1218 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1219 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1220 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1221 getShiftExtendAmount() < width;
1222 }
1223
1224 bool isMovImm32Shifter() const {
1225 if (!isShifter())
1226 return false;
1227
1228 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1229 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1230 if (ST != AArch64_AM::LSL)
1231 return false;
1232 uint64_t Val = getShiftExtendAmount();
1233 return (Val == 0 || Val == 16);
1234 }
1235
1236 bool isMovImm64Shifter() const {
1237 if (!isShifter())
1238 return false;
1239
1240 // A MOVi shifter is LSL of 0 or 16.
1241 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1242 if (ST != AArch64_AM::LSL)
1243 return false;
1244 uint64_t Val = getShiftExtendAmount();
1245 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1246 }
1247
1248 bool isLogicalVecShifter() const {
1249 if (!isShifter())
1250 return false;
1251
1252 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1253 unsigned Shift = getShiftExtendAmount();
1254 return getShiftExtendType() == AArch64_AM::LSL &&
1255 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1256 }
1257
1258 bool isLogicalVecHalfWordShifter() const {
1259 if (!isLogicalVecShifter())
1260 return false;
1261
1262 // A logical vector shifter is a left shift by 0 or 8.
1263 unsigned Shift = getShiftExtendAmount();
1264 return getShiftExtendType() == AArch64_AM::LSL &&
1265 (Shift == 0 || Shift == 8);
1266 }
1267
1268 bool isMoveVecShifter() const {
1269 if (!isShiftExtend())
1270 return false;
1271
1272 // A logical vector shifter is a left shift by 8 or 16.
1273 unsigned Shift = getShiftExtendAmount();
1274 return getShiftExtendType() == AArch64_AM::MSL &&
1275 (Shift == 8 || Shift == 16);
1276 }
1277
1278 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1279 // to LDUR/STUR when the offset is not legal for the former but is for
1280 // the latter. As such, in addition to checking for being a legal unscaled
1281 // address, also check that it is not a legal scaled address. This avoids
1282 // ambiguity in the matcher.
1283 template<int Width>
1284 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001285 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001286 }
1287
1288 bool isAdrpLabel() const {
1289 // Validation was handled during parsing, so we just sanity check that
1290 // something didn't go haywire.
1291 if (!isImm())
1292 return false;
1293
1294 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1295 int64_t Val = CE->getValue();
1296 int64_t Min = - (4096 * (1LL << (21 - 1)));
1297 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1298 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1299 }
1300
1301 return true;
1302 }
1303
1304 bool isAdrLabel() const {
1305 // Validation was handled during parsing, so we just sanity check that
1306 // something didn't go haywire.
1307 if (!isImm())
1308 return false;
1309
1310 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1311 int64_t Val = CE->getValue();
1312 int64_t Min = - (1LL << (21 - 1));
1313 int64_t Max = ((1LL << (21 - 1)) - 1);
1314 return Val >= Min && Val <= Max;
1315 }
1316
1317 return true;
1318 }
1319
1320 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1321 // Add as immediates when possible. Null MCExpr = 0.
1322 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001323 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001324 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001325 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001326 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001327 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001328 }
1329
1330 void addRegOperands(MCInst &Inst, unsigned N) const {
1331 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001332 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001333 }
1334
1335 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1336 assert(N == 1 && "Invalid number of operands!");
1337 assert(
1338 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1339
1340 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1341 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1342 RI->getEncodingValue(getReg()));
1343
Jim Grosbache9119e42015-05-13 18:37:00 +00001344 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001345 }
1346
Sander de Smalen0325e302018-07-02 07:34:52 +00001347 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1348 assert(N == 1 && "Invalid number of operands!");
1349 assert(
1350 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(getReg()));
1351
1352 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1353 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID).getRegister(
1354 RI->getEncodingValue(getReg()));
1355
1356 Inst.addOperand(MCOperand::createReg(Reg));
1357 }
1358
Sander de Smalenfd54a782018-06-04 07:07:35 +00001359 template <int Width>
1360 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1361 unsigned Base;
1362 switch (Width) {
1363 case 8: Base = AArch64::B0; break;
1364 case 16: Base = AArch64::H0; break;
1365 case 32: Base = AArch64::S0; break;
1366 case 64: Base = AArch64::D0; break;
1367 case 128: Base = AArch64::Q0; break;
1368 default:
1369 llvm_unreachable("Unsupported width");
1370 }
1371 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1372 }
1373
Tim Northover3b0846e2014-05-24 12:50:23 +00001374 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1375 assert(N == 1 && "Invalid number of operands!");
1376 assert(
1377 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001378 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001379 }
1380
1381 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1382 assert(N == 1 && "Invalid number of operands!");
1383 assert(
1384 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001385 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001386 }
1387
1388 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1389 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001390 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001391 }
1392
Sander de Smalen525e3222018-04-12 13:19:32 +00001393 enum VecListIndexType {
1394 VecListIdx_DReg = 0,
1395 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001396 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001397 };
1398
1399 template <VecListIndexType RegTy, unsigned NumRegs>
1400 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001401 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001402 static const unsigned FirstRegs[][5] = {
1403 /* DReg */ { AArch64::Q0,
1404 AArch64::D0, AArch64::D0_D1,
1405 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1406 /* QReg */ { AArch64::Q0,
1407 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001408 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1409 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001410 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001411 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001412 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001413
Sander de Smalen7a210db2018-04-16 10:46:18 +00001414 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1415 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001416
Sander de Smalen525e3222018-04-12 13:19:32 +00001417 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1418 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1419 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001420 }
1421
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001422 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001423 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001424 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001425 }
1426
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001427 template <unsigned ImmIs0, unsigned ImmIs1>
1428 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1429 assert(N == 1 && "Invalid number of operands!");
1430 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1431 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1432 }
1433
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 void addImmOperands(MCInst &Inst, unsigned N) const {
1435 assert(N == 1 && "Invalid number of operands!");
1436 // If this is a pageoff symrefexpr with an addend, adjust the addend
1437 // to be only the page-offset portion. Otherwise, just add the expr
1438 // as-is.
1439 addExpr(Inst, getImm());
1440 }
1441
Sander de Smalen62770792018-05-25 09:47:52 +00001442 template <int Shift>
1443 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001444 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001445 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1446 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1447 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1448 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001449 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001450 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001451 } else {
1452 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001453 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001454 }
1455 }
1456
Sander de Smalen62770792018-05-25 09:47:52 +00001457 template <int Shift>
1458 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +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
1464 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001465 }
1466
Tim Northover3b0846e2014-05-24 12:50:23 +00001467 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1468 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001469 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001470 }
1471
1472 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1473 assert(N == 1 && "Invalid number of operands!");
1474 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1475 if (!MCE)
1476 addExpr(Inst, getImm());
1477 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001478 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001479 }
1480
1481 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1482 addImmOperands(Inst, N);
1483 }
1484
1485 template<int Scale>
1486 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1487 assert(N == 1 && "Invalid number of operands!");
1488 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1489
1490 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001491 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001492 return;
1493 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001494 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001495 }
1496
Sander de Smalen5c625982018-04-13 12:56:14 +00001497 template <int Scale>
1498 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1499 assert(N == 1 && "Invalid number of operands!");
1500 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1501 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1502 }
1503
Sander de Smalena1c259c2018-01-29 13:05:38 +00001504 template <typename T>
1505 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001506 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001507 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001508 typename std::make_unsigned<T>::type Val = MCE->getValue();
1509 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001510 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001511 }
1512
Sander de Smalena1c259c2018-01-29 13:05:38 +00001513 template <typename T>
1514 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001515 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001516 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001517 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1518 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001519 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001520 }
1521
Tim Northover3b0846e2014-05-24 12:50:23 +00001522 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1523 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001524 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001525 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001526 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001527 }
1528
1529 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1530 // Branch operands don't encode the low bits, so shift them off
1531 // here. If it's a label, however, just put it on directly as there's
1532 // not enough information now to do anything.
1533 assert(N == 1 && "Invalid number of operands!");
1534 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1535 if (!MCE) {
1536 addExpr(Inst, getImm());
1537 return;
1538 }
1539 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001540 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001541 }
1542
1543 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1544 // Branch operands don't encode the low bits, so shift them off
1545 // here. If it's a label, however, just put it on directly as there's
1546 // not enough information now to do anything.
1547 assert(N == 1 && "Invalid number of operands!");
1548 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1549 if (!MCE) {
1550 addExpr(Inst, getImm());
1551 return;
1552 }
1553 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001554 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001555 }
1556
1557 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1558 // Branch operands don't encode the low bits, so shift them off
1559 // here. If it's a label, however, just put it on directly as there's
1560 // not enough information now to do anything.
1561 assert(N == 1 && "Invalid number of operands!");
1562 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1563 if (!MCE) {
1564 addExpr(Inst, getImm());
1565 return;
1566 }
1567 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001568 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001569 }
1570
1571 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1572 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001573 Inst.addOperand(MCOperand::createImm(
1574 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
Tim Northover3b0846e2014-05-24 12:50:23 +00001575 }
1576
1577 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1578 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001579 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001580 }
1581
1582 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1583 assert(N == 1 && "Invalid number of operands!");
1584
Jim Grosbache9119e42015-05-13 18:37:00 +00001585 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001586 }
1587
1588 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1589 assert(N == 1 && "Invalid number of operands!");
1590
Jim Grosbache9119e42015-05-13 18:37:00 +00001591 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001592 }
1593
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001594 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1595 assert(N == 1 && "Invalid number of operands!");
1596
1597 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1598 }
1599
1600 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001601 assert(N == 1 && "Invalid number of operands!");
1602
Jim Grosbache9119e42015-05-13 18:37:00 +00001603 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001604 }
1605
1606 void addSysCROperands(MCInst &Inst, unsigned N) const {
1607 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001608 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001609 }
1610
1611 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1612 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001613 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001614 }
1615
Oliver Stannarda34e4702015-12-01 10:48:51 +00001616 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1617 assert(N == 1 && "Invalid number of operands!");
1618 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1619 }
1620
Tim Northover3b0846e2014-05-24 12:50:23 +00001621 void addShifterOperands(MCInst &Inst, unsigned N) const {
1622 assert(N == 1 && "Invalid number of operands!");
1623 unsigned Imm =
1624 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001625 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001626 }
1627
1628 void addExtendOperands(MCInst &Inst, unsigned N) const {
1629 assert(N == 1 && "Invalid number of operands!");
1630 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1631 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1632 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001633 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001634 }
1635
1636 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1637 assert(N == 1 && "Invalid number of operands!");
1638 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1639 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1640 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001641 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001642 }
1643
1644 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1645 assert(N == 2 && "Invalid number of operands!");
1646 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1647 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001648 Inst.addOperand(MCOperand::createImm(IsSigned));
1649 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001650 }
1651
1652 // For 8-bit load/store instructions with a register offset, both the
1653 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1654 // they're disambiguated by whether the shift was explicit or implicit rather
1655 // than its size.
1656 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1657 assert(N == 2 && "Invalid number of operands!");
1658 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1659 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001660 Inst.addOperand(MCOperand::createImm(IsSigned));
1661 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001662 }
1663
1664 template<int Shift>
1665 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1666 assert(N == 1 && "Invalid number of operands!");
1667
1668 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1669 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001670 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001671 }
1672
1673 template<int Shift>
1674 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1675 assert(N == 1 && "Invalid number of operands!");
1676
1677 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1678 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001679 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001680 }
1681
Sam Parker5f934642017-08-31 09:27:04 +00001682 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1683 assert(N == 1 && "Invalid number of operands!");
1684 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1685 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1686 }
1687
1688 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1689 assert(N == 1 && "Invalid number of operands!");
1690 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1691 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1692 }
1693
Tim Northover3b0846e2014-05-24 12:50:23 +00001694 void print(raw_ostream &OS) const override;
1695
David Blaikie960ea3f2014-06-08 16:18:35 +00001696 static std::unique_ptr<AArch64Operand>
1697 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1698 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001699 Op->Tok.Data = Str.data();
1700 Op->Tok.Length = Str.size();
1701 Op->Tok.IsSuffix = IsSuffix;
1702 Op->StartLoc = S;
1703 Op->EndLoc = S;
1704 return Op;
1705 }
1706
David Blaikie960ea3f2014-06-08 16:18:35 +00001707 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001708 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
Sander de Smalen0325e302018-07-02 07:34:52 +00001709 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
Sander de Smalen149916d2018-04-20 07:24:20 +00001710 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1711 unsigned ShiftAmount = 0,
1712 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001713 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001714 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001715 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001716 Op->Reg.ElementWidth = 0;
Sander de Smalen0325e302018-07-02 07:34:52 +00001717 Op->Reg.EqualityTy = EqTy;
Sander de Smalen149916d2018-04-20 07:24:20 +00001718 Op->Reg.ShiftExtend.Type = ExtTy;
1719 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1720 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001721 Op->StartLoc = S;
1722 Op->EndLoc = E;
1723 return Op;
1724 }
1725
David Blaikie960ea3f2014-06-08 16:18:35 +00001726 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001727 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001728 SMLoc S, SMLoc E, MCContext &Ctx,
1729 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1730 unsigned ShiftAmount = 0,
1731 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001732 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1733 Kind == RegKind::SVEPredicateVector) &&
1734 "Invalid vector kind");
Sander de Smalen0325e302018-07-02 07:34:52 +00001735 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
Sander de Smalen149916d2018-04-20 07:24:20 +00001736 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001737 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001738 return Op;
1739 }
1740
1741 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001742 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001743 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1744 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001745 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001746 Op->VectorList.RegNum = RegNum;
1747 Op->VectorList.Count = Count;
1748 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001749 Op->VectorList.ElementWidth = ElementWidth;
1750 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001751 Op->StartLoc = S;
1752 Op->EndLoc = E;
1753 return Op;
1754 }
1755
David Blaikie960ea3f2014-06-08 16:18:35 +00001756 static std::unique_ptr<AArch64Operand>
1757 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1758 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001759 Op->VectorIndex.Val = Idx;
1760 Op->StartLoc = S;
1761 Op->EndLoc = E;
1762 return Op;
1763 }
1764
David Blaikie960ea3f2014-06-08 16:18:35 +00001765 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1766 SMLoc E, MCContext &Ctx) {
1767 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001768 Op->Imm.Val = Val;
1769 Op->StartLoc = S;
1770 Op->EndLoc = E;
1771 return Op;
1772 }
1773
David Blaikie960ea3f2014-06-08 16:18:35 +00001774 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1775 unsigned ShiftAmount,
1776 SMLoc S, SMLoc E,
1777 MCContext &Ctx) {
1778 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001779 Op->ShiftedImm .Val = Val;
1780 Op->ShiftedImm.ShiftAmount = ShiftAmount;
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>
1787 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1788 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001789 Op->CondCode.Code = Code;
1790 Op->StartLoc = S;
1791 Op->EndLoc = E;
1792 return Op;
1793 }
1794
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001795 static std::unique_ptr<AArch64Operand>
1796 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001797 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001798 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
1799 Op->FPImm.IsExact = IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +00001800 Op->StartLoc = S;
1801 Op->EndLoc = S;
1802 return Op;
1803 }
1804
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001805 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1806 StringRef Str,
1807 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001808 MCContext &Ctx) {
1809 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001810 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001811 Op->Barrier.Data = Str.data();
1812 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001813 Op->StartLoc = S;
1814 Op->EndLoc = S;
1815 return Op;
1816 }
1817
Tim Northover7cd58932015-01-22 17:23:04 +00001818 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1819 uint32_t MRSReg,
1820 uint32_t MSRReg,
1821 uint32_t PStateField,
1822 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001823 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001824 Op->SysReg.Data = Str.data();
1825 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001826 Op->SysReg.MRSReg = MRSReg;
1827 Op->SysReg.MSRReg = MSRReg;
1828 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001829 Op->StartLoc = S;
1830 Op->EndLoc = S;
1831 return Op;
1832 }
1833
David Blaikie960ea3f2014-06-08 16:18:35 +00001834 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1835 SMLoc E, MCContext &Ctx) {
1836 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001837 Op->SysCRImm.Val = Val;
1838 Op->StartLoc = S;
1839 Op->EndLoc = E;
1840 return Op;
1841 }
1842
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001843 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1844 StringRef Str,
1845 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001846 MCContext &Ctx) {
1847 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001848 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001849 Op->Barrier.Data = Str.data();
1850 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001851 Op->StartLoc = S;
1852 Op->EndLoc = S;
1853 return Op;
1854 }
1855
Oliver Stannarda34e4702015-12-01 10:48:51 +00001856 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1857 StringRef Str,
1858 SMLoc S,
1859 MCContext &Ctx) {
1860 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1861 Op->PSBHint.Val = Val;
1862 Op->PSBHint.Data = Str.data();
1863 Op->PSBHint.Length = Str.size();
1864 Op->StartLoc = S;
1865 Op->EndLoc = S;
1866 return Op;
1867 }
1868
David Blaikie960ea3f2014-06-08 16:18:35 +00001869 static std::unique_ptr<AArch64Operand>
1870 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1871 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1872 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001873 Op->ShiftExtend.Type = ShOp;
1874 Op->ShiftExtend.Amount = Val;
1875 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1876 Op->StartLoc = S;
1877 Op->EndLoc = E;
1878 return Op;
1879 }
1880};
1881
1882} // end anonymous namespace.
1883
1884void AArch64Operand::print(raw_ostream &OS) const {
1885 switch (Kind) {
1886 case k_FPImm:
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001887 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
1888 if (!getFPImmIsExact())
1889 OS << " (inexact)";
1890 OS << ">";
Tim Northover3b0846e2014-05-24 12:50:23 +00001891 break;
1892 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001893 StringRef Name = getBarrierName();
1894 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001895 OS << "<barrier " << Name << ">";
1896 else
1897 OS << "<barrier invalid #" << getBarrier() << ">";
1898 break;
1899 }
1900 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001901 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001902 break;
1903 case k_ShiftedImm: {
1904 unsigned Shift = getShiftedImmShift();
1905 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001906 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001907 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1908 break;
1909 }
1910 case k_CondCode:
1911 OS << "<condcode " << getCondCode() << ">";
1912 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001913 case k_VectorList: {
1914 OS << "<vectorlist ";
1915 unsigned Reg = getVectorListStart();
1916 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1917 OS << Reg + i << " ";
1918 OS << ">";
1919 break;
1920 }
1921 case k_VectorIndex:
1922 OS << "<vectorindex " << getVectorIndex() << ">";
1923 break;
1924 case k_SysReg:
1925 OS << "<sysreg: " << getSysReg() << '>';
1926 break;
1927 case k_Token:
1928 OS << "'" << getToken() << "'";
1929 break;
1930 case k_SysCR:
1931 OS << "c" << getSysCR();
1932 break;
1933 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001934 StringRef Name = getPrefetchName();
1935 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001936 OS << "<prfop " << Name << ">";
1937 else
1938 OS << "<prfop invalid #" << getPrefetch() << ">";
1939 break;
1940 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001941 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001942 OS << getPSBHintName();
1943 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00001944 case k_Register:
1945 OS << "<register " << getReg() << ">";
1946 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
1947 break;
1948 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001949 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001950 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1951 << getShiftExtendAmount();
1952 if (!hasShiftExtendAmount())
1953 OS << "<imp>";
1954 OS << '>';
1955 break;
1956 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001957}
1958
1959/// @name Auto-generated Match Functions
1960/// {
1961
1962static unsigned MatchRegisterName(StringRef Name);
1963
1964/// }
1965
Florian Hahnc4422242017-11-07 13:07:50 +00001966static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001967 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001968 .Case("v0", AArch64::Q0)
1969 .Case("v1", AArch64::Q1)
1970 .Case("v2", AArch64::Q2)
1971 .Case("v3", AArch64::Q3)
1972 .Case("v4", AArch64::Q4)
1973 .Case("v5", AArch64::Q5)
1974 .Case("v6", AArch64::Q6)
1975 .Case("v7", AArch64::Q7)
1976 .Case("v8", AArch64::Q8)
1977 .Case("v9", AArch64::Q9)
1978 .Case("v10", AArch64::Q10)
1979 .Case("v11", AArch64::Q11)
1980 .Case("v12", AArch64::Q12)
1981 .Case("v13", AArch64::Q13)
1982 .Case("v14", AArch64::Q14)
1983 .Case("v15", AArch64::Q15)
1984 .Case("v16", AArch64::Q16)
1985 .Case("v17", AArch64::Q17)
1986 .Case("v18", AArch64::Q18)
1987 .Case("v19", AArch64::Q19)
1988 .Case("v20", AArch64::Q20)
1989 .Case("v21", AArch64::Q21)
1990 .Case("v22", AArch64::Q22)
1991 .Case("v23", AArch64::Q23)
1992 .Case("v24", AArch64::Q24)
1993 .Case("v25", AArch64::Q25)
1994 .Case("v26", AArch64::Q26)
1995 .Case("v27", AArch64::Q27)
1996 .Case("v28", AArch64::Q28)
1997 .Case("v29", AArch64::Q29)
1998 .Case("v30", AArch64::Q30)
1999 .Case("v31", AArch64::Q31)
2000 .Default(0);
2001}
2002
Sander de Smalen73937b72018-04-11 07:36:10 +00002003/// Returns an optional pair of (#elements, element-width) if Suffix
2004/// is a valid vector kind. Where the number of elements in a vector
2005/// or the vector width is implicit or explicitly unknown (but still a
2006/// valid suffix kind), 0 is used.
2007static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2008 RegKind VectorKind) {
2009 std::pair<int, int> Res = {-1, -1};
2010
2011 switch (VectorKind) {
2012 case RegKind::NeonVector:
2013 Res =
2014 StringSwitch<std::pair<int, int>>(Suffix.lower())
2015 .Case("", {0, 0})
2016 .Case(".1d", {1, 64})
2017 .Case(".1q", {1, 128})
2018 // '.2h' needed for fp16 scalar pairwise reductions
2019 .Case(".2h", {2, 16})
2020 .Case(".2s", {2, 32})
2021 .Case(".2d", {2, 64})
2022 // '.4b' is another special case for the ARMv8.2a dot product
2023 // operand
2024 .Case(".4b", {4, 8})
2025 .Case(".4h", {4, 16})
2026 .Case(".4s", {4, 32})
2027 .Case(".8b", {8, 8})
2028 .Case(".8h", {8, 16})
2029 .Case(".16b", {16, 8})
2030 // Accept the width neutral ones, too, for verbose syntax. If those
2031 // aren't used in the right places, the token operand won't match so
2032 // all will work out.
2033 .Case(".b", {0, 8})
2034 .Case(".h", {0, 16})
2035 .Case(".s", {0, 32})
2036 .Case(".d", {0, 64})
2037 .Default({-1, -1});
2038 break;
2039 case RegKind::SVEPredicateVector:
2040 case RegKind::SVEDataVector:
2041 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2042 .Case("", {0, 0})
2043 .Case(".b", {0, 8})
2044 .Case(".h", {0, 16})
2045 .Case(".s", {0, 32})
2046 .Case(".d", {0, 64})
2047 .Case(".q", {0, 128})
2048 .Default({-1, -1});
2049 break;
2050 default:
2051 llvm_unreachable("Unsupported RegKind");
2052 }
2053
2054 if (Res == std::make_pair(-1, -1))
2055 return Optional<std::pair<int, int>>();
2056
2057 return Optional<std::pair<int, int>>(Res);
2058}
2059
2060static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2061 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002062}
2063
Florian Hahn91f11e52017-11-07 16:45:48 +00002064static unsigned matchSVEDataVectorRegName(StringRef Name) {
2065 return StringSwitch<unsigned>(Name.lower())
2066 .Case("z0", AArch64::Z0)
2067 .Case("z1", AArch64::Z1)
2068 .Case("z2", AArch64::Z2)
2069 .Case("z3", AArch64::Z3)
2070 .Case("z4", AArch64::Z4)
2071 .Case("z5", AArch64::Z5)
2072 .Case("z6", AArch64::Z6)
2073 .Case("z7", AArch64::Z7)
2074 .Case("z8", AArch64::Z8)
2075 .Case("z9", AArch64::Z9)
2076 .Case("z10", AArch64::Z10)
2077 .Case("z11", AArch64::Z11)
2078 .Case("z12", AArch64::Z12)
2079 .Case("z13", AArch64::Z13)
2080 .Case("z14", AArch64::Z14)
2081 .Case("z15", AArch64::Z15)
2082 .Case("z16", AArch64::Z16)
2083 .Case("z17", AArch64::Z17)
2084 .Case("z18", AArch64::Z18)
2085 .Case("z19", AArch64::Z19)
2086 .Case("z20", AArch64::Z20)
2087 .Case("z21", AArch64::Z21)
2088 .Case("z22", AArch64::Z22)
2089 .Case("z23", AArch64::Z23)
2090 .Case("z24", AArch64::Z24)
2091 .Case("z25", AArch64::Z25)
2092 .Case("z26", AArch64::Z26)
2093 .Case("z27", AArch64::Z27)
2094 .Case("z28", AArch64::Z28)
2095 .Case("z29", AArch64::Z29)
2096 .Case("z30", AArch64::Z30)
2097 .Case("z31", AArch64::Z31)
2098 .Default(0);
2099}
2100
Sander de Smalencd6be962017-12-20 11:02:42 +00002101static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2102 return StringSwitch<unsigned>(Name.lower())
2103 .Case("p0", AArch64::P0)
2104 .Case("p1", AArch64::P1)
2105 .Case("p2", AArch64::P2)
2106 .Case("p3", AArch64::P3)
2107 .Case("p4", AArch64::P4)
2108 .Case("p5", AArch64::P5)
2109 .Case("p6", AArch64::P6)
2110 .Case("p7", AArch64::P7)
2111 .Case("p8", AArch64::P8)
2112 .Case("p9", AArch64::P9)
2113 .Case("p10", AArch64::P10)
2114 .Case("p11", AArch64::P11)
2115 .Case("p12", AArch64::P12)
2116 .Case("p13", AArch64::P13)
2117 .Case("p14", AArch64::P14)
2118 .Case("p15", AArch64::P15)
2119 .Default(0);
2120}
2121
Tim Northover3b0846e2014-05-24 12:50:23 +00002122bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2123 SMLoc &EndLoc) {
2124 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002125 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002126 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002127 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002128}
2129
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002130// Matches a register name or register alias previously defined by '.req'
2131unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002132 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002133 unsigned RegNum = 0;
2134 if ((RegNum = matchSVEDataVectorRegName(Name)))
2135 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2136
Sander de Smalencd6be962017-12-20 11:02:42 +00002137 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2138 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2139
Sander de Smalenc067c302017-12-20 09:45:45 +00002140 if ((RegNum = MatchNeonVectorRegName(Name)))
2141 return Kind == RegKind::NeonVector ? RegNum : 0;
2142
2143 // The parsed register must be of RegKind Scalar
2144 if ((RegNum = MatchRegisterName(Name)))
2145 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002146
Florian Hahnc4422242017-11-07 13:07:50 +00002147 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002148 // Handle a few common aliases of registers.
2149 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2150 .Case("fp", AArch64::FP)
2151 .Case("lr", AArch64::LR)
2152 .Case("x31", AArch64::XZR)
2153 .Case("w31", AArch64::WZR)
2154 .Default(0))
2155 return Kind == RegKind::Scalar ? RegNum : 0;
2156
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002157 // Check for aliases registered via .req. Canonicalize to lower case.
2158 // That's more consistent since register names are case insensitive, and
2159 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2160 auto Entry = RegisterReqs.find(Name.lower());
2161 if (Entry == RegisterReqs.end())
2162 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002163
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002164 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002165 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002166 RegNum = Entry->getValue().second;
2167 }
2168 return RegNum;
2169}
2170
Sander de Smalen50d87022018-04-19 07:35:08 +00002171/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002172/// Identifier when called, and if it is a register name the token is eaten and
2173/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002174OperandMatchResultTy
2175AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002176 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002177 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002178 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002179 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002180
2181 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002182 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2183 if (Reg == 0)
2184 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002185
Sander de Smalen50d87022018-04-19 07:35:08 +00002186 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002187 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002188 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002189}
2190
Tim Northover3b0846e2014-05-24 12:50:23 +00002191/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002192OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002193AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002194 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002195 SMLoc S = getLoc();
2196
2197 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2198 Error(S, "Expected cN operand where 0 <= N <= 15");
2199 return MatchOperand_ParseFail;
2200 }
2201
2202 StringRef Tok = Parser.getTok().getIdentifier();
2203 if (Tok[0] != 'c' && Tok[0] != 'C') {
2204 Error(S, "Expected cN operand where 0 <= N <= 15");
2205 return MatchOperand_ParseFail;
2206 }
2207
2208 uint32_t CRNum;
2209 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2210 if (BadNum || CRNum > 15) {
2211 Error(S, "Expected cN operand where 0 <= N <= 15");
2212 return MatchOperand_ParseFail;
2213 }
2214
2215 Parser.Lex(); // Eat identifier token.
2216 Operands.push_back(
2217 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2218 return MatchOperand_Success;
2219}
2220
2221/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002222template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002223OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002224AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002225 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002226 SMLoc S = getLoc();
2227 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002228
2229 auto LookupByName = [](StringRef N) {
2230 if (IsSVEPrefetch) {
2231 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2232 return Optional<unsigned>(Res->Encoding);
2233 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2234 return Optional<unsigned>(Res->Encoding);
2235 return Optional<unsigned>();
2236 };
2237
2238 auto LookupByEncoding = [](unsigned E) {
2239 if (IsSVEPrefetch) {
2240 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2241 return Optional<StringRef>(Res->Name);
2242 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2243 return Optional<StringRef>(Res->Name);
2244 return Optional<StringRef>();
2245 };
2246 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2247
Tim Northover3b0846e2014-05-24 12:50:23 +00002248 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002249 // Eat optional hash.
2250 if (parseOptionalToken(AsmToken::Hash) ||
2251 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002252 const MCExpr *ImmVal;
2253 if (getParser().parseExpression(ImmVal))
2254 return MatchOperand_ParseFail;
2255
2256 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2257 if (!MCE) {
2258 TokError("immediate value expected for prefetch operand");
2259 return MatchOperand_ParseFail;
2260 }
2261 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002262 if (prfop > MaxVal) {
2263 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2264 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002265 return MatchOperand_ParseFail;
2266 }
2267
Sander de Smalen93380372018-05-14 11:54:41 +00002268 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002269 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002270 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002271 return MatchOperand_Success;
2272 }
2273
2274 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002275 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002276 return MatchOperand_ParseFail;
2277 }
2278
Sander de Smalen93380372018-05-14 11:54:41 +00002279 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002280 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002281 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002282 return MatchOperand_ParseFail;
2283 }
2284
2285 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002286 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002287 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002288 return MatchOperand_Success;
2289}
2290
Oliver Stannarda34e4702015-12-01 10:48:51 +00002291/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002292OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002293AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2294 MCAsmParser &Parser = getParser();
2295 SMLoc S = getLoc();
2296 const AsmToken &Tok = Parser.getTok();
2297 if (Tok.isNot(AsmToken::Identifier)) {
2298 TokError("invalid operand for instruction");
2299 return MatchOperand_ParseFail;
2300 }
2301
Tim Northovere6ae6762016-07-05 21:23:04 +00002302 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2303 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002304 TokError("invalid operand for instruction");
2305 return MatchOperand_ParseFail;
2306 }
2307
2308 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002309 Operands.push_back(AArch64Operand::CreatePSBHint(
2310 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002311 return MatchOperand_Success;
2312}
2313
Tim Northover3b0846e2014-05-24 12:50:23 +00002314/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2315/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002316OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002317AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002318 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002319 SMLoc S = getLoc();
2320 const MCExpr *Expr;
2321
2322 if (Parser.getTok().is(AsmToken::Hash)) {
2323 Parser.Lex(); // Eat hash token.
2324 }
2325
2326 if (parseSymbolicImmVal(Expr))
2327 return MatchOperand_ParseFail;
2328
2329 AArch64MCExpr::VariantKind ELFRefKind;
2330 MCSymbolRefExpr::VariantKind DarwinRefKind;
2331 int64_t Addend;
2332 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2333 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2334 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2335 // No modifier was specified at all; this is the syntax for an ELF basic
2336 // ADRP relocation (unfortunately).
2337 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002338 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002339 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2340 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2341 Addend != 0) {
2342 Error(S, "gotpage label reference not allowed an addend");
2343 return MatchOperand_ParseFail;
2344 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2345 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2346 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2347 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2348 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2349 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2350 // The operand must be an @page or @gotpage qualified symbolref.
2351 Error(S, "page or gotpage label reference expected");
2352 return MatchOperand_ParseFail;
2353 }
2354 }
2355
2356 // We have either a label reference possibly with addend or an immediate. The
2357 // addend is a raw value here. The linker will adjust it to only reference the
2358 // page.
2359 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2360 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2361
2362 return MatchOperand_Success;
2363}
2364
2365/// tryParseAdrLabel - Parse and validate a source label for the ADR
2366/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002367OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002368AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2369 SMLoc S = getLoc();
2370 const MCExpr *Expr;
2371
Nirav Davee833c6c2016-11-08 18:31:04 +00002372 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002373 if (getParser().parseExpression(Expr))
2374 return MatchOperand_ParseFail;
2375
2376 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2377 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2378
2379 return MatchOperand_Success;
2380}
2381
2382/// tryParseFPImm - A floating point immediate expression operand.
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002383template<bool AddFPZeroAsLiteral>
Alex Bradbury58eba092016-11-01 16:32:05 +00002384OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002385AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002386 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002387 SMLoc S = getLoc();
2388
Nirav Davee833c6c2016-11-08 18:31:04 +00002389 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002390
2391 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002392 bool isNegative = parseOptionalToken(AsmToken::Minus);
2393
Tim Northover3b0846e2014-05-24 12:50:23 +00002394 const AsmToken &Tok = Parser.getTok();
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002395 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2396 if (!Hash)
2397 return MatchOperand_NoMatch;
2398 TokError("invalid floating point immediate");
2399 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002400 }
2401
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002402 // Parse hexadecimal representation.
2403 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2404 if (Tok.getIntVal() > 255 || isNegative) {
2405 TokError("encoded floating point value out of range");
2406 return MatchOperand_ParseFail;
2407 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002408
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002409 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2410 Operands.push_back(
2411 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2412 } else {
2413 // Parse FP representation.
2414 APFloat RealVal(APFloat::IEEEdouble());
2415 auto Status =
2416 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2417 if (isNegative)
2418 RealVal.changeSign();
2419
2420 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2421 Operands.push_back(
2422 AArch64Operand::CreateToken("#0", false, S, getContext()));
2423 Operands.push_back(
2424 AArch64Operand::CreateToken(".0", false, S, getContext()));
2425 } else
2426 Operands.push_back(AArch64Operand::CreateFPImm(
2427 RealVal, Status == APFloat::opOK, S, getContext()));
2428 }
2429
2430 Parser.Lex(); // Eat the token.
2431
2432 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002433}
2434
Sander de Smalen62770792018-05-25 09:47:52 +00002435/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2436/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002437OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002438AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002439 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002440 SMLoc S = getLoc();
2441
2442 if (Parser.getTok().is(AsmToken::Hash))
2443 Parser.Lex(); // Eat '#'
2444 else if (Parser.getTok().isNot(AsmToken::Integer))
2445 // Operand should start from # or should be integer, emit error otherwise.
2446 return MatchOperand_NoMatch;
2447
2448 const MCExpr *Imm;
2449 if (parseSymbolicImmVal(Imm))
2450 return MatchOperand_ParseFail;
2451 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002452 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002453 Operands.push_back(
2454 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002455 return MatchOperand_Success;
2456 }
2457
2458 // Eat ','
2459 Parser.Lex();
2460
2461 // The optional operand must be "lsl #N" where N is non-negative.
2462 if (!Parser.getTok().is(AsmToken::Identifier) ||
2463 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2464 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2465 return MatchOperand_ParseFail;
2466 }
2467
2468 // Eat 'lsl'
2469 Parser.Lex();
2470
Nirav Davee833c6c2016-11-08 18:31:04 +00002471 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002472
2473 if (Parser.getTok().isNot(AsmToken::Integer)) {
2474 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2475 return MatchOperand_ParseFail;
2476 }
2477
2478 int64_t ShiftAmount = Parser.getTok().getIntVal();
2479
2480 if (ShiftAmount < 0) {
2481 Error(Parser.getTok().getLoc(), "positive shift amount required");
2482 return MatchOperand_ParseFail;
2483 }
2484 Parser.Lex(); // Eat the number
2485
Sander de Smalen62770792018-05-25 09:47:52 +00002486 // Just in case the optional lsl #0 is used for immediates other than zero.
2487 if (ShiftAmount == 0 && Imm != 0) {
2488 SMLoc E = Parser.getTok().getLoc();
2489 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2490 return MatchOperand_Success;
2491 }
2492
Tim Northover3b0846e2014-05-24 12:50:23 +00002493 SMLoc E = Parser.getTok().getLoc();
2494 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2495 S, E, getContext()));
2496 return MatchOperand_Success;
2497}
2498
2499/// parseCondCodeString - Parse a Condition Code string.
2500AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2501 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2502 .Case("eq", AArch64CC::EQ)
2503 .Case("ne", AArch64CC::NE)
2504 .Case("cs", AArch64CC::HS)
2505 .Case("hs", AArch64CC::HS)
2506 .Case("cc", AArch64CC::LO)
2507 .Case("lo", AArch64CC::LO)
2508 .Case("mi", AArch64CC::MI)
2509 .Case("pl", AArch64CC::PL)
2510 .Case("vs", AArch64CC::VS)
2511 .Case("vc", AArch64CC::VC)
2512 .Case("hi", AArch64CC::HI)
2513 .Case("ls", AArch64CC::LS)
2514 .Case("ge", AArch64CC::GE)
2515 .Case("lt", AArch64CC::LT)
2516 .Case("gt", AArch64CC::GT)
2517 .Case("le", AArch64CC::LE)
2518 .Case("al", AArch64CC::AL)
2519 .Case("nv", AArch64CC::NV)
2520 .Default(AArch64CC::Invalid);
2521 return CC;
2522}
2523
2524/// parseCondCode - Parse a Condition Code operand.
2525bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2526 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002527 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002528 SMLoc S = getLoc();
2529 const AsmToken &Tok = Parser.getTok();
2530 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2531
2532 StringRef Cond = Tok.getString();
2533 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2534 if (CC == AArch64CC::Invalid)
2535 return TokError("invalid condition code");
2536 Parser.Lex(); // Eat identifier token.
2537
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002538 if (invertCondCode) {
2539 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2540 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002541 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002542 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002543
2544 Operands.push_back(
2545 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2546 return false;
2547}
2548
2549/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2550/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002551OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002552AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002553 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002554 const AsmToken &Tok = Parser.getTok();
2555 std::string LowerID = Tok.getString().lower();
2556 AArch64_AM::ShiftExtendType ShOp =
2557 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2558 .Case("lsl", AArch64_AM::LSL)
2559 .Case("lsr", AArch64_AM::LSR)
2560 .Case("asr", AArch64_AM::ASR)
2561 .Case("ror", AArch64_AM::ROR)
2562 .Case("msl", AArch64_AM::MSL)
2563 .Case("uxtb", AArch64_AM::UXTB)
2564 .Case("uxth", AArch64_AM::UXTH)
2565 .Case("uxtw", AArch64_AM::UXTW)
2566 .Case("uxtx", AArch64_AM::UXTX)
2567 .Case("sxtb", AArch64_AM::SXTB)
2568 .Case("sxth", AArch64_AM::SXTH)
2569 .Case("sxtw", AArch64_AM::SXTW)
2570 .Case("sxtx", AArch64_AM::SXTX)
2571 .Default(AArch64_AM::InvalidShiftExtend);
2572
2573 if (ShOp == AArch64_AM::InvalidShiftExtend)
2574 return MatchOperand_NoMatch;
2575
2576 SMLoc S = Tok.getLoc();
2577 Parser.Lex();
2578
Nirav Davee833c6c2016-11-08 18:31:04 +00002579 bool Hash = parseOptionalToken(AsmToken::Hash);
2580
Tim Northover3b0846e2014-05-24 12:50:23 +00002581 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2582 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2583 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2584 ShOp == AArch64_AM::MSL) {
2585 // We expect a number here.
2586 TokError("expected #imm after shift specifier");
2587 return MatchOperand_ParseFail;
2588 }
2589
Chad Rosier2ff37b82016-12-27 16:58:09 +00002590 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002591 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2592 Operands.push_back(
2593 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2594 return MatchOperand_Success;
2595 }
2596
Chad Rosier2ff37b82016-12-27 16:58:09 +00002597 // Make sure we do actually have a number, identifier or a parenthesized
2598 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002599 SMLoc E = Parser.getTok().getLoc();
2600 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002601 !Parser.getTok().is(AsmToken::LParen) &&
2602 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002603 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002604 return MatchOperand_ParseFail;
2605 }
2606
2607 const MCExpr *ImmVal;
2608 if (getParser().parseExpression(ImmVal))
2609 return MatchOperand_ParseFail;
2610
2611 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2612 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002613 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002614 return MatchOperand_ParseFail;
2615 }
2616
Jim Grosbach57fd2622014-09-23 22:16:02 +00002617 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002618 Operands.push_back(AArch64Operand::CreateShiftExtend(
2619 ShOp, MCE->getValue(), true, S, E, getContext()));
2620 return MatchOperand_Success;
2621}
2622
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002623static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2624 if (FBS[AArch64::HasV8_1aOps])
2625 Str += "ARMv8.1a";
2626 else if (FBS[AArch64::HasV8_2aOps])
2627 Str += "ARMv8.2a";
2628 else
2629 Str += "(unknown)";
2630}
2631
2632void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2633 SMLoc S) {
2634 const uint16_t Op2 = Encoding & 7;
2635 const uint16_t Cm = (Encoding & 0x78) >> 3;
2636 const uint16_t Cn = (Encoding & 0x780) >> 7;
2637 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2638
2639 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2640
2641 Operands.push_back(
2642 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2643 Operands.push_back(
2644 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2645 Operands.push_back(
2646 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2647 Expr = MCConstantExpr::create(Op2, getContext());
2648 Operands.push_back(
2649 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2650}
2651
Tim Northover3b0846e2014-05-24 12:50:23 +00002652/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2653/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2654bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2655 OperandVector &Operands) {
2656 if (Name.find('.') != StringRef::npos)
2657 return TokError("invalid operand");
2658
2659 Mnemonic = Name;
2660 Operands.push_back(
2661 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2662
Rafael Espindola961d4692014-11-11 05:18:41 +00002663 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002664 const AsmToken &Tok = Parser.getTok();
2665 StringRef Op = Tok.getString();
2666 SMLoc S = Tok.getLoc();
2667
Tim Northover3b0846e2014-05-24 12:50:23 +00002668 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002669 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2670 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002671 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002672 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2673 std::string Str("IC " + std::string(IC->Name) + " requires ");
2674 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2675 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002676 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002677 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002678 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002679 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2680 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002681 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002682 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2683 std::string Str("DC " + std::string(DC->Name) + " requires ");
2684 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2685 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002686 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002687 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002688 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002689 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2690 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002691 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002692 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2693 std::string Str("AT " + std::string(AT->Name) + " requires ");
2694 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2695 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002696 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002697 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002698 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002699 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2700 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002701 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002702 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2703 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2704 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2705 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002706 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002707 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002708 }
2709
Tim Northover3b0846e2014-05-24 12:50:23 +00002710 Parser.Lex(); // Eat operand.
2711
2712 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2713 bool HasRegister = false;
2714
2715 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002716 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002717 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2718 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002719 HasRegister = true;
2720 }
2721
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002722 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002723 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002724 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002725 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002726
Nirav Davee833c6c2016-11-08 18:31:04 +00002727 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2728 return true;
2729
Tim Northover3b0846e2014-05-24 12:50:23 +00002730 return false;
2731}
2732
Alex Bradbury58eba092016-11-01 16:32:05 +00002733OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002734AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002735 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002736 const AsmToken &Tok = Parser.getTok();
2737
2738 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002739 if (parseOptionalToken(AsmToken::Hash) ||
2740 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002741 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002742 const MCExpr *ImmVal;
2743 SMLoc ExprLoc = getLoc();
2744 if (getParser().parseExpression(ImmVal))
2745 return MatchOperand_ParseFail;
2746 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2747 if (!MCE) {
2748 Error(ExprLoc, "immediate value expected for barrier operand");
2749 return MatchOperand_ParseFail;
2750 }
2751 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2752 Error(ExprLoc, "barrier operand out of range");
2753 return MatchOperand_ParseFail;
2754 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002755 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2756 Operands.push_back(AArch64Operand::CreateBarrier(
2757 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002758 return MatchOperand_Success;
2759 }
2760
2761 if (Tok.isNot(AsmToken::Identifier)) {
2762 TokError("invalid operand for instruction");
2763 return MatchOperand_ParseFail;
2764 }
2765
Tim Northover3b0846e2014-05-24 12:50:23 +00002766 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002767 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2768 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002769 TokError("'sy' or #imm operand expected");
2770 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002771 } else if (!DB) {
2772 TokError("invalid barrier option name");
2773 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002774 }
2775
Tim Northovere6ae6762016-07-05 21:23:04 +00002776 Operands.push_back(AArch64Operand::CreateBarrier(
2777 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002778 Parser.Lex(); // Consume the option
2779
2780 return MatchOperand_Success;
2781}
2782
Alex Bradbury58eba092016-11-01 16:32:05 +00002783OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002784AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002785 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002786 const AsmToken &Tok = Parser.getTok();
2787
2788 if (Tok.isNot(AsmToken::Identifier))
2789 return MatchOperand_NoMatch;
2790
Tim Northovere6ae6762016-07-05 21:23:04 +00002791 int MRSReg, MSRReg;
2792 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2793 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2794 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2795 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2796 } else
2797 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002798
Tim Northovere6ae6762016-07-05 21:23:04 +00002799 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2800 unsigned PStateImm = -1;
2801 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2802 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002803
Tim Northovere6ae6762016-07-05 21:23:04 +00002804 Operands.push_back(
2805 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2806 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002807 Parser.Lex(); // Eat identifier
2808
2809 return MatchOperand_Success;
2810}
2811
Florian Hahnc4422242017-11-07 13:07:50 +00002812/// tryParseNeonVectorRegister - Parse a vector register operand.
2813bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002814 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002815 if (Parser.getTok().isNot(AsmToken::Identifier))
2816 return true;
2817
2818 SMLoc S = getLoc();
2819 // Check for a vector register specifier first.
2820 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002821 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002822 OperandMatchResultTy Res =
2823 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2824 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002825 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002826
2827 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2828 if (!KindRes)
2829 return true;
2830
2831 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002832 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002833 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2834 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002835
Tim Northover3b0846e2014-05-24 12:50:23 +00002836 // If there was an explicit qualifier, that goes on as a literal text
2837 // operand.
2838 if (!Kind.empty())
2839 Operands.push_back(
2840 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2841
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002842 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2843}
2844
2845OperandMatchResultTy
2846AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002847 SMLoc SIdx = getLoc();
2848 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002849 const MCExpr *ImmVal;
2850 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002851 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002852 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2853 if (!MCE) {
2854 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002855 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002856 }
2857
2858 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002859
Nirav Davee833c6c2016-11-08 18:31:04 +00002860 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002861 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002862
2863 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2864 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002865 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002866 }
2867
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002868 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002869}
2870
Sander de Smalen73937b72018-04-11 07:36:10 +00002871// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002872// optional kind specifier. If it is a register specifier, eat the token
2873// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002874OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002875AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002876 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002877 MCAsmParser &Parser = getParser();
2878 const AsmToken &Tok = Parser.getTok();
2879
Florian Hahn91f11e52017-11-07 16:45:48 +00002880 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002881 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002882
2883 StringRef Name = Tok.getString();
2884 // If there is a kind specifier, it's separated from the register name by
2885 // a '.'.
2886 size_t Start = 0, Next = Name.find('.');
2887 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002888 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002889
2890 if (RegNum) {
2891 if (Next != StringRef::npos) {
2892 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002893 if (!isValidVectorKind(Kind, MatchKind)) {
2894 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002895 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002896 }
2897 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002898 Parser.Lex(); // Eat the register token.
2899
2900 Reg = RegNum;
2901 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002902 }
2903
Sander de Smalen8e607342017-11-15 15:44:43 +00002904 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002905}
2906
Sander de Smalencd6be962017-12-20 11:02:42 +00002907/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2908OperandMatchResultTy
2909AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2910 // Check for a SVE predicate register specifier first.
2911 const SMLoc S = getLoc();
2912 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002913 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002914 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002915 if (Res != MatchOperand_Success)
2916 return Res;
2917
Sander de Smalen73937b72018-04-11 07:36:10 +00002918 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2919 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002920 return MatchOperand_NoMatch;
2921
Sander de Smalen73937b72018-04-11 07:36:10 +00002922 unsigned ElementWidth = KindRes->second;
2923 Operands.push_back(AArch64Operand::CreateVectorReg(
2924 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2925 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002926
Sander de Smalen7868e742018-01-09 11:17:06 +00002927 // Not all predicates are followed by a '/m' or '/z'.
2928 MCAsmParser &Parser = getParser();
2929 if (Parser.getTok().isNot(AsmToken::Slash))
2930 return MatchOperand_Success;
2931
2932 // But when they do they shouldn't have an element type suffix.
2933 if (!Kind.empty()) {
2934 Error(S, "not expecting size suffix");
2935 return MatchOperand_ParseFail;
2936 }
2937
2938 // Add a literal slash as operand
2939 Operands.push_back(
2940 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2941
2942 Parser.Lex(); // Eat the slash.
2943
2944 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002945 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002946 if (Pred != "z" && Pred != "m") {
2947 Error(getLoc(), "expecting 'm' or 'z' predication");
2948 return MatchOperand_ParseFail;
2949 }
2950
2951 // Add zero/merge token.
2952 const char *ZM = Pred == "z" ? "z" : "m";
2953 Operands.push_back(
2954 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2955
2956 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002957 return MatchOperand_Success;
2958}
2959
Sander de Smalen50d87022018-04-19 07:35:08 +00002960/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002961bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002962 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002963 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002964 return false;
2965
Sander de Smalen149916d2018-04-20 07:24:20 +00002966 // Otherwise try for a scalar register.
2967 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
2968 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002969
Sander de Smalen149916d2018-04-20 07:24:20 +00002970 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002971}
2972
2973bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002974 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002975 bool HasELFModifier = false;
2976 AArch64MCExpr::VariantKind RefKind;
2977
Nirav Davee833c6c2016-11-08 18:31:04 +00002978 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002979 HasELFModifier = true;
2980
Nirav Davee833c6c2016-11-08 18:31:04 +00002981 if (Parser.getTok().isNot(AsmToken::Identifier))
2982 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002983
2984 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2985 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2986 .Case("lo12", AArch64MCExpr::VK_LO12)
2987 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2988 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2989 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2990 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2991 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2992 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2993 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2994 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2995 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2996 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2997 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2998 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2999 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3000 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3001 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3002 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3003 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3004 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3005 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3006 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3007 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3008 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3009 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3010 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3011 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3012 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3013 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3014 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3015 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3016 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3017 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3018 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3019 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3020 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003021 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3022 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00003023 .Default(AArch64MCExpr::VK_INVALID);
3024
Nirav Davee833c6c2016-11-08 18:31:04 +00003025 if (RefKind == AArch64MCExpr::VK_INVALID)
3026 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003027
3028 Parser.Lex(); // Eat identifier
3029
Nirav Davee833c6c2016-11-08 18:31:04 +00003030 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003031 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003032 }
3033
3034 if (getParser().parseExpression(ImmVal))
3035 return true;
3036
3037 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003038 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003039
3040 return false;
3041}
3042
Sander de Smalen650234b2018-04-12 11:40:52 +00003043template <RegKind VectorKind>
3044OperandMatchResultTy
3045AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3046 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003047 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003048 if (!Parser.getTok().is(AsmToken::LCurly))
3049 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003050
3051 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003052 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003053 bool NoMatchIsError) {
3054 auto RegTok = Parser.getTok();
3055 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3056 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003057 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003058 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003059 llvm_unreachable("Expected a valid vector kind");
3060 }
3061
Sander de Smalen650234b2018-04-12 11:40:52 +00003062 if (RegTok.isNot(AsmToken::Identifier) ||
3063 ParseRes == MatchOperand_ParseFail ||
3064 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3065 Error(Loc, "vector register expected");
3066 return MatchOperand_ParseFail;
3067 }
3068
3069 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003070 };
3071
Tim Northover3b0846e2014-05-24 12:50:23 +00003072 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003073 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003074 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003075
Tim Northover3b0846e2014-05-24 12:50:23 +00003076 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003077 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003078 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3079
3080 // Put back the original left bracket if there was no match, so that
3081 // different types of list-operands can be matched (e.g. SVE, Neon).
3082 if (ParseRes == MatchOperand_NoMatch)
3083 Parser.getLexer().UnLex(LCurly);
3084
3085 if (ParseRes != MatchOperand_Success)
3086 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003087
Tim Northover3b0846e2014-05-24 12:50:23 +00003088 int64_t PrevReg = FirstReg;
3089 unsigned Count = 1;
3090
Nirav Davee833c6c2016-11-08 18:31:04 +00003091 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003092 SMLoc Loc = getLoc();
3093 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003094
Sander de Smalen50d87022018-04-19 07:35:08 +00003095 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003096 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3097 if (ParseRes != MatchOperand_Success)
3098 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003099
Tim Northover3b0846e2014-05-24 12:50:23 +00003100 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003101 if (Kind != NextKind) {
3102 Error(Loc, "mismatched register size suffix");
3103 return MatchOperand_ParseFail;
3104 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003105
3106 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3107
3108 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003109 Error(Loc, "invalid number of vectors");
3110 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003111 }
3112
3113 Count += Space;
3114 }
3115 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003116 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003117 SMLoc Loc = getLoc();
3118 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003119 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003120 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3121 if (ParseRes != MatchOperand_Success)
3122 return ParseRes;
3123
Tim Northover3b0846e2014-05-24 12:50:23 +00003124 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003125 if (Kind != NextKind) {
3126 Error(Loc, "mismatched register size suffix");
3127 return MatchOperand_ParseFail;
3128 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003129
3130 // Registers must be incremental (with wraparound at 31)
3131 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003132 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3133 Error(Loc, "registers must be sequential");
3134 return MatchOperand_ParseFail;
3135 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003136
3137 PrevReg = Reg;
3138 ++Count;
3139 }
3140 }
3141
Nirav Davee833c6c2016-11-08 18:31:04 +00003142 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003143 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003144
Sander de Smalen650234b2018-04-12 11:40:52 +00003145 if (Count > 4) {
3146 Error(S, "invalid number of vectors");
3147 return MatchOperand_ParseFail;
3148 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003149
3150 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003151 unsigned ElementWidth = 0;
3152 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003153 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003154 std::tie(NumElements, ElementWidth) = *VK;
3155 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003156
3157 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003158 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3159 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003160
Sander de Smalen650234b2018-04-12 11:40:52 +00003161 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003162}
3163
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003164/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3165bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003166 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3167 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003168 return true;
3169
3170 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3171}
3172
Alex Bradbury58eba092016-11-01 16:32:05 +00003173OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003174AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003175 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003176
Sander de Smalen50d87022018-04-19 07:35:08 +00003177 unsigned RegNum;
3178 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3179 if (Res != MatchOperand_Success)
3180 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003181
Nirav Davee833c6c2016-11-08 18:31:04 +00003182 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003183 Operands.push_back(AArch64Operand::CreateReg(
3184 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003185 return MatchOperand_Success;
3186 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003187
Nirav Davee833c6c2016-11-08 18:31:04 +00003188 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003189
Sander de Smalen50d87022018-04-19 07:35:08 +00003190 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003191 Error(getLoc(), "index must be absent or #0");
3192 return MatchOperand_ParseFail;
3193 }
3194
3195 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003196 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003197 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3198 Error(getLoc(), "index must be absent or #0");
3199 return MatchOperand_ParseFail;
3200 }
3201
Sander de Smalen50d87022018-04-19 07:35:08 +00003202 Operands.push_back(AArch64Operand::CreateReg(
3203 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003204 return MatchOperand_Success;
3205}
3206
Sander de Smalen0325e302018-07-02 07:34:52 +00003207template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
Sander de Smalen149916d2018-04-20 07:24:20 +00003208OperandMatchResultTy
3209AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3210 SMLoc StartLoc = getLoc();
3211
3212 unsigned RegNum;
3213 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3214 if (Res != MatchOperand_Success)
3215 return Res;
3216
3217 // No shift/extend is the default.
3218 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3219 Operands.push_back(AArch64Operand::CreateReg(
Sander de Smalen0325e302018-07-02 07:34:52 +00003220 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
Sander de Smalen149916d2018-04-20 07:24:20 +00003221 return MatchOperand_Success;
3222 }
3223
3224 // Eat the comma
3225 getParser().Lex();
3226
3227 // Match the shift
3228 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3229 Res = tryParseOptionalShiftExtend(ExtOpnd);
3230 if (Res != MatchOperand_Success)
3231 return Res;
3232
3233 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
Sander de Smalen0325e302018-07-02 07:34:52 +00003234 Operands.push_back(AArch64Operand::CreateReg(
3235 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3236 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3237 Ext->hasShiftExtendAmount()));
Sander de Smalen149916d2018-04-20 07:24:20 +00003238
3239 return MatchOperand_Success;
3240}
3241
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003242bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
Sander de Smalen5c625982018-04-13 12:56:14 +00003243 MCAsmParser &Parser = getParser();
3244
3245 // Some SVE instructions have a decoration after the immediate, i.e.
3246 // "mul vl". We parse them here and add tokens, which must be present in the
3247 // asm string in the tablegen instruction.
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003248 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3249 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
Sander de Smalen5c625982018-04-13 12:56:14 +00003250 if (!Parser.getTok().getString().equals_lower("mul") ||
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003251 !(NextIsVL || NextIsHash))
Sander de Smalen5c625982018-04-13 12:56:14 +00003252 return true;
3253
Sander de Smalen5c625982018-04-13 12:56:14 +00003254 Operands.push_back(
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003255 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
Sander de Smalen5c625982018-04-13 12:56:14 +00003256 Parser.Lex(); // Eat the "mul"
3257
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003258 if (NextIsVL) {
3259 Operands.push_back(
3260 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3261 Parser.Lex(); // Eat the "vl"
3262 return false;
3263 }
Sander de Smalen5c625982018-04-13 12:56:14 +00003264
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003265 if (NextIsHash) {
3266 Parser.Lex(); // Eat the #
3267 SMLoc S = getLoc();
3268
3269 // Parse immediate operand.
3270 const MCExpr *ImmVal;
3271 if (!Parser.parseExpression(ImmVal))
3272 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3273 Operands.push_back(AArch64Operand::CreateImm(
3274 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3275 getContext()));
3276 return MatchOperand_Success;
3277 }
3278 }
3279
3280 return Error(getLoc(), "expected 'vl' or '#<imm>'");
Sander de Smalen5c625982018-04-13 12:56:14 +00003281}
3282
Tim Northover3b0846e2014-05-24 12:50:23 +00003283/// parseOperand - Parse a arm instruction operand. For now this parses the
3284/// operand regardless of the mnemonic.
3285bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3286 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003287 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003288
3289 OperandMatchResultTy ResTy =
3290 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3291
Tim Northover3b0846e2014-05-24 12:50:23 +00003292 // Check if the current operand has a custom associated parser, if so, try to
3293 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003294 if (ResTy == MatchOperand_Success)
3295 return false;
3296 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3297 // there was a match, but an error occurred, in which case, just return that
3298 // the operand parsing failed.
3299 if (ResTy == MatchOperand_ParseFail)
3300 return true;
3301
3302 // Nothing custom, so do general case parsing.
3303 SMLoc S, E;
3304 switch (getLexer().getKind()) {
3305 default: {
3306 SMLoc S = getLoc();
3307 const MCExpr *Expr;
3308 if (parseSymbolicImmVal(Expr))
3309 return Error(S, "invalid operand");
3310
3311 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3312 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3313 return false;
3314 }
3315 case AsmToken::LBrac: {
3316 SMLoc Loc = Parser.getTok().getLoc();
3317 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3318 getContext()));
3319 Parser.Lex(); // Eat '['
3320
3321 // There's no comma after a '[', so we can parse the next operand
3322 // immediately.
3323 return parseOperand(Operands, false, false);
3324 }
3325 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003326 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003327 case AsmToken::Identifier: {
3328 // If we're expecting a Condition Code operand, then just parse that.
3329 if (isCondCode)
3330 return parseCondCode(Operands, invertCondCode);
3331
3332 // If it's a register name, parse it.
3333 if (!parseRegister(Operands))
3334 return false;
3335
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003336 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3337 // by SVE instructions.
3338 if (!parseOptionalMulOperand(Operands))
Sander de Smalen5c625982018-04-13 12:56:14 +00003339 return false;
3340
Tim Northover3b0846e2014-05-24 12:50:23 +00003341 // This could be an optional "shift" or "extend" operand.
3342 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3343 // We can only continue if no tokens were eaten.
3344 if (GotShift != MatchOperand_NoMatch)
3345 return GotShift;
3346
3347 // This was not a register so parse other operands that start with an
3348 // identifier (like labels) as expressions and create them as immediates.
3349 const MCExpr *IdVal;
3350 S = getLoc();
3351 if (getParser().parseExpression(IdVal))
3352 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003353 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3354 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3355 return false;
3356 }
3357 case AsmToken::Integer:
3358 case AsmToken::Real:
3359 case AsmToken::Hash: {
3360 // #42 -> immediate.
3361 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003362
3363 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003364
3365 // Parse a negative sign
3366 bool isNegative = false;
3367 if (Parser.getTok().is(AsmToken::Minus)) {
3368 isNegative = true;
3369 // We need to consume this token only when we have a Real, otherwise
3370 // we let parseSymbolicImmVal take care of it
3371 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3372 Parser.Lex();
3373 }
3374
3375 // The only Real that should come through here is a literal #0.0 for
3376 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3377 // so convert the value.
3378 const AsmToken &Tok = Parser.getTok();
3379 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003380 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003381 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3382 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3383 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
Sander de Smalen8fcc3f52018-07-03 09:07:23 +00003384 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
Tim Northover3b0846e2014-05-24 12:50:23 +00003385 return TokError("unexpected floating point literal");
3386 else if (IntVal != 0 || isNegative)
3387 return TokError("expected floating-point constant #0.0");
3388 Parser.Lex(); // Eat the token.
3389
3390 Operands.push_back(
3391 AArch64Operand::CreateToken("#0", false, S, getContext()));
3392 Operands.push_back(
3393 AArch64Operand::CreateToken(".0", false, S, getContext()));
3394 return false;
3395 }
3396
3397 const MCExpr *ImmVal;
3398 if (parseSymbolicImmVal(ImmVal))
3399 return true;
3400
3401 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3402 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3403 return false;
3404 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003405 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003406 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003407 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003408 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003409 Parser.Lex(); // Eat '='
3410 const MCExpr *SubExprVal;
3411 if (getParser().parseExpression(SubExprVal))
3412 return true;
3413
David Peixottoae5ba762014-07-18 16:05:14 +00003414 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003415 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003416 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003417
3418 bool IsXReg =
3419 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3420 Operands[1]->getReg());
3421
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003422 MCContext& Ctx = getContext();
3423 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3424 // 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 +00003425 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003426 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3427 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3428 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3429 ShiftAmt += 16;
3430 Imm >>= 16;
3431 }
3432 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3433 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3434 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003435 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003436 if (ShiftAmt)
3437 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3438 ShiftAmt, true, S, E, Ctx));
3439 return false;
3440 }
David Peixottoae5ba762014-07-18 16:05:14 +00003441 APInt Simm = APInt(64, Imm << ShiftAmt);
3442 // check if the immediate is an unsigned or signed 32-bit int for W regs
3443 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3444 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003445 }
3446 // 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 +00003447 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003448 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003449 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3450 return false;
3451 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003452 }
3453}
3454
Sander de Smalen0325e302018-07-02 07:34:52 +00003455bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3456 const MCParsedAsmOperand &Op2) const {
3457 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3458 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3459 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3460 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3461 return MCTargetAsmParser::regsEqual(Op1, Op2);
3462
3463 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3464 "Testing equality of non-scalar registers not supported");
3465
3466 // Check if a registers match their sub/super register classes.
3467 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3468 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3469 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3470 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3471 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3472 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3473 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3474 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3475
3476 return false;
3477}
3478
Tim Northover3b0846e2014-05-24 12:50:23 +00003479/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3480/// operands.
3481bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3482 StringRef Name, SMLoc NameLoc,
3483 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003484 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003485 Name = StringSwitch<StringRef>(Name.lower())
3486 .Case("beq", "b.eq")
3487 .Case("bne", "b.ne")
3488 .Case("bhs", "b.hs")
3489 .Case("bcs", "b.cs")
3490 .Case("blo", "b.lo")
3491 .Case("bcc", "b.cc")
3492 .Case("bmi", "b.mi")
3493 .Case("bpl", "b.pl")
3494 .Case("bvs", "b.vs")
3495 .Case("bvc", "b.vc")
3496 .Case("bhi", "b.hi")
3497 .Case("bls", "b.ls")
3498 .Case("bge", "b.ge")
3499 .Case("blt", "b.lt")
3500 .Case("bgt", "b.gt")
3501 .Case("ble", "b.le")
3502 .Case("bal", "b.al")
3503 .Case("bnv", "b.nv")
3504 .Default(Name);
3505
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003506 // First check for the AArch64-specific .req directive.
3507 if (Parser.getTok().is(AsmToken::Identifier) &&
3508 Parser.getTok().getIdentifier() == ".req") {
3509 parseDirectiveReq(Name, NameLoc);
3510 // We always return 'error' for this, as we're done with this
3511 // statement and don't need to match the 'instruction."
3512 return true;
3513 }
3514
Tim Northover3b0846e2014-05-24 12:50:23 +00003515 // Create the leading tokens for the mnemonic, split by '.' characters.
3516 size_t Start = 0, Next = Name.find('.');
3517 StringRef Head = Name.slice(Start, Next);
3518
3519 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003520 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3521 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003522
3523 Operands.push_back(
3524 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3525 Mnemonic = Head;
3526
3527 // Handle condition codes for a branch mnemonic
3528 if (Head == "b" && Next != StringRef::npos) {
3529 Start = Next;
3530 Next = Name.find('.', Start + 1);
3531 Head = Name.slice(Start + 1, Next);
3532
3533 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3534 (Head.data() - Name.data()));
3535 AArch64CC::CondCode CC = parseCondCodeString(Head);
3536 if (CC == AArch64CC::Invalid)
3537 return Error(SuffixLoc, "invalid condition code");
3538 Operands.push_back(
3539 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3540 Operands.push_back(
3541 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3542 }
3543
3544 // Add the remaining tokens in the mnemonic.
3545 while (Next != StringRef::npos) {
3546 Start = Next;
3547 Next = Name.find('.', Start + 1);
3548 Head = Name.slice(Start, Next);
3549 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3550 (Head.data() - Name.data()) + 1);
3551 Operands.push_back(
3552 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3553 }
3554
3555 // Conditional compare instructions have a Condition Code operand, which needs
3556 // to be parsed and an immediate operand created.
3557 bool condCodeFourthOperand =
3558 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3559 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3560 Head == "csinc" || Head == "csinv" || Head == "csneg");
3561
3562 // These instructions are aliases to some of the conditional select
3563 // instructions. However, the condition code is inverted in the aliased
3564 // instruction.
3565 //
3566 // FIXME: Is this the correct way to handle these? Or should the parser
3567 // generate the aliased instructions directly?
3568 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3569 bool condCodeThirdOperand =
3570 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3571
3572 // Read the remaining operands.
3573 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3574 // Read the first operand.
3575 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003576 return true;
3577 }
3578
3579 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003580 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003581 // Parse and remember the operand.
3582 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3583 (N == 3 && condCodeThirdOperand) ||
3584 (N == 2 && condCodeSecondOperand),
3585 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003586 return true;
3587 }
3588
3589 // After successfully parsing some operands there are two special cases to
3590 // consider (i.e. notional operands not separated by commas). Both are due
3591 // to memory specifiers:
3592 // + An RBrac will end an address for load/store/prefetch
3593 // + An '!' will indicate a pre-indexed operation.
3594 //
3595 // It's someone else's responsibility to make sure these tokens are sane
3596 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003597
Nirav Davee833c6c2016-11-08 18:31:04 +00003598 SMLoc RLoc = Parser.getTok().getLoc();
3599 if (parseOptionalToken(AsmToken::RBrac))
3600 Operands.push_back(
3601 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3602 SMLoc ELoc = Parser.getTok().getLoc();
3603 if (parseOptionalToken(AsmToken::Exclaim))
3604 Operands.push_back(
3605 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003606
3607 ++N;
3608 }
3609 }
3610
Nirav Davee833c6c2016-11-08 18:31:04 +00003611 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3612 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003613
Tim Northover3b0846e2014-05-24 12:50:23 +00003614 return false;
3615}
3616
3617// FIXME: This entire function is a giant hack to provide us with decent
3618// operand range validation/diagnostics until TableGen/MC can be extended
3619// to support autogeneration of this kind of validation.
3620bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3621 SmallVectorImpl<SMLoc> &Loc) {
3622 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3623 // Check for indexed addressing modes w/ the base register being the
3624 // same as a destination/source register or pair load where
3625 // the Rt == Rt2. All of those are undefined behaviour.
3626 switch (Inst.getOpcode()) {
3627 case AArch64::LDPSWpre:
3628 case AArch64::LDPWpost:
3629 case AArch64::LDPWpre:
3630 case AArch64::LDPXpost:
3631 case AArch64::LDPXpre: {
3632 unsigned Rt = Inst.getOperand(1).getReg();
3633 unsigned Rt2 = Inst.getOperand(2).getReg();
3634 unsigned Rn = Inst.getOperand(3).getReg();
3635 if (RI->isSubRegisterEq(Rn, Rt))
3636 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3637 "is also a destination");
3638 if (RI->isSubRegisterEq(Rn, Rt2))
3639 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3640 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003641 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003642 }
3643 case AArch64::LDPDi:
3644 case AArch64::LDPQi:
3645 case AArch64::LDPSi:
3646 case AArch64::LDPSWi:
3647 case AArch64::LDPWi:
3648 case AArch64::LDPXi: {
3649 unsigned Rt = Inst.getOperand(0).getReg();
3650 unsigned Rt2 = Inst.getOperand(1).getReg();
3651 if (Rt == Rt2)
3652 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3653 break;
3654 }
3655 case AArch64::LDPDpost:
3656 case AArch64::LDPDpre:
3657 case AArch64::LDPQpost:
3658 case AArch64::LDPQpre:
3659 case AArch64::LDPSpost:
3660 case AArch64::LDPSpre:
3661 case AArch64::LDPSWpost: {
3662 unsigned Rt = Inst.getOperand(1).getReg();
3663 unsigned Rt2 = Inst.getOperand(2).getReg();
3664 if (Rt == Rt2)
3665 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3666 break;
3667 }
3668 case AArch64::STPDpost:
3669 case AArch64::STPDpre:
3670 case AArch64::STPQpost:
3671 case AArch64::STPQpre:
3672 case AArch64::STPSpost:
3673 case AArch64::STPSpre:
3674 case AArch64::STPWpost:
3675 case AArch64::STPWpre:
3676 case AArch64::STPXpost:
3677 case AArch64::STPXpre: {
3678 unsigned Rt = Inst.getOperand(1).getReg();
3679 unsigned Rt2 = Inst.getOperand(2).getReg();
3680 unsigned Rn = Inst.getOperand(3).getReg();
3681 if (RI->isSubRegisterEq(Rn, Rt))
3682 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3683 "is also a source");
3684 if (RI->isSubRegisterEq(Rn, Rt2))
3685 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3686 "is also a source");
3687 break;
3688 }
3689 case AArch64::LDRBBpre:
3690 case AArch64::LDRBpre:
3691 case AArch64::LDRHHpre:
3692 case AArch64::LDRHpre:
3693 case AArch64::LDRSBWpre:
3694 case AArch64::LDRSBXpre:
3695 case AArch64::LDRSHWpre:
3696 case AArch64::LDRSHXpre:
3697 case AArch64::LDRSWpre:
3698 case AArch64::LDRWpre:
3699 case AArch64::LDRXpre:
3700 case AArch64::LDRBBpost:
3701 case AArch64::LDRBpost:
3702 case AArch64::LDRHHpost:
3703 case AArch64::LDRHpost:
3704 case AArch64::LDRSBWpost:
3705 case AArch64::LDRSBXpost:
3706 case AArch64::LDRSHWpost:
3707 case AArch64::LDRSHXpost:
3708 case AArch64::LDRSWpost:
3709 case AArch64::LDRWpost:
3710 case AArch64::LDRXpost: {
3711 unsigned Rt = Inst.getOperand(1).getReg();
3712 unsigned Rn = Inst.getOperand(2).getReg();
3713 if (RI->isSubRegisterEq(Rn, Rt))
3714 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3715 "is also a source");
3716 break;
3717 }
3718 case AArch64::STRBBpost:
3719 case AArch64::STRBpost:
3720 case AArch64::STRHHpost:
3721 case AArch64::STRHpost:
3722 case AArch64::STRWpost:
3723 case AArch64::STRXpost:
3724 case AArch64::STRBBpre:
3725 case AArch64::STRBpre:
3726 case AArch64::STRHHpre:
3727 case AArch64::STRHpre:
3728 case AArch64::STRWpre:
3729 case AArch64::STRXpre: {
3730 unsigned Rt = Inst.getOperand(1).getReg();
3731 unsigned Rn = Inst.getOperand(2).getReg();
3732 if (RI->isSubRegisterEq(Rn, Rt))
3733 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3734 "is also a source");
3735 break;
3736 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003737 case AArch64::STXRB:
3738 case AArch64::STXRH:
3739 case AArch64::STXRW:
3740 case AArch64::STXRX:
3741 case AArch64::STLXRB:
3742 case AArch64::STLXRH:
3743 case AArch64::STLXRW:
3744 case AArch64::STLXRX: {
3745 unsigned Rs = Inst.getOperand(0).getReg();
3746 unsigned Rt = Inst.getOperand(1).getReg();
3747 unsigned Rn = Inst.getOperand(2).getReg();
3748 if (RI->isSubRegisterEq(Rt, Rs) ||
3749 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3750 return Error(Loc[0],
3751 "unpredictable STXR instruction, status is also a source");
3752 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003753 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003754 case AArch64::STXPW:
3755 case AArch64::STXPX:
3756 case AArch64::STLXPW:
3757 case AArch64::STLXPX: {
3758 unsigned Rs = Inst.getOperand(0).getReg();
3759 unsigned Rt1 = Inst.getOperand(1).getReg();
3760 unsigned Rt2 = Inst.getOperand(2).getReg();
3761 unsigned Rn = Inst.getOperand(3).getReg();
3762 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3763 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3764 return Error(Loc[0],
3765 "unpredictable STXP instruction, status is also a source");
3766 break;
3767 }
3768 }
3769
Tim Northover3b0846e2014-05-24 12:50:23 +00003770
3771 // Now check immediate ranges. Separate from the above as there is overlap
3772 // in the instructions being checked and this keeps the nested conditionals
3773 // to a minimum.
3774 switch (Inst.getOpcode()) {
3775 case AArch64::ADDSWri:
3776 case AArch64::ADDSXri:
3777 case AArch64::ADDWri:
3778 case AArch64::ADDXri:
3779 case AArch64::SUBSWri:
3780 case AArch64::SUBSXri:
3781 case AArch64::SUBWri:
3782 case AArch64::SUBXri: {
3783 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3784 // some slight duplication here.
3785 if (Inst.getOperand(2).isExpr()) {
3786 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3787 AArch64MCExpr::VariantKind ELFRefKind;
3788 MCSymbolRefExpr::VariantKind DarwinRefKind;
3789 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003790 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3791
3792 // Only allow these with ADDXri.
3793 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3794 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3795 Inst.getOpcode() == AArch64::ADDXri)
3796 return false;
3797
3798 // Only allow these with ADDXri/ADDWri
3799 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3800 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3801 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3802 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3803 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3804 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3805 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003806 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3807 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3808 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003809 (Inst.getOpcode() == AArch64::ADDXri ||
3810 Inst.getOpcode() == AArch64::ADDWri))
3811 return false;
3812
3813 // Don't allow symbol refs in the immediate field otherwise
3814 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3815 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3816 // 'cmp w0, 'borked')
3817 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003818 }
Diana Picusc93518d2016-10-11 09:17:47 +00003819 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003820 }
3821 return false;
3822 }
3823 default:
3824 return false;
3825 }
3826}
3827
Craig Topper05515562017-10-26 06:46:41 +00003828static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3829 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003830
3831bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
Sander de Smalen0325e302018-07-02 07:34:52 +00003832 uint64_t ErrorInfo,
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003833 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003834 switch (ErrCode) {
Sander de Smalen0325e302018-07-02 07:34:52 +00003835 case Match_InvalidTiedOperand: {
3836 RegConstraintEqualityTy EqTy =
3837 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
3838 .getRegEqualityTy();
3839 switch (EqTy) {
3840 case RegConstraintEqualityTy::EqualsSubReg:
3841 return Error(Loc, "operand must be 64-bit form of destination register");
3842 case RegConstraintEqualityTy::EqualsSuperReg:
3843 return Error(Loc, "operand must be 32-bit form of destination register");
3844 case RegConstraintEqualityTy::EqualsReg:
3845 return Error(Loc, "operand must match destination register");
3846 }
3847 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003848 case Match_MissingFeature:
3849 return Error(Loc,
3850 "instruction requires a CPU feature not currently enabled");
3851 case Match_InvalidOperand:
3852 return Error(Loc, "invalid operand for instruction");
3853 case Match_InvalidSuffix:
3854 return Error(Loc, "invalid type suffix for instruction");
3855 case Match_InvalidCondCode:
3856 return Error(Loc, "expected AArch64 condition code");
3857 case Match_AddSubRegExtendSmall:
3858 return Error(Loc,
3859 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3860 case Match_AddSubRegExtendLarge:
3861 return Error(Loc,
3862 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3863 case Match_AddSubSecondSource:
3864 return Error(Loc,
3865 "expected compatible register, symbol or integer in range [0, 4095]");
3866 case Match_LogicalSecondSource:
3867 return Error(Loc, "expected compatible register or logical immediate");
3868 case Match_InvalidMovImm32Shift:
3869 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3870 case Match_InvalidMovImm64Shift:
3871 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3872 case Match_AddSubRegShift32:
3873 return Error(Loc,
3874 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3875 case Match_AddSubRegShift64:
3876 return Error(Loc,
3877 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3878 case Match_InvalidFPImm:
3879 return Error(Loc,
3880 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003881 case Match_InvalidMemoryIndexedSImm6:
3882 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003883 case Match_InvalidMemoryIndexedSImm5:
3884 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003885 case Match_InvalidMemoryIndexed1SImm4:
3886 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003887 case Match_InvalidMemoryIndexed2SImm4:
3888 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003889 case Match_InvalidMemoryIndexed3SImm4:
3890 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003891 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00003892 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00003893 case Match_InvalidMemoryIndexed16SImm4:
3894 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00003895 case Match_InvalidMemoryIndexed1SImm6:
3896 return Error(Loc, "index must be an integer in range [-32, 31].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003897 case Match_InvalidMemoryIndexedSImm9:
3898 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00003899 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00003900 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003901 case Match_InvalidMemoryIndexed4SImm7:
3902 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3903 case Match_InvalidMemoryIndexed8SImm7:
3904 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3905 case Match_InvalidMemoryIndexed16SImm7:
3906 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00003907 case Match_InvalidMemoryIndexed8UImm5:
3908 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
3909 case Match_InvalidMemoryIndexed4UImm5:
3910 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
3911 case Match_InvalidMemoryIndexed2UImm5:
3912 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00003913 case Match_InvalidMemoryIndexed8UImm6:
3914 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
3915 case Match_InvalidMemoryIndexed4UImm6:
3916 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
3917 case Match_InvalidMemoryIndexed2UImm6:
3918 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
3919 case Match_InvalidMemoryIndexed1UImm6:
3920 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003921 case Match_InvalidMemoryWExtend8:
3922 return Error(Loc,
3923 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3924 case Match_InvalidMemoryWExtend16:
3925 return Error(Loc,
3926 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3927 case Match_InvalidMemoryWExtend32:
3928 return Error(Loc,
3929 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3930 case Match_InvalidMemoryWExtend64:
3931 return Error(Loc,
3932 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3933 case Match_InvalidMemoryWExtend128:
3934 return Error(Loc,
3935 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3936 case Match_InvalidMemoryXExtend8:
3937 return Error(Loc,
3938 "expected 'lsl' or 'sxtx' with optional shift of #0");
3939 case Match_InvalidMemoryXExtend16:
3940 return Error(Loc,
3941 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3942 case Match_InvalidMemoryXExtend32:
3943 return Error(Loc,
3944 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3945 case Match_InvalidMemoryXExtend64:
3946 return Error(Loc,
3947 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3948 case Match_InvalidMemoryXExtend128:
3949 return Error(Loc,
3950 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3951 case Match_InvalidMemoryIndexed1:
3952 return Error(Loc, "index must be an integer in range [0, 4095].");
3953 case Match_InvalidMemoryIndexed2:
3954 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3955 case Match_InvalidMemoryIndexed4:
3956 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3957 case Match_InvalidMemoryIndexed8:
3958 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3959 case Match_InvalidMemoryIndexed16:
3960 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003961 case Match_InvalidImm0_1:
3962 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003963 case Match_InvalidImm0_7:
3964 return Error(Loc, "immediate must be an integer in range [0, 7].");
3965 case Match_InvalidImm0_15:
3966 return Error(Loc, "immediate must be an integer in range [0, 15].");
3967 case Match_InvalidImm0_31:
3968 return Error(Loc, "immediate must be an integer in range [0, 31].");
3969 case Match_InvalidImm0_63:
3970 return Error(Loc, "immediate must be an integer in range [0, 63].");
3971 case Match_InvalidImm0_127:
3972 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003973 case Match_InvalidImm0_255:
3974 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003975 case Match_InvalidImm0_65535:
3976 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3977 case Match_InvalidImm1_8:
3978 return Error(Loc, "immediate must be an integer in range [1, 8].");
3979 case Match_InvalidImm1_16:
3980 return Error(Loc, "immediate must be an integer in range [1, 16].");
3981 case Match_InvalidImm1_32:
3982 return Error(Loc, "immediate must be an integer in range [1, 32].");
3983 case Match_InvalidImm1_64:
3984 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00003985 case Match_InvalidSVEAddSubImm8:
3986 return Error(Loc, "immediate must be an integer in range [0, 255]"
3987 " with a shift amount of 0");
3988 case Match_InvalidSVEAddSubImm16:
3989 case Match_InvalidSVEAddSubImm32:
3990 case Match_InvalidSVEAddSubImm64:
3991 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
3992 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00003993 case Match_InvalidSVECpyImm8:
3994 return Error(Loc, "immediate must be an integer in range [-128, 255]"
3995 " with a shift amount of 0");
3996 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00003997 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
3998 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00003999 case Match_InvalidSVECpyImm32:
4000 case Match_InvalidSVECpyImm64:
4001 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4002 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004003 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004004 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004005 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00004006 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004007 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00004008 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004009 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004010 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004011 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004012 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004013 case Match_InvalidSVEIndexRange0_63:
4014 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4015 case Match_InvalidSVEIndexRange0_31:
4016 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4017 case Match_InvalidSVEIndexRange0_15:
4018 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4019 case Match_InvalidSVEIndexRange0_7:
4020 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4021 case Match_InvalidSVEIndexRange0_3:
4022 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004023 case Match_InvalidLabel:
4024 return Error(Loc, "expected label or encodable integer pc offset");
4025 case Match_MRS:
4026 return Error(Loc, "expected readable system register");
4027 case Match_MSR:
4028 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00004029 case Match_InvalidComplexRotationEven:
4030 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4031 case Match_InvalidComplexRotationOdd:
4032 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004033 case Match_MnemonicFail: {
4034 std::string Suggestion = AArch64MnemonicSpellCheck(
4035 ((AArch64Operand &)*Operands[0]).getToken(),
4036 ComputeAvailableFeatures(STI->getFeatureBits()));
4037 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4038 }
Sander de Smalen367694b2018-04-20 08:54:49 +00004039 case Match_InvalidGPR64shifted8:
4040 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4041 case Match_InvalidGPR64shifted16:
4042 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4043 case Match_InvalidGPR64shifted32:
4044 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4045 case Match_InvalidGPR64shifted64:
4046 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4047 case Match_InvalidGPR64NoXZRshifted8:
4048 return Error(Loc, "register must be x0..x30 without shift");
4049 case Match_InvalidGPR64NoXZRshifted16:
4050 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4051 case Match_InvalidGPR64NoXZRshifted32:
4052 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4053 case Match_InvalidGPR64NoXZRshifted64:
4054 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004055 case Match_InvalidZPR32UXTW8:
4056 case Match_InvalidZPR32SXTW8:
4057 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4058 case Match_InvalidZPR32UXTW16:
4059 case Match_InvalidZPR32SXTW16:
4060 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4061 case Match_InvalidZPR32UXTW32:
4062 case Match_InvalidZPR32SXTW32:
4063 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4064 case Match_InvalidZPR32UXTW64:
4065 case Match_InvalidZPR32SXTW64:
4066 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4067 case Match_InvalidZPR64UXTW8:
4068 case Match_InvalidZPR64SXTW8:
4069 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4070 case Match_InvalidZPR64UXTW16:
4071 case Match_InvalidZPR64SXTW16:
4072 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4073 case Match_InvalidZPR64UXTW32:
4074 case Match_InvalidZPR64SXTW32:
4075 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4076 case Match_InvalidZPR64UXTW64:
4077 case Match_InvalidZPR64SXTW64:
4078 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
4079 case Match_InvalidZPR64LSL8:
4080 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4081 case Match_InvalidZPR64LSL16:
4082 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4083 case Match_InvalidZPR64LSL32:
4084 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4085 case Match_InvalidZPR64LSL64:
4086 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00004087 case Match_InvalidZPR0:
4088 return Error(Loc, "expected register without element width sufix");
4089 case Match_InvalidZPR8:
4090 case Match_InvalidZPR16:
4091 case Match_InvalidZPR32:
4092 case Match_InvalidZPR64:
4093 case Match_InvalidZPR128:
4094 return Error(Loc, "invalid element width");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004095 case Match_InvalidSVEPattern:
4096 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004097 case Match_InvalidSVEPredicateAnyReg:
4098 case Match_InvalidSVEPredicateBReg:
4099 case Match_InvalidSVEPredicateHReg:
4100 case Match_InvalidSVEPredicateSReg:
4101 case Match_InvalidSVEPredicateDReg:
4102 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004103 case Match_InvalidSVEPredicate3bAnyReg:
4104 case Match_InvalidSVEPredicate3bBReg:
4105 case Match_InvalidSVEPredicate3bHReg:
4106 case Match_InvalidSVEPredicate3bSReg:
4107 case Match_InvalidSVEPredicate3bDReg:
4108 return Error(Loc, "restricted predicate has range [0, 7].");
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004109 case Match_InvalidSVEExactFPImmOperandHalfOne:
4110 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4111 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4112 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4113 case Match_InvalidSVEExactFPImmOperandZeroOne:
4114 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004115 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004116 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004117 }
4118}
4119
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004120static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004121
4122bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4123 OperandVector &Operands,
4124 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004125 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004126 bool MatchingInlineAsm) {
4127 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004128 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4129 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004130
David Blaikie960ea3f2014-06-08 16:18:35 +00004131 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004132 unsigned NumOperands = Operands.size();
4133
4134 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004135 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4136 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004137 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004138 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004139 if (Op3CE) {
4140 uint64_t Op3Val = Op3CE->getValue();
4141 uint64_t NewOp3Val = 0;
4142 uint64_t NewOp4Val = 0;
4143 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004144 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004145 NewOp3Val = (32 - Op3Val) & 0x1f;
4146 NewOp4Val = 31 - Op3Val;
4147 } else {
4148 NewOp3Val = (64 - Op3Val) & 0x3f;
4149 NewOp4Val = 63 - Op3Val;
4150 }
4151
Jim Grosbach13760bd2015-05-30 01:25:56 +00004152 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4153 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004154
4155 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004156 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004157 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004158 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4159 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4160 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004161 }
4162 }
Tim Northover03b99f62015-04-30 18:28:58 +00004163 } else if (NumOperands == 4 && Tok == "bfc") {
4164 // FIXME: Horrible hack to handle BFC->BFM alias.
4165 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4166 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4167 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4168
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004169 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004170 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4171 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4172
4173 if (LSBCE && WidthCE) {
4174 uint64_t LSB = LSBCE->getValue();
4175 uint64_t Width = WidthCE->getValue();
4176
4177 uint64_t RegWidth = 0;
4178 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4179 Op1.getReg()))
4180 RegWidth = 64;
4181 else
4182 RegWidth = 32;
4183
4184 if (LSB >= RegWidth)
4185 return Error(LSBOp.getStartLoc(),
4186 "expected integer in range [0, 31]");
4187 if (Width < 1 || Width > RegWidth)
4188 return Error(WidthOp.getStartLoc(),
4189 "expected integer in range [1, 32]");
4190
4191 uint64_t ImmR = 0;
4192 if (RegWidth == 32)
4193 ImmR = (32 - LSB) & 0x1f;
4194 else
4195 ImmR = (64 - LSB) & 0x3f;
4196
4197 uint64_t ImmS = Width - 1;
4198
4199 if (ImmR != 0 && ImmS >= ImmR)
4200 return Error(WidthOp.getStartLoc(),
4201 "requested insert overflows register");
4202
Jim Grosbach13760bd2015-05-30 01:25:56 +00004203 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4204 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004205 Operands[0] = AArch64Operand::CreateToken(
4206 "bfm", false, Op.getStartLoc(), getContext());
4207 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004208 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4209 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004210 Operands[3] = AArch64Operand::CreateImm(
4211 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4212 Operands.emplace_back(
4213 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4214 WidthOp.getEndLoc(), getContext()));
4215 }
4216 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004217 } else if (NumOperands == 5) {
4218 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4219 // UBFIZ -> UBFM aliases.
4220 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004221 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4222 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4223 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004224
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004225 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004226 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4227 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004228
4229 if (Op3CE && Op4CE) {
4230 uint64_t Op3Val = Op3CE->getValue();
4231 uint64_t Op4Val = Op4CE->getValue();
4232
4233 uint64_t RegWidth = 0;
4234 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004235 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004236 RegWidth = 64;
4237 else
4238 RegWidth = 32;
4239
4240 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004241 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004242 "expected integer in range [0, 31]");
4243 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004244 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004245 "expected integer in range [1, 32]");
4246
4247 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004248 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004249 NewOp3Val = (32 - Op3Val) & 0x1f;
4250 else
4251 NewOp3Val = (64 - Op3Val) & 0x3f;
4252
4253 uint64_t NewOp4Val = Op4Val - 1;
4254
4255 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004256 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004257 "requested insert overflows register");
4258
4259 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004260 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004261 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004262 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004263 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004264 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004265 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004266 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004267 if (Tok == "bfi")
4268 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004269 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004270 else if (Tok == "sbfiz")
4271 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004272 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004273 else if (Tok == "ubfiz")
4274 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004275 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004276 else
4277 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004278 }
4279 }
4280
4281 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4282 // UBFX -> UBFM aliases.
4283 } else if (NumOperands == 5 &&
4284 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004285 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4286 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4287 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004288
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004289 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004290 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4291 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004292
4293 if (Op3CE && Op4CE) {
4294 uint64_t Op3Val = Op3CE->getValue();
4295 uint64_t Op4Val = Op4CE->getValue();
4296
4297 uint64_t RegWidth = 0;
4298 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004299 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004300 RegWidth = 64;
4301 else
4302 RegWidth = 32;
4303
4304 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004305 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004306 "expected integer in range [0, 31]");
4307 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004308 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004309 "expected integer in range [1, 32]");
4310
4311 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4312
4313 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004314 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004315 "requested extract overflows register");
4316
4317 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004318 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004319 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004320 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004321 if (Tok == "bfxil")
4322 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004323 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004324 else if (Tok == "sbfx")
4325 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004326 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004327 else if (Tok == "ubfx")
4328 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004329 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004330 else
4331 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004332 }
4333 }
4334 }
4335 }
Tim Northover9097a072017-12-18 10:36:00 +00004336
4337 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4338 // instruction for FP registers correctly in some rare circumstances. Convert
4339 // it to a safe instruction and warn (because silently changing someone's
4340 // assembly is rude).
4341 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4342 NumOperands == 4 && Tok == "movi") {
4343 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4344 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4345 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4346 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4347 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4348 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4349 if (Suffix.lower() == ".2d" &&
4350 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4351 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4352 " correctly on this CPU, converting to equivalent movi.16b");
4353 // Switch the suffix to .16b.
4354 unsigned Idx = Op1.isToken() ? 1 : 2;
4355 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4356 getContext());
4357 }
4358 }
4359 }
4360
Tim Northover3b0846e2014-05-24 12:50:23 +00004361 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4362 // InstAlias can't quite handle this since the reg classes aren't
4363 // subclasses.
4364 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4365 // The source register can be Wn here, but the matcher expects a
4366 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004367 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004368 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004369 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004370 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4371 Op.getStartLoc(), Op.getEndLoc(),
4372 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004373 }
4374 }
4375 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4376 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004377 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004378 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004379 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004380 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004381 // The source register can be Wn here, but the matcher expects a
4382 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004383 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004384 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004385 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004386 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4387 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004388 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004389 }
4390 }
4391 }
4392 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4393 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004394 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004395 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004396 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004397 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004398 // The source register can be Wn here, but the matcher expects a
4399 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004400 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004401 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004402 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004403 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4404 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004405 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004406 }
4407 }
4408 }
4409
Tim Northover3b0846e2014-05-24 12:50:23 +00004410 MCInst Inst;
4411 // First try to match against the secondary set of tables containing the
4412 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4413 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004414 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004415
4416 // If that fails, try against the alternate table containing long-form NEON:
4417 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004418 if (MatchResult != Match_Success) {
4419 // But first, save the short-form match result: we can use it in case the
4420 // long-form match also fails.
4421 auto ShortFormNEONErrorInfo = ErrorInfo;
4422 auto ShortFormNEONMatchResult = MatchResult;
4423
Tim Northover3b0846e2014-05-24 12:50:23 +00004424 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004425 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004426
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004427 // Now, both matches failed, and the long-form match failed on the mnemonic
4428 // suffix token operand. The short-form match failure is probably more
4429 // relevant: use it instead.
4430 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004431 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004432 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4433 MatchResult = ShortFormNEONMatchResult;
4434 ErrorInfo = ShortFormNEONErrorInfo;
4435 }
4436 }
4437
Tim Northover3b0846e2014-05-24 12:50:23 +00004438 switch (MatchResult) {
4439 case Match_Success: {
4440 // Perform range checking and other semantic validations
4441 SmallVector<SMLoc, 8> OperandLocs;
4442 NumOperands = Operands.size();
4443 for (unsigned i = 1; i < NumOperands; ++i)
4444 OperandLocs.push_back(Operands[i]->getStartLoc());
4445 if (validateInstruction(Inst, OperandLocs))
4446 return true;
4447
4448 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004449 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004450 return false;
4451 }
4452 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004453 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004454 // Special case the error message for the very common case where only
4455 // a single subtarget feature is missing (neon, e.g.).
4456 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004457 uint64_t Mask = 1;
4458 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4459 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004460 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004461 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004462 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004463 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004464 }
4465 return Error(IDLoc, Msg);
4466 }
4467 case Match_MnemonicFail:
Sander de Smalen0325e302018-07-02 07:34:52 +00004468 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004469 case Match_InvalidOperand: {
4470 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004471
Tim Northover26bb14e2014-08-18 11:49:42 +00004472 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004473 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004474 return Error(IDLoc, "too few operands for instruction",
4475 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004476
David Blaikie960ea3f2014-06-08 16:18:35 +00004477 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004478 if (ErrorLoc == SMLoc())
4479 ErrorLoc = IDLoc;
4480 }
4481 // If the match failed on a suffix token operand, tweak the diagnostic
4482 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004483 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4484 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004485 MatchResult = Match_InvalidSuffix;
4486
Sander de Smalen0325e302018-07-02 07:34:52 +00004487 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004488 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004489 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004490 case Match_InvalidMemoryIndexed1:
4491 case Match_InvalidMemoryIndexed2:
4492 case Match_InvalidMemoryIndexed4:
4493 case Match_InvalidMemoryIndexed8:
4494 case Match_InvalidMemoryIndexed16:
4495 case Match_InvalidCondCode:
4496 case Match_AddSubRegExtendSmall:
4497 case Match_AddSubRegExtendLarge:
4498 case Match_AddSubSecondSource:
4499 case Match_LogicalSecondSource:
4500 case Match_AddSubRegShift32:
4501 case Match_AddSubRegShift64:
4502 case Match_InvalidMovImm32Shift:
4503 case Match_InvalidMovImm64Shift:
4504 case Match_InvalidFPImm:
4505 case Match_InvalidMemoryWExtend8:
4506 case Match_InvalidMemoryWExtend16:
4507 case Match_InvalidMemoryWExtend32:
4508 case Match_InvalidMemoryWExtend64:
4509 case Match_InvalidMemoryWExtend128:
4510 case Match_InvalidMemoryXExtend8:
4511 case Match_InvalidMemoryXExtend16:
4512 case Match_InvalidMemoryXExtend32:
4513 case Match_InvalidMemoryXExtend64:
4514 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004515 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004516 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004517 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004518 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004519 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004520 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004521 case Match_InvalidMemoryIndexed4SImm7:
4522 case Match_InvalidMemoryIndexed8SImm7:
4523 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004524 case Match_InvalidMemoryIndexed8UImm5:
4525 case Match_InvalidMemoryIndexed4UImm5:
4526 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004527 case Match_InvalidMemoryIndexed1UImm6:
4528 case Match_InvalidMemoryIndexed2UImm6:
4529 case Match_InvalidMemoryIndexed4UImm6:
4530 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004531 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004532 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004533 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004534 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004535 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004536 case Match_InvalidImm0_7:
4537 case Match_InvalidImm0_15:
4538 case Match_InvalidImm0_31:
4539 case Match_InvalidImm0_63:
4540 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004541 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004542 case Match_InvalidImm0_65535:
4543 case Match_InvalidImm1_8:
4544 case Match_InvalidImm1_16:
4545 case Match_InvalidImm1_32:
4546 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004547 case Match_InvalidSVEAddSubImm8:
4548 case Match_InvalidSVEAddSubImm16:
4549 case Match_InvalidSVEAddSubImm32:
4550 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004551 case Match_InvalidSVECpyImm8:
4552 case Match_InvalidSVECpyImm16:
4553 case Match_InvalidSVECpyImm32:
4554 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004555 case Match_InvalidIndexRange1_1:
4556 case Match_InvalidIndexRange0_15:
4557 case Match_InvalidIndexRange0_7:
4558 case Match_InvalidIndexRange0_3:
4559 case Match_InvalidIndexRange0_1:
4560 case Match_InvalidSVEIndexRange0_63:
4561 case Match_InvalidSVEIndexRange0_31:
4562 case Match_InvalidSVEIndexRange0_15:
4563 case Match_InvalidSVEIndexRange0_7:
4564 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004565 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004566 case Match_InvalidComplexRotationEven:
4567 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004568 case Match_InvalidGPR64shifted8:
4569 case Match_InvalidGPR64shifted16:
4570 case Match_InvalidGPR64shifted32:
4571 case Match_InvalidGPR64shifted64:
4572 case Match_InvalidGPR64NoXZRshifted8:
4573 case Match_InvalidGPR64NoXZRshifted16:
4574 case Match_InvalidGPR64NoXZRshifted32:
4575 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004576 case Match_InvalidZPR32UXTW8:
4577 case Match_InvalidZPR32UXTW16:
4578 case Match_InvalidZPR32UXTW32:
4579 case Match_InvalidZPR32UXTW64:
4580 case Match_InvalidZPR32SXTW8:
4581 case Match_InvalidZPR32SXTW16:
4582 case Match_InvalidZPR32SXTW32:
4583 case Match_InvalidZPR32SXTW64:
4584 case Match_InvalidZPR64UXTW8:
4585 case Match_InvalidZPR64SXTW8:
4586 case Match_InvalidZPR64UXTW16:
4587 case Match_InvalidZPR64SXTW16:
4588 case Match_InvalidZPR64UXTW32:
4589 case Match_InvalidZPR64SXTW32:
4590 case Match_InvalidZPR64UXTW64:
4591 case Match_InvalidZPR64SXTW64:
4592 case Match_InvalidZPR64LSL8:
4593 case Match_InvalidZPR64LSL16:
4594 case Match_InvalidZPR64LSL32:
4595 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004596 case Match_InvalidZPR0:
4597 case Match_InvalidZPR8:
4598 case Match_InvalidZPR16:
4599 case Match_InvalidZPR32:
4600 case Match_InvalidZPR64:
4601 case Match_InvalidZPR128:
Sander de Smalencd6be962017-12-20 11:02:42 +00004602 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004603 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004604 case Match_InvalidSVEPredicateBReg:
4605 case Match_InvalidSVEPredicateHReg:
4606 case Match_InvalidSVEPredicateSReg:
4607 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004608 case Match_InvalidSVEPredicate3bAnyReg:
4609 case Match_InvalidSVEPredicate3bBReg:
4610 case Match_InvalidSVEPredicate3bHReg:
4611 case Match_InvalidSVEPredicate3bSReg:
4612 case Match_InvalidSVEPredicate3bDReg:
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004613 case Match_InvalidSVEExactFPImmOperandHalfOne:
4614 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4615 case Match_InvalidSVEExactFPImmOperandZeroOne:
Tim Northover3b0846e2014-05-24 12:50:23 +00004616 case Match_MSR:
4617 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004618 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004619 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004620 // Any time we get here, there's nothing fancy to do. Just get the
4621 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004622 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004623 if (ErrorLoc == SMLoc())
4624 ErrorLoc = IDLoc;
Sander de Smalen0325e302018-07-02 07:34:52 +00004625 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004626 }
4627 }
4628
4629 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004630}
4631
4632/// ParseDirective parses the arm specific directives
4633bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004634 const MCObjectFileInfo::Environment Format =
4635 getContext().getObjectFileInfo()->getObjectFileType();
4636 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4637 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004638
Tim Northover3b0846e2014-05-24 12:50:23 +00004639 StringRef IDVal = DirectiveID.getIdentifier();
4640 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004641 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004642 parseDirectiveArch(Loc);
4643 else if (IDVal == ".cpu")
4644 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00004645 else if (IDVal == ".tlsdesccall")
4646 parseDirectiveTLSDescCall(Loc);
4647 else if (IDVal == ".ltorg" || IDVal == ".pool")
4648 parseDirectiveLtorg(Loc);
4649 else if (IDVal == ".unreq")
4650 parseDirectiveUnreq(Loc);
4651 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004652 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004653 parseDirectiveInst(Loc);
4654 else
4655 return true;
4656 } else if (IDVal == MCLOHDirectiveName())
4657 parseDirectiveLOH(IDVal, Loc);
4658 else
4659 return true;
4660 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004661}
4662
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004663static const struct {
4664 const char *Name;
4665 const FeatureBitset Features;
4666} ExtensionMap[] = {
4667 { "crc", {AArch64::FeatureCRC} },
4668 { "crypto", {AArch64::FeatureCrypto} },
4669 { "fp", {AArch64::FeatureFPARMv8} },
4670 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004671 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004672 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004673
4674 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004675 { "pan", {} },
4676 { "lor", {} },
4677 { "rdma", {} },
4678 { "profile", {} },
4679};
4680
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004681/// parseDirectiveArch
4682/// ::= .arch token
4683bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4684 SMLoc ArchLoc = getLoc();
4685
4686 StringRef Arch, ExtensionString;
4687 std::tie(Arch, ExtensionString) =
4688 getParser().parseStringToEndOfStatement().trim().split('+');
4689
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004690 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4691 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004692 return Error(ArchLoc, "unknown arch name");
4693
4694 if (parseToken(AsmToken::EndOfStatement))
4695 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004696
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004697 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004698 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004699 AArch64::getArchFeatures(ID, AArch64Features);
4700 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4701 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004702
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004703 MCSubtargetInfo &STI = copySTI();
4704 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4705 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4706
4707 SmallVector<StringRef, 4> RequestedExtensions;
4708 if (!ExtensionString.empty())
4709 ExtensionString.split(RequestedExtensions, '+');
4710
4711 FeatureBitset Features = STI.getFeatureBits();
4712 for (auto Name : RequestedExtensions) {
4713 bool EnableFeature = true;
4714
4715 if (Name.startswith_lower("no")) {
4716 EnableFeature = false;
4717 Name = Name.substr(2);
4718 }
4719
4720 for (const auto &Extension : ExtensionMap) {
4721 if (Extension.Name != Name)
4722 continue;
4723
4724 if (Extension.Features.none())
4725 report_fatal_error("unsupported architectural extension: " + Name);
4726
4727 FeatureBitset ToggleFeatures = EnableFeature
4728 ? (~Features & Extension.Features)
4729 : ( Features & Extension.Features);
4730 uint64_t Features =
4731 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4732 setAvailableFeatures(Features);
4733 break;
4734 }
4735 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004736 return false;
4737}
4738
Tim Northover8b96c7e2017-05-15 19:42:15 +00004739static SMLoc incrementLoc(SMLoc L, int Offset) {
4740 return SMLoc::getFromPointer(L.getPointer() + Offset);
4741}
4742
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004743/// parseDirectiveCPU
4744/// ::= .cpu id
4745bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004746 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004747
4748 StringRef CPU, ExtensionString;
4749 std::tie(CPU, ExtensionString) =
4750 getParser().parseStringToEndOfStatement().trim().split('+');
4751
Nirav Davee833c6c2016-11-08 18:31:04 +00004752 if (parseToken(AsmToken::EndOfStatement))
4753 return true;
4754
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004755 SmallVector<StringRef, 4> RequestedExtensions;
4756 if (!ExtensionString.empty())
4757 ExtensionString.split(RequestedExtensions, '+');
4758
4759 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4760 // once that is tablegen'ed
4761 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004762 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004763 return false;
4764 }
4765
4766 MCSubtargetInfo &STI = copySTI();
4767 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004768 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004769
4770 FeatureBitset Features = STI.getFeatureBits();
4771 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004772 // Advance source location past '+'.
4773 CurLoc = incrementLoc(CurLoc, 1);
4774
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004775 bool EnableFeature = true;
4776
4777 if (Name.startswith_lower("no")) {
4778 EnableFeature = false;
4779 Name = Name.substr(2);
4780 }
4781
Tim Northover8b96c7e2017-05-15 19:42:15 +00004782 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004783 for (const auto &Extension : ExtensionMap) {
4784 if (Extension.Name != Name)
4785 continue;
4786
4787 if (Extension.Features.none())
4788 report_fatal_error("unsupported architectural extension: " + Name);
4789
4790 FeatureBitset ToggleFeatures = EnableFeature
4791 ? (~Features & Extension.Features)
4792 : ( Features & Extension.Features);
4793 uint64_t Features =
4794 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4795 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004796 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004797
4798 break;
4799 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004800
4801 if (!FoundExtension)
4802 Error(CurLoc, "unsupported architectural extension");
4803
4804 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004805 }
4806 return false;
4807}
4808
Chad Rosierdcd2a302014-10-22 20:35:57 +00004809/// parseDirectiveInst
4810/// ::= .inst opcode [, ...]
4811bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004812 if (getLexer().is(AsmToken::EndOfStatement))
4813 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004814
Nirav Davee833c6c2016-11-08 18:31:04 +00004815 auto parseOp = [&]() -> bool {
4816 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004817 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004818 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4819 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004820 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004821 if (check(!Value, L, "expected constant expression"))
4822 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004823 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004824 return false;
4825 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004826
Nirav Davee833c6c2016-11-08 18:31:04 +00004827 if (parseMany(parseOp))
4828 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004829 return false;
4830}
4831
Tim Northover3b0846e2014-05-24 12:50:23 +00004832// parseDirectiveTLSDescCall:
4833// ::= .tlsdesccall symbol
4834bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4835 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004836 if (check(getParser().parseIdentifier(Name), L,
4837 "expected symbol after directive") ||
4838 parseToken(AsmToken::EndOfStatement))
4839 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004840
Jim Grosbach6f482002015-05-18 18:43:14 +00004841 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004842 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4843 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004844
4845 MCInst Inst;
4846 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004847 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004848
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004849 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004850 return false;
4851}
4852
4853/// ::= .loh <lohName | lohId> label1, ..., labelN
4854/// The number of arguments depends on the loh identifier.
4855bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004856 MCLOHType Kind;
4857 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4858 if (getParser().getTok().isNot(AsmToken::Integer))
4859 return TokError("expected an identifier or a number in directive");
4860 // We successfully get a numeric value for the identifier.
4861 // Check if it is valid.
4862 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004863 if (Id <= -1U && !isValidMCLOHType(Id))
4864 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004865 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004866 } else {
4867 StringRef Name = getTok().getIdentifier();
4868 // We successfully parse an identifier.
4869 // Check if it is a recognized one.
4870 int Id = MCLOHNameToId(Name);
4871
4872 if (Id == -1)
4873 return TokError("invalid identifier in directive");
4874 Kind = (MCLOHType)Id;
4875 }
4876 // Consume the identifier.
4877 Lex();
4878 // Get the number of arguments of this LOH.
4879 int NbArgs = MCLOHIdToNbArgs(Kind);
4880
4881 assert(NbArgs != -1 && "Invalid number of arguments");
4882
4883 SmallVector<MCSymbol *, 3> Args;
4884 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4885 StringRef Name;
4886 if (getParser().parseIdentifier(Name))
4887 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004888 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004889
4890 if (Idx + 1 == NbArgs)
4891 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004892 if (parseToken(AsmToken::Comma,
4893 "unexpected token in '" + Twine(IDVal) + "' directive"))
4894 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004895 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004896 if (parseToken(AsmToken::EndOfStatement,
4897 "unexpected token in '" + Twine(IDVal) + "' directive"))
4898 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004899
4900 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4901 return false;
4902}
4903
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004904/// parseDirectiveLtorg
4905/// ::= .ltorg | .pool
4906bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004907 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4908 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004909 getTargetStreamer().emitCurrentConstantPool();
4910 return false;
4911}
4912
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004913/// parseDirectiveReq
4914/// ::= name .req registername
4915bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004916 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004917 Parser.Lex(); // Eat the '.req' token.
4918 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004919 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004920 unsigned RegNum;
4921 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004922
Sander de Smalen50d87022018-04-19 07:35:08 +00004923 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004924 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004925 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004926 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004927
Sander de Smalen50d87022018-04-19 07:35:08 +00004928 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004929 return true;
4930
Sander de Smalen50d87022018-04-19 07:35:08 +00004931 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004932 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004933 }
4934
Sander de Smalen50d87022018-04-19 07:35:08 +00004935 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004936 StringRef Kind;
4937 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004938 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004939 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004940
Sander de Smalen50d87022018-04-19 07:35:08 +00004941 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004942 return true;
4943
Sander de Smalen50d87022018-04-19 07:35:08 +00004944 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004945 return Error(SRegLoc,
4946 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004947 }
4948
Sander de Smalen50d87022018-04-19 07:35:08 +00004949 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00004950 StringRef Kind;
4951 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004952 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004953
Sander de Smalen50d87022018-04-19 07:35:08 +00004954 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00004955 return true;
4956
Sander de Smalen50d87022018-04-19 07:35:08 +00004957 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00004958 return Error(SRegLoc,
4959 "sve predicate register without type specifier expected");
4960 }
4961
Sander de Smalen50d87022018-04-19 07:35:08 +00004962 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00004963 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004964
4965 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004966 if (parseToken(AsmToken::EndOfStatement,
4967 "unexpected input in .req directive"))
4968 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004969
Sander de Smalen8e607342017-11-15 15:44:43 +00004970 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004971 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004972 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4973
Nirav Dave2364748a2016-09-16 18:30:20 +00004974 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004975}
4976
4977/// parseDirectiveUneq
4978/// ::= .unreq registername
4979bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004980 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004981 if (getTok().isNot(AsmToken::Identifier))
4982 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004983 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4984 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004985 if (parseToken(AsmToken::EndOfStatement))
4986 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004987 return false;
4988}
4989
Tim Northover3b0846e2014-05-24 12:50:23 +00004990bool
4991AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4992 AArch64MCExpr::VariantKind &ELFRefKind,
4993 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4994 int64_t &Addend) {
4995 ELFRefKind = AArch64MCExpr::VK_INVALID;
4996 DarwinRefKind = MCSymbolRefExpr::VK_None;
4997 Addend = 0;
4998
4999 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5000 ELFRefKind = AE->getKind();
5001 Expr = AE->getSubExpr();
5002 }
5003
5004 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5005 if (SE) {
5006 // It's a simple symbol reference with no addend.
5007 DarwinRefKind = SE->getKind();
5008 return true;
5009 }
5010
5011 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
5012 if (!BE)
5013 return false;
5014
5015 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
5016 if (!SE)
5017 return false;
5018 DarwinRefKind = SE->getKind();
5019
5020 if (BE->getOpcode() != MCBinaryExpr::Add &&
5021 BE->getOpcode() != MCBinaryExpr::Sub)
5022 return false;
5023
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00005024 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00005025 // on here than we can deal with.
5026 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
5027 if (!AddendExpr)
5028 return false;
5029
5030 Addend = AddendExpr->getValue();
5031 if (BE->getOpcode() == MCBinaryExpr::Sub)
5032 Addend = -Addend;
5033
5034 // It's some symbol reference + a constant addend, but really
5035 // shouldn't use both Darwin and ELF syntax.
5036 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5037 DarwinRefKind == MCSymbolRefExpr::VK_None;
5038}
5039
5040/// Force static initialization.
5041extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00005042 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5043 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5044 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00005045}
5046
5047#define GET_REGISTER_MATCHER
5048#define GET_SUBTARGET_FEATURE_NAME
5049#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00005050#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00005051#include "AArch64GenAsmMatcher.inc"
5052
5053// Define this matcher function after the auto-generated include so we
5054// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00005055unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00005056 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005057 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00005058 // If the kind is a token for a literal immediate, check if our asm
5059 // operand matches. This is for InstAliases which have a fixed-value
5060 // immediate in the syntax.
5061 int64_t ExpectedVal;
5062 switch (Kind) {
5063 default:
5064 return Match_InvalidOperand;
5065 case MCK__35_0:
5066 ExpectedVal = 0;
5067 break;
5068 case MCK__35_1:
5069 ExpectedVal = 1;
5070 break;
5071 case MCK__35_12:
5072 ExpectedVal = 12;
5073 break;
5074 case MCK__35_16:
5075 ExpectedVal = 16;
5076 break;
5077 case MCK__35_2:
5078 ExpectedVal = 2;
5079 break;
5080 case MCK__35_24:
5081 ExpectedVal = 24;
5082 break;
5083 case MCK__35_3:
5084 ExpectedVal = 3;
5085 break;
5086 case MCK__35_32:
5087 ExpectedVal = 32;
5088 break;
5089 case MCK__35_4:
5090 ExpectedVal = 4;
5091 break;
5092 case MCK__35_48:
5093 ExpectedVal = 48;
5094 break;
5095 case MCK__35_6:
5096 ExpectedVal = 6;
5097 break;
5098 case MCK__35_64:
5099 ExpectedVal = 64;
5100 break;
5101 case MCK__35_8:
5102 ExpectedVal = 8;
5103 break;
5104 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005105 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005106 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005107 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005108 if (!CE)
5109 return Match_InvalidOperand;
5110 if (CE->getValue() == ExpectedVal)
5111 return Match_Success;
5112 return Match_InvalidOperand;
5113}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005114
Alex Bradbury58eba092016-11-01 16:32:05 +00005115OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005116AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5117
5118 SMLoc S = getLoc();
5119
5120 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5121 Error(S, "expected register");
5122 return MatchOperand_ParseFail;
5123 }
5124
Sander de Smalen50d87022018-04-19 07:35:08 +00005125 unsigned FirstReg;
5126 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5127 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005128 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005129
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005130 const MCRegisterClass &WRegClass =
5131 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5132 const MCRegisterClass &XRegClass =
5133 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5134
5135 bool isXReg = XRegClass.contains(FirstReg),
5136 isWReg = WRegClass.contains(FirstReg);
5137 if (!isXReg && !isWReg) {
5138 Error(S, "expected first even register of a "
5139 "consecutive same-size even/odd register pair");
5140 return MatchOperand_ParseFail;
5141 }
5142
5143 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5144 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5145
5146 if (FirstEncoding & 0x1) {
5147 Error(S, "expected first even register of a "
5148 "consecutive same-size even/odd register pair");
5149 return MatchOperand_ParseFail;
5150 }
5151
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005152 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005153 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005154 return MatchOperand_ParseFail;
5155 }
5156 // Eat the comma
5157 getParser().Lex();
5158
5159 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005160 unsigned SecondReg;
5161 Res = tryParseScalarRegister(SecondReg);
5162 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005163 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005164
Eugene Zelenko049b0172017-01-06 00:30:53 +00005165 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005166 (isXReg && !XRegClass.contains(SecondReg)) ||
5167 (isWReg && !WRegClass.contains(SecondReg))) {
5168 Error(E,"expected second odd register of a "
5169 "consecutive same-size even/odd register pair");
5170 return MatchOperand_ParseFail;
5171 }
Joel Jones504bf332016-10-24 13:37:13 +00005172
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005173 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005174 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005175 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5176 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5177 } else {
5178 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5179 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5180 }
5181
Florian Hahnc4422242017-11-07 13:07:50 +00005182 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5183 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005184
5185 return MatchOperand_Success;
5186}
Florian Hahn91f11e52017-11-07 16:45:48 +00005187
Sander de Smaleneb896b12018-04-25 09:26:47 +00005188template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005189OperandMatchResultTy
5190AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005191 const SMLoc S = getLoc();
5192 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005193 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005194 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005195
Sander de Smalen8e607342017-11-15 15:44:43 +00005196 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005197 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005198
5199 if (Res != MatchOperand_Success)
5200 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005201
5202 if (ParseSuffix && Kind.empty())
5203 return MatchOperand_NoMatch;
5204
Sander de Smalen73937b72018-04-11 07:36:10 +00005205 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5206 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005207 return MatchOperand_NoMatch;
5208
Sander de Smalen73937b72018-04-11 07:36:10 +00005209 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005210
5211 // No shift/extend is the default.
5212 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5213 Operands.push_back(AArch64Operand::CreateVectorReg(
5214 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5215
Sander de Smalenc33d6682018-06-04 06:40:55 +00005216 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5217 if (Res == MatchOperand_ParseFail)
5218 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005219 return MatchOperand_Success;
5220 }
5221
5222 // Eat the comma
5223 getParser().Lex();
5224
5225 // Match the shift
5226 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5227 Res = tryParseOptionalShiftExtend(ExtOpnd);
5228 if (Res != MatchOperand_Success)
5229 return Res;
5230
5231 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005232 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005233 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5234 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5235 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005236
5237 return MatchOperand_Success;
5238}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005239
5240OperandMatchResultTy
5241AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5242 MCAsmParser &Parser = getParser();
5243
5244 SMLoc SS = getLoc();
5245 const AsmToken &TokE = Parser.getTok();
5246 bool IsHash = TokE.is(AsmToken::Hash);
5247
5248 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5249 return MatchOperand_NoMatch;
5250
5251 int64_t Pattern;
5252 if (IsHash) {
5253 Parser.Lex(); // Eat hash
5254
5255 // Parse the immediate operand.
5256 const MCExpr *ImmVal;
5257 SS = getLoc();
5258 if (Parser.parseExpression(ImmVal))
5259 return MatchOperand_ParseFail;
5260
5261 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5262 if (!MCE)
5263 return MatchOperand_ParseFail;
5264
5265 Pattern = MCE->getValue();
5266 } else {
5267 // Parse the pattern
5268 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5269 if (!Pat)
5270 return MatchOperand_NoMatch;
5271
5272 Parser.Lex();
5273 Pattern = Pat->Encoding;
5274 assert(Pattern >= 0 && Pattern < 32);
5275 }
5276
5277 Operands.push_back(
5278 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5279 SS, getLoc(), getContext()));
5280
5281 return MatchOperand_Success;
5282}