blob: 37c27fe67ebf4cb573d2f9c6928932215e61ea6b [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 ||
Sjoerd Meijer173b7f02018-07-03 12:09:20 +0000925 SysReg.PStateField == AArch64PState::DIT ||
Oliver Stannard911ea202015-11-26 15:32:30 +0000926 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000927 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000928
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000929 bool isSystemPStateFieldWithImm0_15() const {
930 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000931 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000932 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000933
Florian Hahnc4422242017-11-07 13:07:50 +0000934 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000935 return Kind == k_Register;
936 }
937
938 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000939 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
940 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000941
Florian Hahnc4422242017-11-07 13:07:50 +0000942 bool isNeonVectorReg() const {
943 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
944 }
945
946 bool isNeonVectorRegLo() const {
947 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000948 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
949 Reg.RegNum);
950 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000951
Sander de Smalencd6be962017-12-20 11:02:42 +0000952 template <unsigned Class> bool isSVEVectorReg() const {
953 RegKind RK;
954 switch (Class) {
955 case AArch64::ZPRRegClassID:
956 RK = RegKind::SVEDataVector;
957 break;
958 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000959 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000960 RK = RegKind::SVEPredicateVector;
961 break;
962 default:
963 llvm_unreachable("Unsupport register class");
964 }
965
966 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000967 AArch64MCRegisterClasses[Class].contains(getReg());
968 }
969
Sander de Smalenfd54a782018-06-04 07:07:35 +0000970 template <unsigned Class> bool isFPRasZPR() const {
971 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
972 AArch64MCRegisterClasses[Class].contains(getReg());
973 }
974
Sander de Smalencd6be962017-12-20 11:02:42 +0000975 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +0000976 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
977 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
978 return DiagnosticPredicateTy::NoMatch;
979
980 if (isSVEVectorReg<Class>() &&
981 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
982 return DiagnosticPredicateTy::Match;
983
984 return DiagnosticPredicateTy::NearMatch;
985 }
986
987 template <int ElementWidth, unsigned Class>
988 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
989 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
990 return DiagnosticPredicateTy::NoMatch;
991
992 if (isSVEVectorReg<Class>() &&
993 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
994 return DiagnosticPredicateTy::Match;
995
996 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +0000997 }
998
Sander de Smaleneb896b12018-04-25 09:26:47 +0000999 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +00001000 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
1001 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +00001002 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
1003 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
1004 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001005 return DiagnosticPredicateTy::NoMatch;
1006
Sander de Smalen5861c262018-04-30 07:24:38 +00001007 // Give a more specific diagnostic when the user has explicitly typed in
1008 // a shift-amount that does not match what is expected, but for which
1009 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
1010 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
1011 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
1012 ShiftExtendTy == AArch64_AM::SXTW) &&
1013 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
1014 return DiagnosticPredicateTy::NoMatch;
1015
1016 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001017 return DiagnosticPredicateTy::Match;
1018
1019 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +00001020 }
1021
Tim Northover3b0846e2014-05-24 12:50:23 +00001022 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001023 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001024 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
1025 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001026
Sander de Smalen0325e302018-07-02 07:34:52 +00001027 bool isGPR64as32() const {
1028 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1029 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(Reg.RegNum);
1030 }
1031
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001032 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001033 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001034 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
1035 Reg.RegNum);
1036 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001037
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001038 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001039 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001040 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1041 Reg.RegNum);
1042 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001043
Sam Parker5f934642017-08-31 09:27:04 +00001044 template<int64_t Angle, int64_t Remainder>
1045 bool isComplexRotation() const {
1046 if (!isImm()) return false;
1047
1048 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1049 if (!CE) return false;
1050 uint64_t Value = CE->getValue();
1051
1052 return (Value % Angle == Remainder && Value <= 270);
1053 }
1054
Sander de Smalen149916d2018-04-20 07:24:20 +00001055 template <unsigned RegClassID> bool isGPR64() const {
1056 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1057 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1058 }
1059
1060 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001061 DiagnosticPredicate isGPR64WithShiftExtend() const {
1062 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1063 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001064
Sander de Smalenfe17a782018-04-26 12:54:42 +00001065 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1066 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1067 return DiagnosticPredicateTy::Match;
1068 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001069 }
1070
Tim Northover3b0846e2014-05-24 12:50:23 +00001071 /// Is this a vector list with the type implicit (presumably attached to the
1072 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001073 template <RegKind VectorKind, unsigned NumRegs>
1074 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001075 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001076 VectorList.NumElements == 0 &&
1077 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001078 }
1079
Sander de Smalen650234b2018-04-12 11:40:52 +00001080 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1081 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001082 bool isTypedVectorList() const {
1083 if (Kind != k_VectorList)
1084 return false;
1085 if (VectorList.Count != NumRegs)
1086 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001087 if (VectorList.RegisterKind != VectorKind)
1088 return false;
1089 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001090 return false;
1091 return VectorList.NumElements == NumElements;
1092 }
1093
Sander de Smalenc33d6682018-06-04 06:40:55 +00001094 template <int Min, int Max>
1095 DiagnosticPredicate isVectorIndex() const {
1096 if (Kind != k_VectorIndex)
1097 return DiagnosticPredicateTy::NoMatch;
1098 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1099 return DiagnosticPredicateTy::Match;
1100 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001101 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001102
Tim Northover3b0846e2014-05-24 12:50:23 +00001103 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001104
Tim Northover3b0846e2014-05-24 12:50:23 +00001105 bool isTokenEqual(StringRef Str) const {
1106 return Kind == k_Token && getToken() == Str;
1107 }
1108 bool isSysCR() const { return Kind == k_SysCR; }
1109 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001110 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001111 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1112 bool isShifter() const {
1113 if (!isShiftExtend())
1114 return false;
1115
1116 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1117 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1118 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1119 ST == AArch64_AM::MSL);
1120 }
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001121
1122 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1123 if (Kind != k_FPImm)
1124 return DiagnosticPredicateTy::NoMatch;
1125
1126 if (getFPImmIsExact()) {
1127 // Lookup the immediate from table of supported immediates.
1128 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1129 assert(Desc && "Unknown enum value");
1130
1131 // Calculate its FP value.
1132 APFloat RealVal(APFloat::IEEEdouble());
1133 if (RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero) !=
1134 APFloat::opOK)
1135 llvm_unreachable("FP immediate is not exact");
1136
1137 if (getFPImm().bitwiseIsEqual(RealVal))
1138 return DiagnosticPredicateTy::Match;
1139 }
1140
1141 return DiagnosticPredicateTy::NearMatch;
1142 }
1143
1144 template <unsigned ImmA, unsigned ImmB>
1145 DiagnosticPredicate isExactFPImm() const {
1146 DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1147 if ((Res = isExactFPImm<ImmA>()))
1148 return DiagnosticPredicateTy::Match;
1149 if ((Res = isExactFPImm<ImmB>()))
1150 return DiagnosticPredicateTy::Match;
1151 return Res;
1152 }
1153
Tim Northover3b0846e2014-05-24 12:50:23 +00001154 bool isExtend() const {
1155 if (!isShiftExtend())
1156 return false;
1157
1158 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1159 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1160 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1161 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1162 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1163 ET == AArch64_AM::LSL) &&
1164 getShiftExtendAmount() <= 4;
1165 }
1166
1167 bool isExtend64() const {
1168 if (!isExtend())
1169 return false;
1170 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1171 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1172 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1173 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001174
Tim Northover3b0846e2014-05-24 12:50:23 +00001175 bool isExtendLSL64() const {
1176 if (!isExtend())
1177 return false;
1178 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1179 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1180 ET == AArch64_AM::LSL) &&
1181 getShiftExtendAmount() <= 4;
1182 }
1183
1184 template<int Width> bool isMemXExtend() const {
1185 if (!isExtend())
1186 return false;
1187 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1188 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1189 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1190 getShiftExtendAmount() == 0);
1191 }
1192
1193 template<int Width> bool isMemWExtend() const {
1194 if (!isExtend())
1195 return false;
1196 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1197 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1198 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1199 getShiftExtendAmount() == 0);
1200 }
1201
1202 template <unsigned width>
1203 bool isArithmeticShifter() const {
1204 if (!isShifter())
1205 return false;
1206
1207 // An arithmetic shifter is LSL, LSR, or ASR.
1208 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1209 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1210 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1211 }
1212
1213 template <unsigned width>
1214 bool isLogicalShifter() const {
1215 if (!isShifter())
1216 return false;
1217
1218 // A logical shifter is LSL, LSR, ASR or ROR.
1219 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1220 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1221 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1222 getShiftExtendAmount() < width;
1223 }
1224
1225 bool isMovImm32Shifter() const {
1226 if (!isShifter())
1227 return false;
1228
1229 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1230 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1231 if (ST != AArch64_AM::LSL)
1232 return false;
1233 uint64_t Val = getShiftExtendAmount();
1234 return (Val == 0 || Val == 16);
1235 }
1236
1237 bool isMovImm64Shifter() const {
1238 if (!isShifter())
1239 return false;
1240
1241 // A MOVi shifter is LSL of 0 or 16.
1242 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1243 if (ST != AArch64_AM::LSL)
1244 return false;
1245 uint64_t Val = getShiftExtendAmount();
1246 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1247 }
1248
1249 bool isLogicalVecShifter() const {
1250 if (!isShifter())
1251 return false;
1252
1253 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1254 unsigned Shift = getShiftExtendAmount();
1255 return getShiftExtendType() == AArch64_AM::LSL &&
1256 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1257 }
1258
1259 bool isLogicalVecHalfWordShifter() const {
1260 if (!isLogicalVecShifter())
1261 return false;
1262
1263 // A logical vector shifter is a left shift by 0 or 8.
1264 unsigned Shift = getShiftExtendAmount();
1265 return getShiftExtendType() == AArch64_AM::LSL &&
1266 (Shift == 0 || Shift == 8);
1267 }
1268
1269 bool isMoveVecShifter() const {
1270 if (!isShiftExtend())
1271 return false;
1272
1273 // A logical vector shifter is a left shift by 8 or 16.
1274 unsigned Shift = getShiftExtendAmount();
1275 return getShiftExtendType() == AArch64_AM::MSL &&
1276 (Shift == 8 || Shift == 16);
1277 }
1278
1279 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1280 // to LDUR/STUR when the offset is not legal for the former but is for
1281 // the latter. As such, in addition to checking for being a legal unscaled
1282 // address, also check that it is not a legal scaled address. This avoids
1283 // ambiguity in the matcher.
1284 template<int Width>
1285 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001286 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001287 }
1288
1289 bool isAdrpLabel() const {
1290 // Validation was handled during parsing, so we just sanity check that
1291 // something didn't go haywire.
1292 if (!isImm())
1293 return false;
1294
1295 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1296 int64_t Val = CE->getValue();
1297 int64_t Min = - (4096 * (1LL << (21 - 1)));
1298 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1299 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1300 }
1301
1302 return true;
1303 }
1304
1305 bool isAdrLabel() const {
1306 // Validation was handled during parsing, so we just sanity check that
1307 // something didn't go haywire.
1308 if (!isImm())
1309 return false;
1310
1311 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1312 int64_t Val = CE->getValue();
1313 int64_t Min = - (1LL << (21 - 1));
1314 int64_t Max = ((1LL << (21 - 1)) - 1);
1315 return Val >= Min && Val <= Max;
1316 }
1317
1318 return true;
1319 }
1320
1321 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1322 // Add as immediates when possible. Null MCExpr = 0.
1323 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001324 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001325 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001326 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001327 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001328 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001329 }
1330
1331 void addRegOperands(MCInst &Inst, unsigned N) const {
1332 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001333 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001334 }
1335
1336 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1337 assert(N == 1 && "Invalid number of operands!");
1338 assert(
1339 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1340
1341 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1342 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1343 RI->getEncodingValue(getReg()));
1344
Jim Grosbache9119e42015-05-13 18:37:00 +00001345 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001346 }
1347
Sander de Smalen0325e302018-07-02 07:34:52 +00001348 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1349 assert(N == 1 && "Invalid number of operands!");
1350 assert(
1351 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(getReg()));
1352
1353 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1354 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID).getRegister(
1355 RI->getEncodingValue(getReg()));
1356
1357 Inst.addOperand(MCOperand::createReg(Reg));
1358 }
1359
Sander de Smalenfd54a782018-06-04 07:07:35 +00001360 template <int Width>
1361 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1362 unsigned Base;
1363 switch (Width) {
1364 case 8: Base = AArch64::B0; break;
1365 case 16: Base = AArch64::H0; break;
1366 case 32: Base = AArch64::S0; break;
1367 case 64: Base = AArch64::D0; break;
1368 case 128: Base = AArch64::Q0; break;
1369 default:
1370 llvm_unreachable("Unsupported width");
1371 }
1372 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1373 }
1374
Tim Northover3b0846e2014-05-24 12:50:23 +00001375 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1376 assert(N == 1 && "Invalid number of operands!");
1377 assert(
1378 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001379 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001380 }
1381
1382 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1383 assert(N == 1 && "Invalid number of operands!");
1384 assert(
1385 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001386 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001387 }
1388
1389 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1390 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001391 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001392 }
1393
Sander de Smalen525e3222018-04-12 13:19:32 +00001394 enum VecListIndexType {
1395 VecListIdx_DReg = 0,
1396 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001397 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001398 };
1399
1400 template <VecListIndexType RegTy, unsigned NumRegs>
1401 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001402 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001403 static const unsigned FirstRegs[][5] = {
1404 /* DReg */ { AArch64::Q0,
1405 AArch64::D0, AArch64::D0_D1,
1406 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1407 /* QReg */ { AArch64::Q0,
1408 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001409 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1410 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001411 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001412 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001413 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001414
Sander de Smalen7a210db2018-04-16 10:46:18 +00001415 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1416 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001417
Sander de Smalen525e3222018-04-12 13:19:32 +00001418 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1419 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1420 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001421 }
1422
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001423 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001424 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001425 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001426 }
1427
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001428 template <unsigned ImmIs0, unsigned ImmIs1>
1429 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1430 assert(N == 1 && "Invalid number of operands!");
1431 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1432 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1433 }
1434
Tim Northover3b0846e2014-05-24 12:50:23 +00001435 void addImmOperands(MCInst &Inst, unsigned N) const {
1436 assert(N == 1 && "Invalid number of operands!");
1437 // If this is a pageoff symrefexpr with an addend, adjust the addend
1438 // to be only the page-offset portion. Otherwise, just add the expr
1439 // as-is.
1440 addExpr(Inst, getImm());
1441 }
1442
Sander de Smalen62770792018-05-25 09:47:52 +00001443 template <int Shift>
1444 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001445 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001446 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1447 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1448 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1449 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001450 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001451 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001452 } else {
1453 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001454 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001455 }
1456 }
1457
Sander de Smalen62770792018-05-25 09:47:52 +00001458 template <int Shift>
1459 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001460 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001461 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1462 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1463 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1464 } else
1465 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001466 }
1467
Tim Northover3b0846e2014-05-24 12:50:23 +00001468 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1469 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001470 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001471 }
1472
1473 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1474 assert(N == 1 && "Invalid number of operands!");
1475 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1476 if (!MCE)
1477 addExpr(Inst, getImm());
1478 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001479 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001480 }
1481
1482 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1483 addImmOperands(Inst, N);
1484 }
1485
1486 template<int Scale>
1487 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1488 assert(N == 1 && "Invalid number of operands!");
1489 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1490
1491 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001492 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001493 return;
1494 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001495 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001496 }
1497
Sander de Smalen5c625982018-04-13 12:56:14 +00001498 template <int Scale>
1499 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1500 assert(N == 1 && "Invalid number of operands!");
1501 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1502 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1503 }
1504
Sander de Smalena1c259c2018-01-29 13:05:38 +00001505 template <typename T>
1506 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001507 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001508 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001509 typename std::make_unsigned<T>::type Val = MCE->getValue();
1510 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001511 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001512 }
1513
Sander de Smalena1c259c2018-01-29 13:05:38 +00001514 template <typename T>
1515 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001516 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001517 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001518 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1519 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001520 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001521 }
1522
Tim Northover3b0846e2014-05-24 12:50:23 +00001523 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1524 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001525 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001526 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001527 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001528 }
1529
1530 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1531 // Branch operands don't encode the low bits, so shift them off
1532 // here. If it's a label, however, just put it on directly as there's
1533 // not enough information now to do anything.
1534 assert(N == 1 && "Invalid number of operands!");
1535 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1536 if (!MCE) {
1537 addExpr(Inst, getImm());
1538 return;
1539 }
1540 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001541 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001542 }
1543
1544 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1545 // Branch operands don't encode the low bits, so shift them off
1546 // here. If it's a label, however, just put it on directly as there's
1547 // not enough information now to do anything.
1548 assert(N == 1 && "Invalid number of operands!");
1549 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1550 if (!MCE) {
1551 addExpr(Inst, getImm());
1552 return;
1553 }
1554 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001555 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001556 }
1557
1558 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1559 // Branch operands don't encode the low bits, so shift them off
1560 // here. If it's a label, however, just put it on directly as there's
1561 // not enough information now to do anything.
1562 assert(N == 1 && "Invalid number of operands!");
1563 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1564 if (!MCE) {
1565 addExpr(Inst, getImm());
1566 return;
1567 }
1568 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001569 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001570 }
1571
1572 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1573 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001574 Inst.addOperand(MCOperand::createImm(
1575 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
Tim Northover3b0846e2014-05-24 12:50:23 +00001576 }
1577
1578 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1579 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001580 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001581 }
1582
1583 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1584 assert(N == 1 && "Invalid number of operands!");
1585
Jim Grosbache9119e42015-05-13 18:37:00 +00001586 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001587 }
1588
1589 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1590 assert(N == 1 && "Invalid number of operands!");
1591
Jim Grosbache9119e42015-05-13 18:37:00 +00001592 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001593 }
1594
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001595 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1596 assert(N == 1 && "Invalid number of operands!");
1597
1598 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1599 }
1600
1601 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001602 assert(N == 1 && "Invalid number of operands!");
1603
Jim Grosbache9119e42015-05-13 18:37:00 +00001604 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001605 }
1606
1607 void addSysCROperands(MCInst &Inst, unsigned N) const {
1608 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001609 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001610 }
1611
1612 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1613 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001614 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001615 }
1616
Oliver Stannarda34e4702015-12-01 10:48:51 +00001617 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1618 assert(N == 1 && "Invalid number of operands!");
1619 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1620 }
1621
Tim Northover3b0846e2014-05-24 12:50:23 +00001622 void addShifterOperands(MCInst &Inst, unsigned N) const {
1623 assert(N == 1 && "Invalid number of operands!");
1624 unsigned Imm =
1625 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001626 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001627 }
1628
1629 void addExtendOperands(MCInst &Inst, unsigned N) const {
1630 assert(N == 1 && "Invalid number of operands!");
1631 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1632 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1633 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001634 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001635 }
1636
1637 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1638 assert(N == 1 && "Invalid number of operands!");
1639 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1640 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1641 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001642 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001643 }
1644
1645 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1646 assert(N == 2 && "Invalid number of operands!");
1647 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1648 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001649 Inst.addOperand(MCOperand::createImm(IsSigned));
1650 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001651 }
1652
1653 // For 8-bit load/store instructions with a register offset, both the
1654 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1655 // they're disambiguated by whether the shift was explicit or implicit rather
1656 // than its size.
1657 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1658 assert(N == 2 && "Invalid number of operands!");
1659 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1660 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001661 Inst.addOperand(MCOperand::createImm(IsSigned));
1662 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001663 }
1664
1665 template<int Shift>
1666 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1667 assert(N == 1 && "Invalid number of operands!");
1668
1669 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1670 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001671 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001672 }
1673
1674 template<int Shift>
1675 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1676 assert(N == 1 && "Invalid number of operands!");
1677
1678 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1679 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001680 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001681 }
1682
Sam Parker5f934642017-08-31 09:27:04 +00001683 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1684 assert(N == 1 && "Invalid number of operands!");
1685 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1686 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1687 }
1688
1689 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1690 assert(N == 1 && "Invalid number of operands!");
1691 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1692 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1693 }
1694
Tim Northover3b0846e2014-05-24 12:50:23 +00001695 void print(raw_ostream &OS) const override;
1696
David Blaikie960ea3f2014-06-08 16:18:35 +00001697 static std::unique_ptr<AArch64Operand>
1698 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1699 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001700 Op->Tok.Data = Str.data();
1701 Op->Tok.Length = Str.size();
1702 Op->Tok.IsSuffix = IsSuffix;
1703 Op->StartLoc = S;
1704 Op->EndLoc = S;
1705 return Op;
1706 }
1707
David Blaikie960ea3f2014-06-08 16:18:35 +00001708 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001709 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
Sander de Smalen0325e302018-07-02 07:34:52 +00001710 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
Sander de Smalen149916d2018-04-20 07:24:20 +00001711 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1712 unsigned ShiftAmount = 0,
1713 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001714 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001715 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001716 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001717 Op->Reg.ElementWidth = 0;
Sander de Smalen0325e302018-07-02 07:34:52 +00001718 Op->Reg.EqualityTy = EqTy;
Sander de Smalen149916d2018-04-20 07:24:20 +00001719 Op->Reg.ShiftExtend.Type = ExtTy;
1720 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1721 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001722 Op->StartLoc = S;
1723 Op->EndLoc = E;
1724 return Op;
1725 }
1726
David Blaikie960ea3f2014-06-08 16:18:35 +00001727 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001728 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001729 SMLoc S, SMLoc E, MCContext &Ctx,
1730 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1731 unsigned ShiftAmount = 0,
1732 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001733 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1734 Kind == RegKind::SVEPredicateVector) &&
1735 "Invalid vector kind");
Sander de Smalen0325e302018-07-02 07:34:52 +00001736 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
Sander de Smalen149916d2018-04-20 07:24:20 +00001737 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001738 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001739 return Op;
1740 }
1741
1742 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001743 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001744 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1745 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001746 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001747 Op->VectorList.RegNum = RegNum;
1748 Op->VectorList.Count = Count;
1749 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001750 Op->VectorList.ElementWidth = ElementWidth;
1751 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001752 Op->StartLoc = S;
1753 Op->EndLoc = E;
1754 return Op;
1755 }
1756
David Blaikie960ea3f2014-06-08 16:18:35 +00001757 static std::unique_ptr<AArch64Operand>
1758 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1759 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001760 Op->VectorIndex.Val = Idx;
1761 Op->StartLoc = S;
1762 Op->EndLoc = E;
1763 return Op;
1764 }
1765
David Blaikie960ea3f2014-06-08 16:18:35 +00001766 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1767 SMLoc E, MCContext &Ctx) {
1768 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001769 Op->Imm.Val = Val;
1770 Op->StartLoc = S;
1771 Op->EndLoc = E;
1772 return Op;
1773 }
1774
David Blaikie960ea3f2014-06-08 16:18:35 +00001775 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1776 unsigned ShiftAmount,
1777 SMLoc S, SMLoc E,
1778 MCContext &Ctx) {
1779 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001780 Op->ShiftedImm .Val = Val;
1781 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1782 Op->StartLoc = S;
1783 Op->EndLoc = E;
1784 return Op;
1785 }
1786
David Blaikie960ea3f2014-06-08 16:18:35 +00001787 static std::unique_ptr<AArch64Operand>
1788 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1789 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001790 Op->CondCode.Code = Code;
1791 Op->StartLoc = S;
1792 Op->EndLoc = E;
1793 return Op;
1794 }
1795
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001796 static std::unique_ptr<AArch64Operand>
1797 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001798 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001799 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
1800 Op->FPImm.IsExact = IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +00001801 Op->StartLoc = S;
1802 Op->EndLoc = S;
1803 return Op;
1804 }
1805
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001806 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1807 StringRef Str,
1808 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001809 MCContext &Ctx) {
1810 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001811 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001812 Op->Barrier.Data = Str.data();
1813 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001814 Op->StartLoc = S;
1815 Op->EndLoc = S;
1816 return Op;
1817 }
1818
Tim Northover7cd58932015-01-22 17:23:04 +00001819 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1820 uint32_t MRSReg,
1821 uint32_t MSRReg,
1822 uint32_t PStateField,
1823 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001824 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001825 Op->SysReg.Data = Str.data();
1826 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001827 Op->SysReg.MRSReg = MRSReg;
1828 Op->SysReg.MSRReg = MSRReg;
1829 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001830 Op->StartLoc = S;
1831 Op->EndLoc = S;
1832 return Op;
1833 }
1834
David Blaikie960ea3f2014-06-08 16:18:35 +00001835 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1836 SMLoc E, MCContext &Ctx) {
1837 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001838 Op->SysCRImm.Val = Val;
1839 Op->StartLoc = S;
1840 Op->EndLoc = E;
1841 return Op;
1842 }
1843
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001844 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1845 StringRef Str,
1846 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001847 MCContext &Ctx) {
1848 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001849 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001850 Op->Barrier.Data = Str.data();
1851 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001852 Op->StartLoc = S;
1853 Op->EndLoc = S;
1854 return Op;
1855 }
1856
Oliver Stannarda34e4702015-12-01 10:48:51 +00001857 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1858 StringRef Str,
1859 SMLoc S,
1860 MCContext &Ctx) {
1861 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1862 Op->PSBHint.Val = Val;
1863 Op->PSBHint.Data = Str.data();
1864 Op->PSBHint.Length = Str.size();
1865 Op->StartLoc = S;
1866 Op->EndLoc = S;
1867 return Op;
1868 }
1869
David Blaikie960ea3f2014-06-08 16:18:35 +00001870 static std::unique_ptr<AArch64Operand>
1871 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1872 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1873 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001874 Op->ShiftExtend.Type = ShOp;
1875 Op->ShiftExtend.Amount = Val;
1876 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1877 Op->StartLoc = S;
1878 Op->EndLoc = E;
1879 return Op;
1880 }
1881};
1882
1883} // end anonymous namespace.
1884
1885void AArch64Operand::print(raw_ostream &OS) const {
1886 switch (Kind) {
1887 case k_FPImm:
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001888 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
1889 if (!getFPImmIsExact())
1890 OS << " (inexact)";
1891 OS << ">";
Tim Northover3b0846e2014-05-24 12:50:23 +00001892 break;
1893 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001894 StringRef Name = getBarrierName();
1895 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001896 OS << "<barrier " << Name << ">";
1897 else
1898 OS << "<barrier invalid #" << getBarrier() << ">";
1899 break;
1900 }
1901 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001902 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001903 break;
1904 case k_ShiftedImm: {
1905 unsigned Shift = getShiftedImmShift();
1906 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001907 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001908 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1909 break;
1910 }
1911 case k_CondCode:
1912 OS << "<condcode " << getCondCode() << ">";
1913 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001914 case k_VectorList: {
1915 OS << "<vectorlist ";
1916 unsigned Reg = getVectorListStart();
1917 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1918 OS << Reg + i << " ";
1919 OS << ">";
1920 break;
1921 }
1922 case k_VectorIndex:
1923 OS << "<vectorindex " << getVectorIndex() << ">";
1924 break;
1925 case k_SysReg:
1926 OS << "<sysreg: " << getSysReg() << '>';
1927 break;
1928 case k_Token:
1929 OS << "'" << getToken() << "'";
1930 break;
1931 case k_SysCR:
1932 OS << "c" << getSysCR();
1933 break;
1934 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001935 StringRef Name = getPrefetchName();
1936 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001937 OS << "<prfop " << Name << ">";
1938 else
1939 OS << "<prfop invalid #" << getPrefetch() << ">";
1940 break;
1941 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001942 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001943 OS << getPSBHintName();
1944 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00001945 case k_Register:
1946 OS << "<register " << getReg() << ">";
1947 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
1948 break;
1949 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001950 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001951 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1952 << getShiftExtendAmount();
1953 if (!hasShiftExtendAmount())
1954 OS << "<imp>";
1955 OS << '>';
1956 break;
1957 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001958}
1959
1960/// @name Auto-generated Match Functions
1961/// {
1962
1963static unsigned MatchRegisterName(StringRef Name);
1964
1965/// }
1966
Florian Hahnc4422242017-11-07 13:07:50 +00001967static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001968 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001969 .Case("v0", AArch64::Q0)
1970 .Case("v1", AArch64::Q1)
1971 .Case("v2", AArch64::Q2)
1972 .Case("v3", AArch64::Q3)
1973 .Case("v4", AArch64::Q4)
1974 .Case("v5", AArch64::Q5)
1975 .Case("v6", AArch64::Q6)
1976 .Case("v7", AArch64::Q7)
1977 .Case("v8", AArch64::Q8)
1978 .Case("v9", AArch64::Q9)
1979 .Case("v10", AArch64::Q10)
1980 .Case("v11", AArch64::Q11)
1981 .Case("v12", AArch64::Q12)
1982 .Case("v13", AArch64::Q13)
1983 .Case("v14", AArch64::Q14)
1984 .Case("v15", AArch64::Q15)
1985 .Case("v16", AArch64::Q16)
1986 .Case("v17", AArch64::Q17)
1987 .Case("v18", AArch64::Q18)
1988 .Case("v19", AArch64::Q19)
1989 .Case("v20", AArch64::Q20)
1990 .Case("v21", AArch64::Q21)
1991 .Case("v22", AArch64::Q22)
1992 .Case("v23", AArch64::Q23)
1993 .Case("v24", AArch64::Q24)
1994 .Case("v25", AArch64::Q25)
1995 .Case("v26", AArch64::Q26)
1996 .Case("v27", AArch64::Q27)
1997 .Case("v28", AArch64::Q28)
1998 .Case("v29", AArch64::Q29)
1999 .Case("v30", AArch64::Q30)
2000 .Case("v31", AArch64::Q31)
2001 .Default(0);
2002}
2003
Sander de Smalen73937b72018-04-11 07:36:10 +00002004/// Returns an optional pair of (#elements, element-width) if Suffix
2005/// is a valid vector kind. Where the number of elements in a vector
2006/// or the vector width is implicit or explicitly unknown (but still a
2007/// valid suffix kind), 0 is used.
2008static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2009 RegKind VectorKind) {
2010 std::pair<int, int> Res = {-1, -1};
2011
2012 switch (VectorKind) {
2013 case RegKind::NeonVector:
2014 Res =
2015 StringSwitch<std::pair<int, int>>(Suffix.lower())
2016 .Case("", {0, 0})
2017 .Case(".1d", {1, 64})
2018 .Case(".1q", {1, 128})
2019 // '.2h' needed for fp16 scalar pairwise reductions
2020 .Case(".2h", {2, 16})
2021 .Case(".2s", {2, 32})
2022 .Case(".2d", {2, 64})
2023 // '.4b' is another special case for the ARMv8.2a dot product
2024 // operand
2025 .Case(".4b", {4, 8})
2026 .Case(".4h", {4, 16})
2027 .Case(".4s", {4, 32})
2028 .Case(".8b", {8, 8})
2029 .Case(".8h", {8, 16})
2030 .Case(".16b", {16, 8})
2031 // Accept the width neutral ones, too, for verbose syntax. If those
2032 // aren't used in the right places, the token operand won't match so
2033 // all will work out.
2034 .Case(".b", {0, 8})
2035 .Case(".h", {0, 16})
2036 .Case(".s", {0, 32})
2037 .Case(".d", {0, 64})
2038 .Default({-1, -1});
2039 break;
2040 case RegKind::SVEPredicateVector:
2041 case RegKind::SVEDataVector:
2042 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2043 .Case("", {0, 0})
2044 .Case(".b", {0, 8})
2045 .Case(".h", {0, 16})
2046 .Case(".s", {0, 32})
2047 .Case(".d", {0, 64})
2048 .Case(".q", {0, 128})
2049 .Default({-1, -1});
2050 break;
2051 default:
2052 llvm_unreachable("Unsupported RegKind");
2053 }
2054
2055 if (Res == std::make_pair(-1, -1))
2056 return Optional<std::pair<int, int>>();
2057
2058 return Optional<std::pair<int, int>>(Res);
2059}
2060
2061static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2062 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002063}
2064
Florian Hahn91f11e52017-11-07 16:45:48 +00002065static unsigned matchSVEDataVectorRegName(StringRef Name) {
2066 return StringSwitch<unsigned>(Name.lower())
2067 .Case("z0", AArch64::Z0)
2068 .Case("z1", AArch64::Z1)
2069 .Case("z2", AArch64::Z2)
2070 .Case("z3", AArch64::Z3)
2071 .Case("z4", AArch64::Z4)
2072 .Case("z5", AArch64::Z5)
2073 .Case("z6", AArch64::Z6)
2074 .Case("z7", AArch64::Z7)
2075 .Case("z8", AArch64::Z8)
2076 .Case("z9", AArch64::Z9)
2077 .Case("z10", AArch64::Z10)
2078 .Case("z11", AArch64::Z11)
2079 .Case("z12", AArch64::Z12)
2080 .Case("z13", AArch64::Z13)
2081 .Case("z14", AArch64::Z14)
2082 .Case("z15", AArch64::Z15)
2083 .Case("z16", AArch64::Z16)
2084 .Case("z17", AArch64::Z17)
2085 .Case("z18", AArch64::Z18)
2086 .Case("z19", AArch64::Z19)
2087 .Case("z20", AArch64::Z20)
2088 .Case("z21", AArch64::Z21)
2089 .Case("z22", AArch64::Z22)
2090 .Case("z23", AArch64::Z23)
2091 .Case("z24", AArch64::Z24)
2092 .Case("z25", AArch64::Z25)
2093 .Case("z26", AArch64::Z26)
2094 .Case("z27", AArch64::Z27)
2095 .Case("z28", AArch64::Z28)
2096 .Case("z29", AArch64::Z29)
2097 .Case("z30", AArch64::Z30)
2098 .Case("z31", AArch64::Z31)
2099 .Default(0);
2100}
2101
Sander de Smalencd6be962017-12-20 11:02:42 +00002102static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2103 return StringSwitch<unsigned>(Name.lower())
2104 .Case("p0", AArch64::P0)
2105 .Case("p1", AArch64::P1)
2106 .Case("p2", AArch64::P2)
2107 .Case("p3", AArch64::P3)
2108 .Case("p4", AArch64::P4)
2109 .Case("p5", AArch64::P5)
2110 .Case("p6", AArch64::P6)
2111 .Case("p7", AArch64::P7)
2112 .Case("p8", AArch64::P8)
2113 .Case("p9", AArch64::P9)
2114 .Case("p10", AArch64::P10)
2115 .Case("p11", AArch64::P11)
2116 .Case("p12", AArch64::P12)
2117 .Case("p13", AArch64::P13)
2118 .Case("p14", AArch64::P14)
2119 .Case("p15", AArch64::P15)
2120 .Default(0);
2121}
2122
Tim Northover3b0846e2014-05-24 12:50:23 +00002123bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2124 SMLoc &EndLoc) {
2125 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002126 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002127 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002128 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002129}
2130
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002131// Matches a register name or register alias previously defined by '.req'
2132unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002133 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002134 unsigned RegNum = 0;
2135 if ((RegNum = matchSVEDataVectorRegName(Name)))
2136 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2137
Sander de Smalencd6be962017-12-20 11:02:42 +00002138 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2139 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2140
Sander de Smalenc067c302017-12-20 09:45:45 +00002141 if ((RegNum = MatchNeonVectorRegName(Name)))
2142 return Kind == RegKind::NeonVector ? RegNum : 0;
2143
2144 // The parsed register must be of RegKind Scalar
2145 if ((RegNum = MatchRegisterName(Name)))
2146 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002147
Florian Hahnc4422242017-11-07 13:07:50 +00002148 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002149 // Handle a few common aliases of registers.
2150 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2151 .Case("fp", AArch64::FP)
2152 .Case("lr", AArch64::LR)
2153 .Case("x31", AArch64::XZR)
2154 .Case("w31", AArch64::WZR)
2155 .Default(0))
2156 return Kind == RegKind::Scalar ? RegNum : 0;
2157
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002158 // Check for aliases registered via .req. Canonicalize to lower case.
2159 // That's more consistent since register names are case insensitive, and
2160 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2161 auto Entry = RegisterReqs.find(Name.lower());
2162 if (Entry == RegisterReqs.end())
2163 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002164
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002165 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002166 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002167 RegNum = Entry->getValue().second;
2168 }
2169 return RegNum;
2170}
2171
Sander de Smalen50d87022018-04-19 07:35:08 +00002172/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002173/// Identifier when called, and if it is a register name the token is eaten and
2174/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002175OperandMatchResultTy
2176AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002177 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002178 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002179 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002180 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002181
2182 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002183 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2184 if (Reg == 0)
2185 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002186
Sander de Smalen50d87022018-04-19 07:35:08 +00002187 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002188 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002189 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002190}
2191
Tim Northover3b0846e2014-05-24 12:50:23 +00002192/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002193OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002194AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002195 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002196 SMLoc S = getLoc();
2197
2198 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2199 Error(S, "Expected cN operand where 0 <= N <= 15");
2200 return MatchOperand_ParseFail;
2201 }
2202
2203 StringRef Tok = Parser.getTok().getIdentifier();
2204 if (Tok[0] != 'c' && Tok[0] != 'C') {
2205 Error(S, "Expected cN operand where 0 <= N <= 15");
2206 return MatchOperand_ParseFail;
2207 }
2208
2209 uint32_t CRNum;
2210 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2211 if (BadNum || CRNum > 15) {
2212 Error(S, "Expected cN operand where 0 <= N <= 15");
2213 return MatchOperand_ParseFail;
2214 }
2215
2216 Parser.Lex(); // Eat identifier token.
2217 Operands.push_back(
2218 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2219 return MatchOperand_Success;
2220}
2221
2222/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002223template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002224OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002225AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002226 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002227 SMLoc S = getLoc();
2228 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002229
2230 auto LookupByName = [](StringRef N) {
2231 if (IsSVEPrefetch) {
2232 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2233 return Optional<unsigned>(Res->Encoding);
2234 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2235 return Optional<unsigned>(Res->Encoding);
2236 return Optional<unsigned>();
2237 };
2238
2239 auto LookupByEncoding = [](unsigned E) {
2240 if (IsSVEPrefetch) {
2241 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2242 return Optional<StringRef>(Res->Name);
2243 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2244 return Optional<StringRef>(Res->Name);
2245 return Optional<StringRef>();
2246 };
2247 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2248
Tim Northover3b0846e2014-05-24 12:50:23 +00002249 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002250 // Eat optional hash.
2251 if (parseOptionalToken(AsmToken::Hash) ||
2252 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002253 const MCExpr *ImmVal;
2254 if (getParser().parseExpression(ImmVal))
2255 return MatchOperand_ParseFail;
2256
2257 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2258 if (!MCE) {
2259 TokError("immediate value expected for prefetch operand");
2260 return MatchOperand_ParseFail;
2261 }
2262 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002263 if (prfop > MaxVal) {
2264 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2265 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002266 return MatchOperand_ParseFail;
2267 }
2268
Sander de Smalen93380372018-05-14 11:54:41 +00002269 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002270 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002271 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002272 return MatchOperand_Success;
2273 }
2274
2275 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002276 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002277 return MatchOperand_ParseFail;
2278 }
2279
Sander de Smalen93380372018-05-14 11:54:41 +00002280 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002281 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002282 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002283 return MatchOperand_ParseFail;
2284 }
2285
2286 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002287 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002288 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002289 return MatchOperand_Success;
2290}
2291
Oliver Stannarda34e4702015-12-01 10:48:51 +00002292/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002293OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002294AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2295 MCAsmParser &Parser = getParser();
2296 SMLoc S = getLoc();
2297 const AsmToken &Tok = Parser.getTok();
2298 if (Tok.isNot(AsmToken::Identifier)) {
2299 TokError("invalid operand for instruction");
2300 return MatchOperand_ParseFail;
2301 }
2302
Tim Northovere6ae6762016-07-05 21:23:04 +00002303 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2304 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002305 TokError("invalid operand for instruction");
2306 return MatchOperand_ParseFail;
2307 }
2308
2309 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002310 Operands.push_back(AArch64Operand::CreatePSBHint(
2311 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002312 return MatchOperand_Success;
2313}
2314
Tim Northover3b0846e2014-05-24 12:50:23 +00002315/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2316/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002317OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002318AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002319 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002320 SMLoc S = getLoc();
2321 const MCExpr *Expr;
2322
2323 if (Parser.getTok().is(AsmToken::Hash)) {
2324 Parser.Lex(); // Eat hash token.
2325 }
2326
2327 if (parseSymbolicImmVal(Expr))
2328 return MatchOperand_ParseFail;
2329
2330 AArch64MCExpr::VariantKind ELFRefKind;
2331 MCSymbolRefExpr::VariantKind DarwinRefKind;
2332 int64_t Addend;
2333 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2334 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2335 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2336 // No modifier was specified at all; this is the syntax for an ELF basic
2337 // ADRP relocation (unfortunately).
2338 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002339 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002340 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2341 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2342 Addend != 0) {
2343 Error(S, "gotpage label reference not allowed an addend");
2344 return MatchOperand_ParseFail;
2345 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2346 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2347 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2348 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2349 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2350 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2351 // The operand must be an @page or @gotpage qualified symbolref.
2352 Error(S, "page or gotpage label reference expected");
2353 return MatchOperand_ParseFail;
2354 }
2355 }
2356
2357 // We have either a label reference possibly with addend or an immediate. The
2358 // addend is a raw value here. The linker will adjust it to only reference the
2359 // page.
2360 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2361 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2362
2363 return MatchOperand_Success;
2364}
2365
2366/// tryParseAdrLabel - Parse and validate a source label for the ADR
2367/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002368OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002369AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2370 SMLoc S = getLoc();
2371 const MCExpr *Expr;
2372
Nirav Davee833c6c2016-11-08 18:31:04 +00002373 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002374 if (getParser().parseExpression(Expr))
2375 return MatchOperand_ParseFail;
2376
2377 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2378 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2379
2380 return MatchOperand_Success;
2381}
2382
2383/// tryParseFPImm - A floating point immediate expression operand.
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002384template<bool AddFPZeroAsLiteral>
Alex Bradbury58eba092016-11-01 16:32:05 +00002385OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002386AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002387 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002388 SMLoc S = getLoc();
2389
Nirav Davee833c6c2016-11-08 18:31:04 +00002390 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002391
2392 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002393 bool isNegative = parseOptionalToken(AsmToken::Minus);
2394
Tim Northover3b0846e2014-05-24 12:50:23 +00002395 const AsmToken &Tok = Parser.getTok();
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002396 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2397 if (!Hash)
2398 return MatchOperand_NoMatch;
2399 TokError("invalid floating point immediate");
2400 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002401 }
2402
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002403 // Parse hexadecimal representation.
2404 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2405 if (Tok.getIntVal() > 255 || isNegative) {
2406 TokError("encoded floating point value out of range");
2407 return MatchOperand_ParseFail;
2408 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002409
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002410 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2411 Operands.push_back(
2412 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2413 } else {
2414 // Parse FP representation.
2415 APFloat RealVal(APFloat::IEEEdouble());
2416 auto Status =
2417 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2418 if (isNegative)
2419 RealVal.changeSign();
2420
2421 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2422 Operands.push_back(
2423 AArch64Operand::CreateToken("#0", false, S, getContext()));
2424 Operands.push_back(
2425 AArch64Operand::CreateToken(".0", false, S, getContext()));
2426 } else
2427 Operands.push_back(AArch64Operand::CreateFPImm(
2428 RealVal, Status == APFloat::opOK, S, getContext()));
2429 }
2430
2431 Parser.Lex(); // Eat the token.
2432
2433 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002434}
2435
Sander de Smalen62770792018-05-25 09:47:52 +00002436/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2437/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002438OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002439AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002440 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002441 SMLoc S = getLoc();
2442
2443 if (Parser.getTok().is(AsmToken::Hash))
2444 Parser.Lex(); // Eat '#'
2445 else if (Parser.getTok().isNot(AsmToken::Integer))
2446 // Operand should start from # or should be integer, emit error otherwise.
2447 return MatchOperand_NoMatch;
2448
2449 const MCExpr *Imm;
2450 if (parseSymbolicImmVal(Imm))
2451 return MatchOperand_ParseFail;
2452 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002453 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002454 Operands.push_back(
2455 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002456 return MatchOperand_Success;
2457 }
2458
2459 // Eat ','
2460 Parser.Lex();
2461
2462 // The optional operand must be "lsl #N" where N is non-negative.
2463 if (!Parser.getTok().is(AsmToken::Identifier) ||
2464 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2465 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2466 return MatchOperand_ParseFail;
2467 }
2468
2469 // Eat 'lsl'
2470 Parser.Lex();
2471
Nirav Davee833c6c2016-11-08 18:31:04 +00002472 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002473
2474 if (Parser.getTok().isNot(AsmToken::Integer)) {
2475 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2476 return MatchOperand_ParseFail;
2477 }
2478
2479 int64_t ShiftAmount = Parser.getTok().getIntVal();
2480
2481 if (ShiftAmount < 0) {
2482 Error(Parser.getTok().getLoc(), "positive shift amount required");
2483 return MatchOperand_ParseFail;
2484 }
2485 Parser.Lex(); // Eat the number
2486
Sander de Smalen62770792018-05-25 09:47:52 +00002487 // Just in case the optional lsl #0 is used for immediates other than zero.
2488 if (ShiftAmount == 0 && Imm != 0) {
2489 SMLoc E = Parser.getTok().getLoc();
2490 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2491 return MatchOperand_Success;
2492 }
2493
Tim Northover3b0846e2014-05-24 12:50:23 +00002494 SMLoc E = Parser.getTok().getLoc();
2495 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2496 S, E, getContext()));
2497 return MatchOperand_Success;
2498}
2499
2500/// parseCondCodeString - Parse a Condition Code string.
2501AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2502 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2503 .Case("eq", AArch64CC::EQ)
2504 .Case("ne", AArch64CC::NE)
2505 .Case("cs", AArch64CC::HS)
2506 .Case("hs", AArch64CC::HS)
2507 .Case("cc", AArch64CC::LO)
2508 .Case("lo", AArch64CC::LO)
2509 .Case("mi", AArch64CC::MI)
2510 .Case("pl", AArch64CC::PL)
2511 .Case("vs", AArch64CC::VS)
2512 .Case("vc", AArch64CC::VC)
2513 .Case("hi", AArch64CC::HI)
2514 .Case("ls", AArch64CC::LS)
2515 .Case("ge", AArch64CC::GE)
2516 .Case("lt", AArch64CC::LT)
2517 .Case("gt", AArch64CC::GT)
2518 .Case("le", AArch64CC::LE)
2519 .Case("al", AArch64CC::AL)
2520 .Case("nv", AArch64CC::NV)
2521 .Default(AArch64CC::Invalid);
2522 return CC;
2523}
2524
2525/// parseCondCode - Parse a Condition Code operand.
2526bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2527 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002528 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002529 SMLoc S = getLoc();
2530 const AsmToken &Tok = Parser.getTok();
2531 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2532
2533 StringRef Cond = Tok.getString();
2534 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2535 if (CC == AArch64CC::Invalid)
2536 return TokError("invalid condition code");
2537 Parser.Lex(); // Eat identifier token.
2538
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002539 if (invertCondCode) {
2540 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2541 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002542 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002543 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002544
2545 Operands.push_back(
2546 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2547 return false;
2548}
2549
2550/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2551/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002552OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002553AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002554 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002555 const AsmToken &Tok = Parser.getTok();
2556 std::string LowerID = Tok.getString().lower();
2557 AArch64_AM::ShiftExtendType ShOp =
2558 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2559 .Case("lsl", AArch64_AM::LSL)
2560 .Case("lsr", AArch64_AM::LSR)
2561 .Case("asr", AArch64_AM::ASR)
2562 .Case("ror", AArch64_AM::ROR)
2563 .Case("msl", AArch64_AM::MSL)
2564 .Case("uxtb", AArch64_AM::UXTB)
2565 .Case("uxth", AArch64_AM::UXTH)
2566 .Case("uxtw", AArch64_AM::UXTW)
2567 .Case("uxtx", AArch64_AM::UXTX)
2568 .Case("sxtb", AArch64_AM::SXTB)
2569 .Case("sxth", AArch64_AM::SXTH)
2570 .Case("sxtw", AArch64_AM::SXTW)
2571 .Case("sxtx", AArch64_AM::SXTX)
2572 .Default(AArch64_AM::InvalidShiftExtend);
2573
2574 if (ShOp == AArch64_AM::InvalidShiftExtend)
2575 return MatchOperand_NoMatch;
2576
2577 SMLoc S = Tok.getLoc();
2578 Parser.Lex();
2579
Nirav Davee833c6c2016-11-08 18:31:04 +00002580 bool Hash = parseOptionalToken(AsmToken::Hash);
2581
Tim Northover3b0846e2014-05-24 12:50:23 +00002582 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2583 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2584 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2585 ShOp == AArch64_AM::MSL) {
2586 // We expect a number here.
2587 TokError("expected #imm after shift specifier");
2588 return MatchOperand_ParseFail;
2589 }
2590
Chad Rosier2ff37b82016-12-27 16:58:09 +00002591 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002592 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2593 Operands.push_back(
2594 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2595 return MatchOperand_Success;
2596 }
2597
Chad Rosier2ff37b82016-12-27 16:58:09 +00002598 // Make sure we do actually have a number, identifier or a parenthesized
2599 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002600 SMLoc E = Parser.getTok().getLoc();
2601 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002602 !Parser.getTok().is(AsmToken::LParen) &&
2603 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002604 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002605 return MatchOperand_ParseFail;
2606 }
2607
2608 const MCExpr *ImmVal;
2609 if (getParser().parseExpression(ImmVal))
2610 return MatchOperand_ParseFail;
2611
2612 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2613 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002614 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002615 return MatchOperand_ParseFail;
2616 }
2617
Jim Grosbach57fd2622014-09-23 22:16:02 +00002618 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002619 Operands.push_back(AArch64Operand::CreateShiftExtend(
2620 ShOp, MCE->getValue(), true, S, E, getContext()));
2621 return MatchOperand_Success;
2622}
2623
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002624static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2625 if (FBS[AArch64::HasV8_1aOps])
2626 Str += "ARMv8.1a";
2627 else if (FBS[AArch64::HasV8_2aOps])
2628 Str += "ARMv8.2a";
2629 else
2630 Str += "(unknown)";
2631}
2632
2633void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2634 SMLoc S) {
2635 const uint16_t Op2 = Encoding & 7;
2636 const uint16_t Cm = (Encoding & 0x78) >> 3;
2637 const uint16_t Cn = (Encoding & 0x780) >> 7;
2638 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2639
2640 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2641
2642 Operands.push_back(
2643 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2644 Operands.push_back(
2645 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2646 Operands.push_back(
2647 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2648 Expr = MCConstantExpr::create(Op2, getContext());
2649 Operands.push_back(
2650 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2651}
2652
Tim Northover3b0846e2014-05-24 12:50:23 +00002653/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2654/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2655bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2656 OperandVector &Operands) {
2657 if (Name.find('.') != StringRef::npos)
2658 return TokError("invalid operand");
2659
2660 Mnemonic = Name;
2661 Operands.push_back(
2662 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2663
Rafael Espindola961d4692014-11-11 05:18:41 +00002664 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002665 const AsmToken &Tok = Parser.getTok();
2666 StringRef Op = Tok.getString();
2667 SMLoc S = Tok.getLoc();
2668
Tim Northover3b0846e2014-05-24 12:50:23 +00002669 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002670 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2671 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002672 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002673 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2674 std::string Str("IC " + std::string(IC->Name) + " requires ");
2675 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2676 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002677 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002678 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002679 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002680 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2681 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002682 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002683 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2684 std::string Str("DC " + std::string(DC->Name) + " requires ");
2685 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2686 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002687 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002688 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002689 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002690 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2691 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002692 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002693 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2694 std::string Str("AT " + std::string(AT->Name) + " requires ");
2695 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2696 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002697 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002698 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002699 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002700 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2701 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002702 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002703 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2704 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2705 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2706 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002707 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002708 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002709 }
2710
Tim Northover3b0846e2014-05-24 12:50:23 +00002711 Parser.Lex(); // Eat operand.
2712
2713 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2714 bool HasRegister = false;
2715
2716 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002717 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002718 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2719 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002720 HasRegister = true;
2721 }
2722
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002723 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002724 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002725 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002726 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002727
Nirav Davee833c6c2016-11-08 18:31:04 +00002728 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2729 return true;
2730
Tim Northover3b0846e2014-05-24 12:50:23 +00002731 return false;
2732}
2733
Alex Bradbury58eba092016-11-01 16:32:05 +00002734OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002735AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002736 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002737 const AsmToken &Tok = Parser.getTok();
2738
2739 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002740 if (parseOptionalToken(AsmToken::Hash) ||
2741 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002742 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002743 const MCExpr *ImmVal;
2744 SMLoc ExprLoc = getLoc();
2745 if (getParser().parseExpression(ImmVal))
2746 return MatchOperand_ParseFail;
2747 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2748 if (!MCE) {
2749 Error(ExprLoc, "immediate value expected for barrier operand");
2750 return MatchOperand_ParseFail;
2751 }
2752 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2753 Error(ExprLoc, "barrier operand out of range");
2754 return MatchOperand_ParseFail;
2755 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002756 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2757 Operands.push_back(AArch64Operand::CreateBarrier(
2758 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002759 return MatchOperand_Success;
2760 }
2761
2762 if (Tok.isNot(AsmToken::Identifier)) {
2763 TokError("invalid operand for instruction");
2764 return MatchOperand_ParseFail;
2765 }
2766
Tim Northover3b0846e2014-05-24 12:50:23 +00002767 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002768 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2769 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002770 TokError("'sy' or #imm operand expected");
2771 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002772 } else if (!DB) {
2773 TokError("invalid barrier option name");
2774 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002775 }
2776
Tim Northovere6ae6762016-07-05 21:23:04 +00002777 Operands.push_back(AArch64Operand::CreateBarrier(
2778 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002779 Parser.Lex(); // Consume the option
2780
2781 return MatchOperand_Success;
2782}
2783
Alex Bradbury58eba092016-11-01 16:32:05 +00002784OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002785AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002786 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002787 const AsmToken &Tok = Parser.getTok();
2788
2789 if (Tok.isNot(AsmToken::Identifier))
2790 return MatchOperand_NoMatch;
2791
Tim Northovere6ae6762016-07-05 21:23:04 +00002792 int MRSReg, MSRReg;
2793 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2794 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2795 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2796 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2797 } else
2798 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002799
Tim Northovere6ae6762016-07-05 21:23:04 +00002800 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2801 unsigned PStateImm = -1;
2802 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2803 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002804
Tim Northovere6ae6762016-07-05 21:23:04 +00002805 Operands.push_back(
2806 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2807 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002808 Parser.Lex(); // Eat identifier
2809
2810 return MatchOperand_Success;
2811}
2812
Florian Hahnc4422242017-11-07 13:07:50 +00002813/// tryParseNeonVectorRegister - Parse a vector register operand.
2814bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002815 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002816 if (Parser.getTok().isNot(AsmToken::Identifier))
2817 return true;
2818
2819 SMLoc S = getLoc();
2820 // Check for a vector register specifier first.
2821 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002822 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002823 OperandMatchResultTy Res =
2824 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2825 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002826 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002827
2828 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2829 if (!KindRes)
2830 return true;
2831
2832 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002833 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002834 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2835 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002836
Tim Northover3b0846e2014-05-24 12:50:23 +00002837 // If there was an explicit qualifier, that goes on as a literal text
2838 // operand.
2839 if (!Kind.empty())
2840 Operands.push_back(
2841 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2842
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002843 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2844}
2845
2846OperandMatchResultTy
2847AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002848 SMLoc SIdx = getLoc();
2849 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002850 const MCExpr *ImmVal;
2851 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002852 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002853 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2854 if (!MCE) {
2855 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002856 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002857 }
2858
2859 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002860
Nirav Davee833c6c2016-11-08 18:31:04 +00002861 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002862 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002863
2864 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2865 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002866 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002867 }
2868
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002869 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002870}
2871
Sander de Smalen73937b72018-04-11 07:36:10 +00002872// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002873// optional kind specifier. If it is a register specifier, eat the token
2874// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002875OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002876AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002877 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002878 MCAsmParser &Parser = getParser();
2879 const AsmToken &Tok = Parser.getTok();
2880
Florian Hahn91f11e52017-11-07 16:45:48 +00002881 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002882 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002883
2884 StringRef Name = Tok.getString();
2885 // If there is a kind specifier, it's separated from the register name by
2886 // a '.'.
2887 size_t Start = 0, Next = Name.find('.');
2888 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002889 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002890
2891 if (RegNum) {
2892 if (Next != StringRef::npos) {
2893 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002894 if (!isValidVectorKind(Kind, MatchKind)) {
2895 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002896 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002897 }
2898 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002899 Parser.Lex(); // Eat the register token.
2900
2901 Reg = RegNum;
2902 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002903 }
2904
Sander de Smalen8e607342017-11-15 15:44:43 +00002905 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002906}
2907
Sander de Smalencd6be962017-12-20 11:02:42 +00002908/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2909OperandMatchResultTy
2910AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2911 // Check for a SVE predicate register specifier first.
2912 const SMLoc S = getLoc();
2913 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002914 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002915 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002916 if (Res != MatchOperand_Success)
2917 return Res;
2918
Sander de Smalen73937b72018-04-11 07:36:10 +00002919 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2920 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002921 return MatchOperand_NoMatch;
2922
Sander de Smalen73937b72018-04-11 07:36:10 +00002923 unsigned ElementWidth = KindRes->second;
2924 Operands.push_back(AArch64Operand::CreateVectorReg(
2925 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2926 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002927
Sander de Smalen7868e742018-01-09 11:17:06 +00002928 // Not all predicates are followed by a '/m' or '/z'.
2929 MCAsmParser &Parser = getParser();
2930 if (Parser.getTok().isNot(AsmToken::Slash))
2931 return MatchOperand_Success;
2932
2933 // But when they do they shouldn't have an element type suffix.
2934 if (!Kind.empty()) {
2935 Error(S, "not expecting size suffix");
2936 return MatchOperand_ParseFail;
2937 }
2938
2939 // Add a literal slash as operand
2940 Operands.push_back(
2941 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2942
2943 Parser.Lex(); // Eat the slash.
2944
2945 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002946 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002947 if (Pred != "z" && Pred != "m") {
2948 Error(getLoc(), "expecting 'm' or 'z' predication");
2949 return MatchOperand_ParseFail;
2950 }
2951
2952 // Add zero/merge token.
2953 const char *ZM = Pred == "z" ? "z" : "m";
2954 Operands.push_back(
2955 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2956
2957 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002958 return MatchOperand_Success;
2959}
2960
Sander de Smalen50d87022018-04-19 07:35:08 +00002961/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002962bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002963 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002964 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002965 return false;
2966
Sander de Smalen149916d2018-04-20 07:24:20 +00002967 // Otherwise try for a scalar register.
2968 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
2969 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002970
Sander de Smalen149916d2018-04-20 07:24:20 +00002971 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002972}
2973
2974bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002975 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002976 bool HasELFModifier = false;
2977 AArch64MCExpr::VariantKind RefKind;
2978
Nirav Davee833c6c2016-11-08 18:31:04 +00002979 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002980 HasELFModifier = true;
2981
Nirav Davee833c6c2016-11-08 18:31:04 +00002982 if (Parser.getTok().isNot(AsmToken::Identifier))
2983 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002984
2985 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2986 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2987 .Case("lo12", AArch64MCExpr::VK_LO12)
2988 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2989 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2990 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2991 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2992 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2993 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2994 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2995 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2996 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2997 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2998 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2999 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
3000 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3001 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3002 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3003 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3004 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3005 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3006 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3007 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3008 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3009 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3010 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3011 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3012 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3013 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3014 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3015 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3016 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3017 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3018 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3019 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3020 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3021 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003022 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3023 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00003024 .Default(AArch64MCExpr::VK_INVALID);
3025
Nirav Davee833c6c2016-11-08 18:31:04 +00003026 if (RefKind == AArch64MCExpr::VK_INVALID)
3027 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003028
3029 Parser.Lex(); // Eat identifier
3030
Nirav Davee833c6c2016-11-08 18:31:04 +00003031 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003032 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003033 }
3034
3035 if (getParser().parseExpression(ImmVal))
3036 return true;
3037
3038 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003039 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003040
3041 return false;
3042}
3043
Sander de Smalen650234b2018-04-12 11:40:52 +00003044template <RegKind VectorKind>
3045OperandMatchResultTy
3046AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3047 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003048 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003049 if (!Parser.getTok().is(AsmToken::LCurly))
3050 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003051
3052 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003053 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003054 bool NoMatchIsError) {
3055 auto RegTok = Parser.getTok();
3056 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3057 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003058 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003059 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003060 llvm_unreachable("Expected a valid vector kind");
3061 }
3062
Sander de Smalen650234b2018-04-12 11:40:52 +00003063 if (RegTok.isNot(AsmToken::Identifier) ||
3064 ParseRes == MatchOperand_ParseFail ||
3065 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3066 Error(Loc, "vector register expected");
3067 return MatchOperand_ParseFail;
3068 }
3069
3070 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003071 };
3072
Tim Northover3b0846e2014-05-24 12:50:23 +00003073 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003074 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003075 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003076
Tim Northover3b0846e2014-05-24 12:50:23 +00003077 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003078 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003079 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3080
3081 // Put back the original left bracket if there was no match, so that
3082 // different types of list-operands can be matched (e.g. SVE, Neon).
3083 if (ParseRes == MatchOperand_NoMatch)
3084 Parser.getLexer().UnLex(LCurly);
3085
3086 if (ParseRes != MatchOperand_Success)
3087 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003088
Tim Northover3b0846e2014-05-24 12:50:23 +00003089 int64_t PrevReg = FirstReg;
3090 unsigned Count = 1;
3091
Nirav Davee833c6c2016-11-08 18:31:04 +00003092 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003093 SMLoc Loc = getLoc();
3094 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003095
Sander de Smalen50d87022018-04-19 07:35:08 +00003096 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003097 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3098 if (ParseRes != MatchOperand_Success)
3099 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003100
Tim Northover3b0846e2014-05-24 12:50:23 +00003101 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003102 if (Kind != NextKind) {
3103 Error(Loc, "mismatched register size suffix");
3104 return MatchOperand_ParseFail;
3105 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003106
3107 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3108
3109 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003110 Error(Loc, "invalid number of vectors");
3111 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003112 }
3113
3114 Count += Space;
3115 }
3116 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003117 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003118 SMLoc Loc = getLoc();
3119 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003120 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003121 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3122 if (ParseRes != MatchOperand_Success)
3123 return ParseRes;
3124
Tim Northover3b0846e2014-05-24 12:50:23 +00003125 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003126 if (Kind != NextKind) {
3127 Error(Loc, "mismatched register size suffix");
3128 return MatchOperand_ParseFail;
3129 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003130
3131 // Registers must be incremental (with wraparound at 31)
3132 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003133 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3134 Error(Loc, "registers must be sequential");
3135 return MatchOperand_ParseFail;
3136 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003137
3138 PrevReg = Reg;
3139 ++Count;
3140 }
3141 }
3142
Nirav Davee833c6c2016-11-08 18:31:04 +00003143 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003144 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003145
Sander de Smalen650234b2018-04-12 11:40:52 +00003146 if (Count > 4) {
3147 Error(S, "invalid number of vectors");
3148 return MatchOperand_ParseFail;
3149 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003150
3151 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003152 unsigned ElementWidth = 0;
3153 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003154 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003155 std::tie(NumElements, ElementWidth) = *VK;
3156 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003157
3158 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003159 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3160 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003161
Sander de Smalen650234b2018-04-12 11:40:52 +00003162 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003163}
3164
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003165/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3166bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003167 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3168 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003169 return true;
3170
3171 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3172}
3173
Alex Bradbury58eba092016-11-01 16:32:05 +00003174OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003175AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003176 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003177
Sander de Smalen50d87022018-04-19 07:35:08 +00003178 unsigned RegNum;
3179 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3180 if (Res != MatchOperand_Success)
3181 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003182
Nirav Davee833c6c2016-11-08 18:31:04 +00003183 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003184 Operands.push_back(AArch64Operand::CreateReg(
3185 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003186 return MatchOperand_Success;
3187 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003188
Nirav Davee833c6c2016-11-08 18:31:04 +00003189 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003190
Sander de Smalen50d87022018-04-19 07:35:08 +00003191 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003192 Error(getLoc(), "index must be absent or #0");
3193 return MatchOperand_ParseFail;
3194 }
3195
3196 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003197 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003198 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3199 Error(getLoc(), "index must be absent or #0");
3200 return MatchOperand_ParseFail;
3201 }
3202
Sander de Smalen50d87022018-04-19 07:35:08 +00003203 Operands.push_back(AArch64Operand::CreateReg(
3204 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003205 return MatchOperand_Success;
3206}
3207
Sander de Smalen0325e302018-07-02 07:34:52 +00003208template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
Sander de Smalen149916d2018-04-20 07:24:20 +00003209OperandMatchResultTy
3210AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3211 SMLoc StartLoc = getLoc();
3212
3213 unsigned RegNum;
3214 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3215 if (Res != MatchOperand_Success)
3216 return Res;
3217
3218 // No shift/extend is the default.
3219 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3220 Operands.push_back(AArch64Operand::CreateReg(
Sander de Smalen0325e302018-07-02 07:34:52 +00003221 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
Sander de Smalen149916d2018-04-20 07:24:20 +00003222 return MatchOperand_Success;
3223 }
3224
3225 // Eat the comma
3226 getParser().Lex();
3227
3228 // Match the shift
3229 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3230 Res = tryParseOptionalShiftExtend(ExtOpnd);
3231 if (Res != MatchOperand_Success)
3232 return Res;
3233
3234 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
Sander de Smalen0325e302018-07-02 07:34:52 +00003235 Operands.push_back(AArch64Operand::CreateReg(
3236 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3237 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3238 Ext->hasShiftExtendAmount()));
Sander de Smalen149916d2018-04-20 07:24:20 +00003239
3240 return MatchOperand_Success;
3241}
3242
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003243bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
Sander de Smalen5c625982018-04-13 12:56:14 +00003244 MCAsmParser &Parser = getParser();
3245
3246 // Some SVE instructions have a decoration after the immediate, i.e.
3247 // "mul vl". We parse them here and add tokens, which must be present in the
3248 // asm string in the tablegen instruction.
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003249 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3250 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
Sander de Smalen5c625982018-04-13 12:56:14 +00003251 if (!Parser.getTok().getString().equals_lower("mul") ||
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003252 !(NextIsVL || NextIsHash))
Sander de Smalen5c625982018-04-13 12:56:14 +00003253 return true;
3254
Sander de Smalen5c625982018-04-13 12:56:14 +00003255 Operands.push_back(
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003256 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
Sander de Smalen5c625982018-04-13 12:56:14 +00003257 Parser.Lex(); // Eat the "mul"
3258
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003259 if (NextIsVL) {
3260 Operands.push_back(
3261 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3262 Parser.Lex(); // Eat the "vl"
3263 return false;
3264 }
Sander de Smalen5c625982018-04-13 12:56:14 +00003265
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003266 if (NextIsHash) {
3267 Parser.Lex(); // Eat the #
3268 SMLoc S = getLoc();
3269
3270 // Parse immediate operand.
3271 const MCExpr *ImmVal;
3272 if (!Parser.parseExpression(ImmVal))
3273 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3274 Operands.push_back(AArch64Operand::CreateImm(
3275 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3276 getContext()));
3277 return MatchOperand_Success;
3278 }
3279 }
3280
3281 return Error(getLoc(), "expected 'vl' or '#<imm>'");
Sander de Smalen5c625982018-04-13 12:56:14 +00003282}
3283
Tim Northover3b0846e2014-05-24 12:50:23 +00003284/// parseOperand - Parse a arm instruction operand. For now this parses the
3285/// operand regardless of the mnemonic.
3286bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3287 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003288 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003289
3290 OperandMatchResultTy ResTy =
3291 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3292
Tim Northover3b0846e2014-05-24 12:50:23 +00003293 // Check if the current operand has a custom associated parser, if so, try to
3294 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003295 if (ResTy == MatchOperand_Success)
3296 return false;
3297 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3298 // there was a match, but an error occurred, in which case, just return that
3299 // the operand parsing failed.
3300 if (ResTy == MatchOperand_ParseFail)
3301 return true;
3302
3303 // Nothing custom, so do general case parsing.
3304 SMLoc S, E;
3305 switch (getLexer().getKind()) {
3306 default: {
3307 SMLoc S = getLoc();
3308 const MCExpr *Expr;
3309 if (parseSymbolicImmVal(Expr))
3310 return Error(S, "invalid operand");
3311
3312 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3313 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3314 return false;
3315 }
3316 case AsmToken::LBrac: {
3317 SMLoc Loc = Parser.getTok().getLoc();
3318 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3319 getContext()));
3320 Parser.Lex(); // Eat '['
3321
3322 // There's no comma after a '[', so we can parse the next operand
3323 // immediately.
3324 return parseOperand(Operands, false, false);
3325 }
3326 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003327 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003328 case AsmToken::Identifier: {
3329 // If we're expecting a Condition Code operand, then just parse that.
3330 if (isCondCode)
3331 return parseCondCode(Operands, invertCondCode);
3332
3333 // If it's a register name, parse it.
3334 if (!parseRegister(Operands))
3335 return false;
3336
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003337 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3338 // by SVE instructions.
3339 if (!parseOptionalMulOperand(Operands))
Sander de Smalen5c625982018-04-13 12:56:14 +00003340 return false;
3341
Tim Northover3b0846e2014-05-24 12:50:23 +00003342 // This could be an optional "shift" or "extend" operand.
3343 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3344 // We can only continue if no tokens were eaten.
3345 if (GotShift != MatchOperand_NoMatch)
3346 return GotShift;
3347
3348 // This was not a register so parse other operands that start with an
3349 // identifier (like labels) as expressions and create them as immediates.
3350 const MCExpr *IdVal;
3351 S = getLoc();
3352 if (getParser().parseExpression(IdVal))
3353 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003354 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3355 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3356 return false;
3357 }
3358 case AsmToken::Integer:
3359 case AsmToken::Real:
3360 case AsmToken::Hash: {
3361 // #42 -> immediate.
3362 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003363
3364 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003365
3366 // Parse a negative sign
3367 bool isNegative = false;
3368 if (Parser.getTok().is(AsmToken::Minus)) {
3369 isNegative = true;
3370 // We need to consume this token only when we have a Real, otherwise
3371 // we let parseSymbolicImmVal take care of it
3372 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3373 Parser.Lex();
3374 }
3375
3376 // The only Real that should come through here is a literal #0.0 for
3377 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3378 // so convert the value.
3379 const AsmToken &Tok = Parser.getTok();
3380 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003381 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003382 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3383 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3384 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
Sander de Smalen8fcc3f52018-07-03 09:07:23 +00003385 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
Tim Northover3b0846e2014-05-24 12:50:23 +00003386 return TokError("unexpected floating point literal");
3387 else if (IntVal != 0 || isNegative)
3388 return TokError("expected floating-point constant #0.0");
3389 Parser.Lex(); // Eat the token.
3390
3391 Operands.push_back(
3392 AArch64Operand::CreateToken("#0", false, S, getContext()));
3393 Operands.push_back(
3394 AArch64Operand::CreateToken(".0", false, S, getContext()));
3395 return false;
3396 }
3397
3398 const MCExpr *ImmVal;
3399 if (parseSymbolicImmVal(ImmVal))
3400 return true;
3401
3402 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3403 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3404 return false;
3405 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003406 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003407 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003408 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003409 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003410 Parser.Lex(); // Eat '='
3411 const MCExpr *SubExprVal;
3412 if (getParser().parseExpression(SubExprVal))
3413 return true;
3414
David Peixottoae5ba762014-07-18 16:05:14 +00003415 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003416 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003417 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003418
3419 bool IsXReg =
3420 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3421 Operands[1]->getReg());
3422
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003423 MCContext& Ctx = getContext();
3424 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3425 // 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 +00003426 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003427 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3428 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3429 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3430 ShiftAmt += 16;
3431 Imm >>= 16;
3432 }
3433 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3434 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3435 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003436 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003437 if (ShiftAmt)
3438 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3439 ShiftAmt, true, S, E, Ctx));
3440 return false;
3441 }
David Peixottoae5ba762014-07-18 16:05:14 +00003442 APInt Simm = APInt(64, Imm << ShiftAmt);
3443 // check if the immediate is an unsigned or signed 32-bit int for W regs
3444 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3445 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003446 }
3447 // 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 +00003448 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003449 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003450 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3451 return false;
3452 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003453 }
3454}
3455
Sander de Smalen0325e302018-07-02 07:34:52 +00003456bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3457 const MCParsedAsmOperand &Op2) const {
3458 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3459 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3460 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3461 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3462 return MCTargetAsmParser::regsEqual(Op1, Op2);
3463
3464 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3465 "Testing equality of non-scalar registers not supported");
3466
3467 // Check if a registers match their sub/super register classes.
3468 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3469 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3470 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3471 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3472 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3473 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3474 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3475 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3476
3477 return false;
3478}
3479
Tim Northover3b0846e2014-05-24 12:50:23 +00003480/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3481/// operands.
3482bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3483 StringRef Name, SMLoc NameLoc,
3484 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003485 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003486 Name = StringSwitch<StringRef>(Name.lower())
3487 .Case("beq", "b.eq")
3488 .Case("bne", "b.ne")
3489 .Case("bhs", "b.hs")
3490 .Case("bcs", "b.cs")
3491 .Case("blo", "b.lo")
3492 .Case("bcc", "b.cc")
3493 .Case("bmi", "b.mi")
3494 .Case("bpl", "b.pl")
3495 .Case("bvs", "b.vs")
3496 .Case("bvc", "b.vc")
3497 .Case("bhi", "b.hi")
3498 .Case("bls", "b.ls")
3499 .Case("bge", "b.ge")
3500 .Case("blt", "b.lt")
3501 .Case("bgt", "b.gt")
3502 .Case("ble", "b.le")
3503 .Case("bal", "b.al")
3504 .Case("bnv", "b.nv")
3505 .Default(Name);
3506
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003507 // First check for the AArch64-specific .req directive.
3508 if (Parser.getTok().is(AsmToken::Identifier) &&
3509 Parser.getTok().getIdentifier() == ".req") {
3510 parseDirectiveReq(Name, NameLoc);
3511 // We always return 'error' for this, as we're done with this
3512 // statement and don't need to match the 'instruction."
3513 return true;
3514 }
3515
Tim Northover3b0846e2014-05-24 12:50:23 +00003516 // Create the leading tokens for the mnemonic, split by '.' characters.
3517 size_t Start = 0, Next = Name.find('.');
3518 StringRef Head = Name.slice(Start, Next);
3519
3520 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003521 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3522 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003523
3524 Operands.push_back(
3525 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3526 Mnemonic = Head;
3527
3528 // Handle condition codes for a branch mnemonic
3529 if (Head == "b" && Next != StringRef::npos) {
3530 Start = Next;
3531 Next = Name.find('.', Start + 1);
3532 Head = Name.slice(Start + 1, Next);
3533
3534 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3535 (Head.data() - Name.data()));
3536 AArch64CC::CondCode CC = parseCondCodeString(Head);
3537 if (CC == AArch64CC::Invalid)
3538 return Error(SuffixLoc, "invalid condition code");
3539 Operands.push_back(
3540 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3541 Operands.push_back(
3542 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3543 }
3544
3545 // Add the remaining tokens in the mnemonic.
3546 while (Next != StringRef::npos) {
3547 Start = Next;
3548 Next = Name.find('.', Start + 1);
3549 Head = Name.slice(Start, Next);
3550 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3551 (Head.data() - Name.data()) + 1);
3552 Operands.push_back(
3553 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3554 }
3555
3556 // Conditional compare instructions have a Condition Code operand, which needs
3557 // to be parsed and an immediate operand created.
3558 bool condCodeFourthOperand =
3559 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3560 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3561 Head == "csinc" || Head == "csinv" || Head == "csneg");
3562
3563 // These instructions are aliases to some of the conditional select
3564 // instructions. However, the condition code is inverted in the aliased
3565 // instruction.
3566 //
3567 // FIXME: Is this the correct way to handle these? Or should the parser
3568 // generate the aliased instructions directly?
3569 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3570 bool condCodeThirdOperand =
3571 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3572
3573 // Read the remaining operands.
3574 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3575 // Read the first operand.
3576 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003577 return true;
3578 }
3579
3580 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003581 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003582 // Parse and remember the operand.
3583 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3584 (N == 3 && condCodeThirdOperand) ||
3585 (N == 2 && condCodeSecondOperand),
3586 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003587 return true;
3588 }
3589
3590 // After successfully parsing some operands there are two special cases to
3591 // consider (i.e. notional operands not separated by commas). Both are due
3592 // to memory specifiers:
3593 // + An RBrac will end an address for load/store/prefetch
3594 // + An '!' will indicate a pre-indexed operation.
3595 //
3596 // It's someone else's responsibility to make sure these tokens are sane
3597 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003598
Nirav Davee833c6c2016-11-08 18:31:04 +00003599 SMLoc RLoc = Parser.getTok().getLoc();
3600 if (parseOptionalToken(AsmToken::RBrac))
3601 Operands.push_back(
3602 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3603 SMLoc ELoc = Parser.getTok().getLoc();
3604 if (parseOptionalToken(AsmToken::Exclaim))
3605 Operands.push_back(
3606 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003607
3608 ++N;
3609 }
3610 }
3611
Nirav Davee833c6c2016-11-08 18:31:04 +00003612 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3613 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003614
Tim Northover3b0846e2014-05-24 12:50:23 +00003615 return false;
3616}
3617
3618// FIXME: This entire function is a giant hack to provide us with decent
3619// operand range validation/diagnostics until TableGen/MC can be extended
3620// to support autogeneration of this kind of validation.
3621bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3622 SmallVectorImpl<SMLoc> &Loc) {
3623 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3624 // Check for indexed addressing modes w/ the base register being the
3625 // same as a destination/source register or pair load where
3626 // the Rt == Rt2. All of those are undefined behaviour.
3627 switch (Inst.getOpcode()) {
3628 case AArch64::LDPSWpre:
3629 case AArch64::LDPWpost:
3630 case AArch64::LDPWpre:
3631 case AArch64::LDPXpost:
3632 case AArch64::LDPXpre: {
3633 unsigned Rt = Inst.getOperand(1).getReg();
3634 unsigned Rt2 = Inst.getOperand(2).getReg();
3635 unsigned Rn = Inst.getOperand(3).getReg();
3636 if (RI->isSubRegisterEq(Rn, Rt))
3637 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3638 "is also a destination");
3639 if (RI->isSubRegisterEq(Rn, Rt2))
3640 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3641 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003642 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003643 }
3644 case AArch64::LDPDi:
3645 case AArch64::LDPQi:
3646 case AArch64::LDPSi:
3647 case AArch64::LDPSWi:
3648 case AArch64::LDPWi:
3649 case AArch64::LDPXi: {
3650 unsigned Rt = Inst.getOperand(0).getReg();
3651 unsigned Rt2 = Inst.getOperand(1).getReg();
3652 if (Rt == Rt2)
3653 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3654 break;
3655 }
3656 case AArch64::LDPDpost:
3657 case AArch64::LDPDpre:
3658 case AArch64::LDPQpost:
3659 case AArch64::LDPQpre:
3660 case AArch64::LDPSpost:
3661 case AArch64::LDPSpre:
3662 case AArch64::LDPSWpost: {
3663 unsigned Rt = Inst.getOperand(1).getReg();
3664 unsigned Rt2 = Inst.getOperand(2).getReg();
3665 if (Rt == Rt2)
3666 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3667 break;
3668 }
3669 case AArch64::STPDpost:
3670 case AArch64::STPDpre:
3671 case AArch64::STPQpost:
3672 case AArch64::STPQpre:
3673 case AArch64::STPSpost:
3674 case AArch64::STPSpre:
3675 case AArch64::STPWpost:
3676 case AArch64::STPWpre:
3677 case AArch64::STPXpost:
3678 case AArch64::STPXpre: {
3679 unsigned Rt = Inst.getOperand(1).getReg();
3680 unsigned Rt2 = Inst.getOperand(2).getReg();
3681 unsigned Rn = Inst.getOperand(3).getReg();
3682 if (RI->isSubRegisterEq(Rn, Rt))
3683 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3684 "is also a source");
3685 if (RI->isSubRegisterEq(Rn, Rt2))
3686 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3687 "is also a source");
3688 break;
3689 }
3690 case AArch64::LDRBBpre:
3691 case AArch64::LDRBpre:
3692 case AArch64::LDRHHpre:
3693 case AArch64::LDRHpre:
3694 case AArch64::LDRSBWpre:
3695 case AArch64::LDRSBXpre:
3696 case AArch64::LDRSHWpre:
3697 case AArch64::LDRSHXpre:
3698 case AArch64::LDRSWpre:
3699 case AArch64::LDRWpre:
3700 case AArch64::LDRXpre:
3701 case AArch64::LDRBBpost:
3702 case AArch64::LDRBpost:
3703 case AArch64::LDRHHpost:
3704 case AArch64::LDRHpost:
3705 case AArch64::LDRSBWpost:
3706 case AArch64::LDRSBXpost:
3707 case AArch64::LDRSHWpost:
3708 case AArch64::LDRSHXpost:
3709 case AArch64::LDRSWpost:
3710 case AArch64::LDRWpost:
3711 case AArch64::LDRXpost: {
3712 unsigned Rt = Inst.getOperand(1).getReg();
3713 unsigned Rn = Inst.getOperand(2).getReg();
3714 if (RI->isSubRegisterEq(Rn, Rt))
3715 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3716 "is also a source");
3717 break;
3718 }
3719 case AArch64::STRBBpost:
3720 case AArch64::STRBpost:
3721 case AArch64::STRHHpost:
3722 case AArch64::STRHpost:
3723 case AArch64::STRWpost:
3724 case AArch64::STRXpost:
3725 case AArch64::STRBBpre:
3726 case AArch64::STRBpre:
3727 case AArch64::STRHHpre:
3728 case AArch64::STRHpre:
3729 case AArch64::STRWpre:
3730 case AArch64::STRXpre: {
3731 unsigned Rt = Inst.getOperand(1).getReg();
3732 unsigned Rn = Inst.getOperand(2).getReg();
3733 if (RI->isSubRegisterEq(Rn, Rt))
3734 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3735 "is also a source");
3736 break;
3737 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003738 case AArch64::STXRB:
3739 case AArch64::STXRH:
3740 case AArch64::STXRW:
3741 case AArch64::STXRX:
3742 case AArch64::STLXRB:
3743 case AArch64::STLXRH:
3744 case AArch64::STLXRW:
3745 case AArch64::STLXRX: {
3746 unsigned Rs = Inst.getOperand(0).getReg();
3747 unsigned Rt = Inst.getOperand(1).getReg();
3748 unsigned Rn = Inst.getOperand(2).getReg();
3749 if (RI->isSubRegisterEq(Rt, Rs) ||
3750 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3751 return Error(Loc[0],
3752 "unpredictable STXR instruction, status is also a source");
3753 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003754 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003755 case AArch64::STXPW:
3756 case AArch64::STXPX:
3757 case AArch64::STLXPW:
3758 case AArch64::STLXPX: {
3759 unsigned Rs = Inst.getOperand(0).getReg();
3760 unsigned Rt1 = Inst.getOperand(1).getReg();
3761 unsigned Rt2 = Inst.getOperand(2).getReg();
3762 unsigned Rn = Inst.getOperand(3).getReg();
3763 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3764 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3765 return Error(Loc[0],
3766 "unpredictable STXP instruction, status is also a source");
3767 break;
3768 }
3769 }
3770
Tim Northover3b0846e2014-05-24 12:50:23 +00003771
3772 // Now check immediate ranges. Separate from the above as there is overlap
3773 // in the instructions being checked and this keeps the nested conditionals
3774 // to a minimum.
3775 switch (Inst.getOpcode()) {
3776 case AArch64::ADDSWri:
3777 case AArch64::ADDSXri:
3778 case AArch64::ADDWri:
3779 case AArch64::ADDXri:
3780 case AArch64::SUBSWri:
3781 case AArch64::SUBSXri:
3782 case AArch64::SUBWri:
3783 case AArch64::SUBXri: {
3784 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3785 // some slight duplication here.
3786 if (Inst.getOperand(2).isExpr()) {
3787 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3788 AArch64MCExpr::VariantKind ELFRefKind;
3789 MCSymbolRefExpr::VariantKind DarwinRefKind;
3790 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003791 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3792
3793 // Only allow these with ADDXri.
3794 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3795 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3796 Inst.getOpcode() == AArch64::ADDXri)
3797 return false;
3798
3799 // Only allow these with ADDXri/ADDWri
3800 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3801 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3802 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3803 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3804 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3805 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3806 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003807 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3808 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3809 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003810 (Inst.getOpcode() == AArch64::ADDXri ||
3811 Inst.getOpcode() == AArch64::ADDWri))
3812 return false;
3813
3814 // Don't allow symbol refs in the immediate field otherwise
3815 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3816 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3817 // 'cmp w0, 'borked')
3818 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003819 }
Diana Picusc93518d2016-10-11 09:17:47 +00003820 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003821 }
3822 return false;
3823 }
3824 default:
3825 return false;
3826 }
3827}
3828
Craig Topper05515562017-10-26 06:46:41 +00003829static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3830 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003831
3832bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
Sander de Smalen0325e302018-07-02 07:34:52 +00003833 uint64_t ErrorInfo,
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003834 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003835 switch (ErrCode) {
Sander de Smalen0325e302018-07-02 07:34:52 +00003836 case Match_InvalidTiedOperand: {
3837 RegConstraintEqualityTy EqTy =
3838 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
3839 .getRegEqualityTy();
3840 switch (EqTy) {
3841 case RegConstraintEqualityTy::EqualsSubReg:
3842 return Error(Loc, "operand must be 64-bit form of destination register");
3843 case RegConstraintEqualityTy::EqualsSuperReg:
3844 return Error(Loc, "operand must be 32-bit form of destination register");
3845 case RegConstraintEqualityTy::EqualsReg:
3846 return Error(Loc, "operand must match destination register");
3847 }
3848 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003849 case Match_MissingFeature:
3850 return Error(Loc,
3851 "instruction requires a CPU feature not currently enabled");
3852 case Match_InvalidOperand:
3853 return Error(Loc, "invalid operand for instruction");
3854 case Match_InvalidSuffix:
3855 return Error(Loc, "invalid type suffix for instruction");
3856 case Match_InvalidCondCode:
3857 return Error(Loc, "expected AArch64 condition code");
3858 case Match_AddSubRegExtendSmall:
3859 return Error(Loc,
3860 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3861 case Match_AddSubRegExtendLarge:
3862 return Error(Loc,
3863 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3864 case Match_AddSubSecondSource:
3865 return Error(Loc,
3866 "expected compatible register, symbol or integer in range [0, 4095]");
3867 case Match_LogicalSecondSource:
3868 return Error(Loc, "expected compatible register or logical immediate");
3869 case Match_InvalidMovImm32Shift:
3870 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3871 case Match_InvalidMovImm64Shift:
3872 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3873 case Match_AddSubRegShift32:
3874 return Error(Loc,
3875 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3876 case Match_AddSubRegShift64:
3877 return Error(Loc,
3878 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3879 case Match_InvalidFPImm:
3880 return Error(Loc,
3881 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003882 case Match_InvalidMemoryIndexedSImm6:
3883 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003884 case Match_InvalidMemoryIndexedSImm5:
3885 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003886 case Match_InvalidMemoryIndexed1SImm4:
3887 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003888 case Match_InvalidMemoryIndexed2SImm4:
3889 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003890 case Match_InvalidMemoryIndexed3SImm4:
3891 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003892 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00003893 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00003894 case Match_InvalidMemoryIndexed16SImm4:
3895 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00003896 case Match_InvalidMemoryIndexed1SImm6:
3897 return Error(Loc, "index must be an integer in range [-32, 31].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003898 case Match_InvalidMemoryIndexedSImm9:
3899 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00003900 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00003901 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003902 case Match_InvalidMemoryIndexed4SImm7:
3903 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3904 case Match_InvalidMemoryIndexed8SImm7:
3905 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3906 case Match_InvalidMemoryIndexed16SImm7:
3907 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00003908 case Match_InvalidMemoryIndexed8UImm5:
3909 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
3910 case Match_InvalidMemoryIndexed4UImm5:
3911 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
3912 case Match_InvalidMemoryIndexed2UImm5:
3913 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00003914 case Match_InvalidMemoryIndexed8UImm6:
3915 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
3916 case Match_InvalidMemoryIndexed4UImm6:
3917 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
3918 case Match_InvalidMemoryIndexed2UImm6:
3919 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
3920 case Match_InvalidMemoryIndexed1UImm6:
3921 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003922 case Match_InvalidMemoryWExtend8:
3923 return Error(Loc,
3924 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3925 case Match_InvalidMemoryWExtend16:
3926 return Error(Loc,
3927 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3928 case Match_InvalidMemoryWExtend32:
3929 return Error(Loc,
3930 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3931 case Match_InvalidMemoryWExtend64:
3932 return Error(Loc,
3933 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3934 case Match_InvalidMemoryWExtend128:
3935 return Error(Loc,
3936 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3937 case Match_InvalidMemoryXExtend8:
3938 return Error(Loc,
3939 "expected 'lsl' or 'sxtx' with optional shift of #0");
3940 case Match_InvalidMemoryXExtend16:
3941 return Error(Loc,
3942 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3943 case Match_InvalidMemoryXExtend32:
3944 return Error(Loc,
3945 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3946 case Match_InvalidMemoryXExtend64:
3947 return Error(Loc,
3948 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3949 case Match_InvalidMemoryXExtend128:
3950 return Error(Loc,
3951 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3952 case Match_InvalidMemoryIndexed1:
3953 return Error(Loc, "index must be an integer in range [0, 4095].");
3954 case Match_InvalidMemoryIndexed2:
3955 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3956 case Match_InvalidMemoryIndexed4:
3957 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3958 case Match_InvalidMemoryIndexed8:
3959 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3960 case Match_InvalidMemoryIndexed16:
3961 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003962 case Match_InvalidImm0_1:
3963 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003964 case Match_InvalidImm0_7:
3965 return Error(Loc, "immediate must be an integer in range [0, 7].");
3966 case Match_InvalidImm0_15:
3967 return Error(Loc, "immediate must be an integer in range [0, 15].");
3968 case Match_InvalidImm0_31:
3969 return Error(Loc, "immediate must be an integer in range [0, 31].");
3970 case Match_InvalidImm0_63:
3971 return Error(Loc, "immediate must be an integer in range [0, 63].");
3972 case Match_InvalidImm0_127:
3973 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003974 case Match_InvalidImm0_255:
3975 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003976 case Match_InvalidImm0_65535:
3977 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3978 case Match_InvalidImm1_8:
3979 return Error(Loc, "immediate must be an integer in range [1, 8].");
3980 case Match_InvalidImm1_16:
3981 return Error(Loc, "immediate must be an integer in range [1, 16].");
3982 case Match_InvalidImm1_32:
3983 return Error(Loc, "immediate must be an integer in range [1, 32].");
3984 case Match_InvalidImm1_64:
3985 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00003986 case Match_InvalidSVEAddSubImm8:
3987 return Error(Loc, "immediate must be an integer in range [0, 255]"
3988 " with a shift amount of 0");
3989 case Match_InvalidSVEAddSubImm16:
3990 case Match_InvalidSVEAddSubImm32:
3991 case Match_InvalidSVEAddSubImm64:
3992 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
3993 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00003994 case Match_InvalidSVECpyImm8:
3995 return Error(Loc, "immediate must be an integer in range [-128, 255]"
3996 " with a shift amount of 0");
3997 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00003998 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
3999 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004000 case Match_InvalidSVECpyImm32:
4001 case Match_InvalidSVECpyImm64:
4002 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4003 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004004 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004005 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004006 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00004007 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004008 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00004009 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004010 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004011 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004012 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004013 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004014 case Match_InvalidSVEIndexRange0_63:
4015 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4016 case Match_InvalidSVEIndexRange0_31:
4017 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4018 case Match_InvalidSVEIndexRange0_15:
4019 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4020 case Match_InvalidSVEIndexRange0_7:
4021 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4022 case Match_InvalidSVEIndexRange0_3:
4023 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004024 case Match_InvalidLabel:
4025 return Error(Loc, "expected label or encodable integer pc offset");
4026 case Match_MRS:
4027 return Error(Loc, "expected readable system register");
4028 case Match_MSR:
4029 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00004030 case Match_InvalidComplexRotationEven:
4031 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4032 case Match_InvalidComplexRotationOdd:
4033 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004034 case Match_MnemonicFail: {
4035 std::string Suggestion = AArch64MnemonicSpellCheck(
4036 ((AArch64Operand &)*Operands[0]).getToken(),
4037 ComputeAvailableFeatures(STI->getFeatureBits()));
4038 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4039 }
Sander de Smalen367694b2018-04-20 08:54:49 +00004040 case Match_InvalidGPR64shifted8:
4041 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4042 case Match_InvalidGPR64shifted16:
4043 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4044 case Match_InvalidGPR64shifted32:
4045 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4046 case Match_InvalidGPR64shifted64:
4047 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4048 case Match_InvalidGPR64NoXZRshifted8:
4049 return Error(Loc, "register must be x0..x30 without shift");
4050 case Match_InvalidGPR64NoXZRshifted16:
4051 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4052 case Match_InvalidGPR64NoXZRshifted32:
4053 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4054 case Match_InvalidGPR64NoXZRshifted64:
4055 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004056 case Match_InvalidZPR32UXTW8:
4057 case Match_InvalidZPR32SXTW8:
4058 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4059 case Match_InvalidZPR32UXTW16:
4060 case Match_InvalidZPR32SXTW16:
4061 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4062 case Match_InvalidZPR32UXTW32:
4063 case Match_InvalidZPR32SXTW32:
4064 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4065 case Match_InvalidZPR32UXTW64:
4066 case Match_InvalidZPR32SXTW64:
4067 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4068 case Match_InvalidZPR64UXTW8:
4069 case Match_InvalidZPR64SXTW8:
4070 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4071 case Match_InvalidZPR64UXTW16:
4072 case Match_InvalidZPR64SXTW16:
4073 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4074 case Match_InvalidZPR64UXTW32:
4075 case Match_InvalidZPR64SXTW32:
4076 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4077 case Match_InvalidZPR64UXTW64:
4078 case Match_InvalidZPR64SXTW64:
4079 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
4080 case Match_InvalidZPR64LSL8:
4081 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4082 case Match_InvalidZPR64LSL16:
4083 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4084 case Match_InvalidZPR64LSL32:
4085 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4086 case Match_InvalidZPR64LSL64:
4087 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00004088 case Match_InvalidZPR0:
4089 return Error(Loc, "expected register without element width sufix");
4090 case Match_InvalidZPR8:
4091 case Match_InvalidZPR16:
4092 case Match_InvalidZPR32:
4093 case Match_InvalidZPR64:
4094 case Match_InvalidZPR128:
4095 return Error(Loc, "invalid element width");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004096 case Match_InvalidSVEPattern:
4097 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004098 case Match_InvalidSVEPredicateAnyReg:
4099 case Match_InvalidSVEPredicateBReg:
4100 case Match_InvalidSVEPredicateHReg:
4101 case Match_InvalidSVEPredicateSReg:
4102 case Match_InvalidSVEPredicateDReg:
4103 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004104 case Match_InvalidSVEPredicate3bAnyReg:
4105 case Match_InvalidSVEPredicate3bBReg:
4106 case Match_InvalidSVEPredicate3bHReg:
4107 case Match_InvalidSVEPredicate3bSReg:
4108 case Match_InvalidSVEPredicate3bDReg:
4109 return Error(Loc, "restricted predicate has range [0, 7].");
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004110 case Match_InvalidSVEExactFPImmOperandHalfOne:
4111 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4112 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4113 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4114 case Match_InvalidSVEExactFPImmOperandZeroOne:
4115 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004116 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004117 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004118 }
4119}
4120
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004121static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004122
4123bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4124 OperandVector &Operands,
4125 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004126 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004127 bool MatchingInlineAsm) {
4128 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004129 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4130 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004131
David Blaikie960ea3f2014-06-08 16:18:35 +00004132 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004133 unsigned NumOperands = Operands.size();
4134
4135 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004136 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4137 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004138 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004139 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004140 if (Op3CE) {
4141 uint64_t Op3Val = Op3CE->getValue();
4142 uint64_t NewOp3Val = 0;
4143 uint64_t NewOp4Val = 0;
4144 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004145 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004146 NewOp3Val = (32 - Op3Val) & 0x1f;
4147 NewOp4Val = 31 - Op3Val;
4148 } else {
4149 NewOp3Val = (64 - Op3Val) & 0x3f;
4150 NewOp4Val = 63 - Op3Val;
4151 }
4152
Jim Grosbach13760bd2015-05-30 01:25:56 +00004153 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4154 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004155
4156 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004157 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004158 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004159 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4160 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4161 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004162 }
4163 }
Tim Northover03b99f62015-04-30 18:28:58 +00004164 } else if (NumOperands == 4 && Tok == "bfc") {
4165 // FIXME: Horrible hack to handle BFC->BFM alias.
4166 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4167 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4168 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4169
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004170 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004171 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4172 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4173
4174 if (LSBCE && WidthCE) {
4175 uint64_t LSB = LSBCE->getValue();
4176 uint64_t Width = WidthCE->getValue();
4177
4178 uint64_t RegWidth = 0;
4179 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4180 Op1.getReg()))
4181 RegWidth = 64;
4182 else
4183 RegWidth = 32;
4184
4185 if (LSB >= RegWidth)
4186 return Error(LSBOp.getStartLoc(),
4187 "expected integer in range [0, 31]");
4188 if (Width < 1 || Width > RegWidth)
4189 return Error(WidthOp.getStartLoc(),
4190 "expected integer in range [1, 32]");
4191
4192 uint64_t ImmR = 0;
4193 if (RegWidth == 32)
4194 ImmR = (32 - LSB) & 0x1f;
4195 else
4196 ImmR = (64 - LSB) & 0x3f;
4197
4198 uint64_t ImmS = Width - 1;
4199
4200 if (ImmR != 0 && ImmS >= ImmR)
4201 return Error(WidthOp.getStartLoc(),
4202 "requested insert overflows register");
4203
Jim Grosbach13760bd2015-05-30 01:25:56 +00004204 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4205 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004206 Operands[0] = AArch64Operand::CreateToken(
4207 "bfm", false, Op.getStartLoc(), getContext());
4208 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004209 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4210 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004211 Operands[3] = AArch64Operand::CreateImm(
4212 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4213 Operands.emplace_back(
4214 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4215 WidthOp.getEndLoc(), getContext()));
4216 }
4217 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004218 } else if (NumOperands == 5) {
4219 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4220 // UBFIZ -> UBFM aliases.
4221 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004222 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4223 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4224 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004225
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004226 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004227 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4228 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004229
4230 if (Op3CE && Op4CE) {
4231 uint64_t Op3Val = Op3CE->getValue();
4232 uint64_t Op4Val = Op4CE->getValue();
4233
4234 uint64_t RegWidth = 0;
4235 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004236 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004237 RegWidth = 64;
4238 else
4239 RegWidth = 32;
4240
4241 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004242 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004243 "expected integer in range [0, 31]");
4244 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004245 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004246 "expected integer in range [1, 32]");
4247
4248 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004249 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004250 NewOp3Val = (32 - Op3Val) & 0x1f;
4251 else
4252 NewOp3Val = (64 - Op3Val) & 0x3f;
4253
4254 uint64_t NewOp4Val = Op4Val - 1;
4255
4256 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004257 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004258 "requested insert overflows register");
4259
4260 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004261 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004262 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004263 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004264 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004265 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004266 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004267 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004268 if (Tok == "bfi")
4269 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004270 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004271 else if (Tok == "sbfiz")
4272 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004273 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004274 else if (Tok == "ubfiz")
4275 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004276 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004277 else
4278 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004279 }
4280 }
4281
4282 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4283 // UBFX -> UBFM aliases.
4284 } else if (NumOperands == 5 &&
4285 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004286 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4287 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4288 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004289
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004290 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004291 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4292 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004293
4294 if (Op3CE && Op4CE) {
4295 uint64_t Op3Val = Op3CE->getValue();
4296 uint64_t Op4Val = Op4CE->getValue();
4297
4298 uint64_t RegWidth = 0;
4299 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004300 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004301 RegWidth = 64;
4302 else
4303 RegWidth = 32;
4304
4305 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004306 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004307 "expected integer in range [0, 31]");
4308 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004309 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004310 "expected integer in range [1, 32]");
4311
4312 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4313
4314 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004315 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004316 "requested extract overflows register");
4317
4318 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004319 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004320 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004321 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004322 if (Tok == "bfxil")
4323 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004324 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004325 else if (Tok == "sbfx")
4326 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004327 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004328 else if (Tok == "ubfx")
4329 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004330 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004331 else
4332 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004333 }
4334 }
4335 }
4336 }
Tim Northover9097a072017-12-18 10:36:00 +00004337
4338 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4339 // instruction for FP registers correctly in some rare circumstances. Convert
4340 // it to a safe instruction and warn (because silently changing someone's
4341 // assembly is rude).
4342 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4343 NumOperands == 4 && Tok == "movi") {
4344 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4345 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4346 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4347 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4348 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4349 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4350 if (Suffix.lower() == ".2d" &&
4351 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4352 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4353 " correctly on this CPU, converting to equivalent movi.16b");
4354 // Switch the suffix to .16b.
4355 unsigned Idx = Op1.isToken() ? 1 : 2;
4356 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4357 getContext());
4358 }
4359 }
4360 }
4361
Tim Northover3b0846e2014-05-24 12:50:23 +00004362 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4363 // InstAlias can't quite handle this since the reg classes aren't
4364 // subclasses.
4365 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4366 // The source register can be Wn here, but the matcher expects a
4367 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004368 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004369 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004370 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004371 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4372 Op.getStartLoc(), Op.getEndLoc(),
4373 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004374 }
4375 }
4376 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4377 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004378 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004379 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004380 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004381 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004382 // The source register can be Wn here, but the matcher expects a
4383 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004384 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004385 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004386 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004387 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4388 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004389 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004390 }
4391 }
4392 }
4393 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4394 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004395 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004396 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004397 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004398 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004399 // The source register can be Wn here, but the matcher expects a
4400 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004401 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004402 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004403 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004404 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4405 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004406 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004407 }
4408 }
4409 }
4410
Tim Northover3b0846e2014-05-24 12:50:23 +00004411 MCInst Inst;
4412 // First try to match against the secondary set of tables containing the
4413 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4414 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004415 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004416
4417 // If that fails, try against the alternate table containing long-form NEON:
4418 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004419 if (MatchResult != Match_Success) {
4420 // But first, save the short-form match result: we can use it in case the
4421 // long-form match also fails.
4422 auto ShortFormNEONErrorInfo = ErrorInfo;
4423 auto ShortFormNEONMatchResult = MatchResult;
4424
Tim Northover3b0846e2014-05-24 12:50:23 +00004425 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004426 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004427
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004428 // Now, both matches failed, and the long-form match failed on the mnemonic
4429 // suffix token operand. The short-form match failure is probably more
4430 // relevant: use it instead.
4431 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004432 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004433 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4434 MatchResult = ShortFormNEONMatchResult;
4435 ErrorInfo = ShortFormNEONErrorInfo;
4436 }
4437 }
4438
Tim Northover3b0846e2014-05-24 12:50:23 +00004439 switch (MatchResult) {
4440 case Match_Success: {
4441 // Perform range checking and other semantic validations
4442 SmallVector<SMLoc, 8> OperandLocs;
4443 NumOperands = Operands.size();
4444 for (unsigned i = 1; i < NumOperands; ++i)
4445 OperandLocs.push_back(Operands[i]->getStartLoc());
4446 if (validateInstruction(Inst, OperandLocs))
4447 return true;
4448
4449 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004450 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004451 return false;
4452 }
4453 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004454 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004455 // Special case the error message for the very common case where only
4456 // a single subtarget feature is missing (neon, e.g.).
4457 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004458 uint64_t Mask = 1;
4459 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4460 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004461 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004462 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004463 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004464 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004465 }
4466 return Error(IDLoc, Msg);
4467 }
4468 case Match_MnemonicFail:
Sander de Smalen0325e302018-07-02 07:34:52 +00004469 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004470 case Match_InvalidOperand: {
4471 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004472
Tim Northover26bb14e2014-08-18 11:49:42 +00004473 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004474 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004475 return Error(IDLoc, "too few operands for instruction",
4476 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004477
David Blaikie960ea3f2014-06-08 16:18:35 +00004478 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004479 if (ErrorLoc == SMLoc())
4480 ErrorLoc = IDLoc;
4481 }
4482 // If the match failed on a suffix token operand, tweak the diagnostic
4483 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004484 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4485 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004486 MatchResult = Match_InvalidSuffix;
4487
Sander de Smalen0325e302018-07-02 07:34:52 +00004488 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004489 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004490 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004491 case Match_InvalidMemoryIndexed1:
4492 case Match_InvalidMemoryIndexed2:
4493 case Match_InvalidMemoryIndexed4:
4494 case Match_InvalidMemoryIndexed8:
4495 case Match_InvalidMemoryIndexed16:
4496 case Match_InvalidCondCode:
4497 case Match_AddSubRegExtendSmall:
4498 case Match_AddSubRegExtendLarge:
4499 case Match_AddSubSecondSource:
4500 case Match_LogicalSecondSource:
4501 case Match_AddSubRegShift32:
4502 case Match_AddSubRegShift64:
4503 case Match_InvalidMovImm32Shift:
4504 case Match_InvalidMovImm64Shift:
4505 case Match_InvalidFPImm:
4506 case Match_InvalidMemoryWExtend8:
4507 case Match_InvalidMemoryWExtend16:
4508 case Match_InvalidMemoryWExtend32:
4509 case Match_InvalidMemoryWExtend64:
4510 case Match_InvalidMemoryWExtend128:
4511 case Match_InvalidMemoryXExtend8:
4512 case Match_InvalidMemoryXExtend16:
4513 case Match_InvalidMemoryXExtend32:
4514 case Match_InvalidMemoryXExtend64:
4515 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004516 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004517 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004518 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004519 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004520 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004521 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004522 case Match_InvalidMemoryIndexed4SImm7:
4523 case Match_InvalidMemoryIndexed8SImm7:
4524 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004525 case Match_InvalidMemoryIndexed8UImm5:
4526 case Match_InvalidMemoryIndexed4UImm5:
4527 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004528 case Match_InvalidMemoryIndexed1UImm6:
4529 case Match_InvalidMemoryIndexed2UImm6:
4530 case Match_InvalidMemoryIndexed4UImm6:
4531 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004532 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004533 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004534 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004535 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004536 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004537 case Match_InvalidImm0_7:
4538 case Match_InvalidImm0_15:
4539 case Match_InvalidImm0_31:
4540 case Match_InvalidImm0_63:
4541 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004542 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004543 case Match_InvalidImm0_65535:
4544 case Match_InvalidImm1_8:
4545 case Match_InvalidImm1_16:
4546 case Match_InvalidImm1_32:
4547 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004548 case Match_InvalidSVEAddSubImm8:
4549 case Match_InvalidSVEAddSubImm16:
4550 case Match_InvalidSVEAddSubImm32:
4551 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004552 case Match_InvalidSVECpyImm8:
4553 case Match_InvalidSVECpyImm16:
4554 case Match_InvalidSVECpyImm32:
4555 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004556 case Match_InvalidIndexRange1_1:
4557 case Match_InvalidIndexRange0_15:
4558 case Match_InvalidIndexRange0_7:
4559 case Match_InvalidIndexRange0_3:
4560 case Match_InvalidIndexRange0_1:
4561 case Match_InvalidSVEIndexRange0_63:
4562 case Match_InvalidSVEIndexRange0_31:
4563 case Match_InvalidSVEIndexRange0_15:
4564 case Match_InvalidSVEIndexRange0_7:
4565 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004566 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004567 case Match_InvalidComplexRotationEven:
4568 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004569 case Match_InvalidGPR64shifted8:
4570 case Match_InvalidGPR64shifted16:
4571 case Match_InvalidGPR64shifted32:
4572 case Match_InvalidGPR64shifted64:
4573 case Match_InvalidGPR64NoXZRshifted8:
4574 case Match_InvalidGPR64NoXZRshifted16:
4575 case Match_InvalidGPR64NoXZRshifted32:
4576 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004577 case Match_InvalidZPR32UXTW8:
4578 case Match_InvalidZPR32UXTW16:
4579 case Match_InvalidZPR32UXTW32:
4580 case Match_InvalidZPR32UXTW64:
4581 case Match_InvalidZPR32SXTW8:
4582 case Match_InvalidZPR32SXTW16:
4583 case Match_InvalidZPR32SXTW32:
4584 case Match_InvalidZPR32SXTW64:
4585 case Match_InvalidZPR64UXTW8:
4586 case Match_InvalidZPR64SXTW8:
4587 case Match_InvalidZPR64UXTW16:
4588 case Match_InvalidZPR64SXTW16:
4589 case Match_InvalidZPR64UXTW32:
4590 case Match_InvalidZPR64SXTW32:
4591 case Match_InvalidZPR64UXTW64:
4592 case Match_InvalidZPR64SXTW64:
4593 case Match_InvalidZPR64LSL8:
4594 case Match_InvalidZPR64LSL16:
4595 case Match_InvalidZPR64LSL32:
4596 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004597 case Match_InvalidZPR0:
4598 case Match_InvalidZPR8:
4599 case Match_InvalidZPR16:
4600 case Match_InvalidZPR32:
4601 case Match_InvalidZPR64:
4602 case Match_InvalidZPR128:
Sander de Smalencd6be962017-12-20 11:02:42 +00004603 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004604 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004605 case Match_InvalidSVEPredicateBReg:
4606 case Match_InvalidSVEPredicateHReg:
4607 case Match_InvalidSVEPredicateSReg:
4608 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004609 case Match_InvalidSVEPredicate3bAnyReg:
4610 case Match_InvalidSVEPredicate3bBReg:
4611 case Match_InvalidSVEPredicate3bHReg:
4612 case Match_InvalidSVEPredicate3bSReg:
4613 case Match_InvalidSVEPredicate3bDReg:
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004614 case Match_InvalidSVEExactFPImmOperandHalfOne:
4615 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4616 case Match_InvalidSVEExactFPImmOperandZeroOne:
Tim Northover3b0846e2014-05-24 12:50:23 +00004617 case Match_MSR:
4618 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004619 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004620 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004621 // Any time we get here, there's nothing fancy to do. Just get the
4622 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004623 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004624 if (ErrorLoc == SMLoc())
4625 ErrorLoc = IDLoc;
Sander de Smalen0325e302018-07-02 07:34:52 +00004626 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004627 }
4628 }
4629
4630 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004631}
4632
4633/// ParseDirective parses the arm specific directives
4634bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004635 const MCObjectFileInfo::Environment Format =
4636 getContext().getObjectFileInfo()->getObjectFileType();
4637 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4638 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004639
Tim Northover3b0846e2014-05-24 12:50:23 +00004640 StringRef IDVal = DirectiveID.getIdentifier();
4641 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004642 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004643 parseDirectiveArch(Loc);
4644 else if (IDVal == ".cpu")
4645 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00004646 else if (IDVal == ".tlsdesccall")
4647 parseDirectiveTLSDescCall(Loc);
4648 else if (IDVal == ".ltorg" || IDVal == ".pool")
4649 parseDirectiveLtorg(Loc);
4650 else if (IDVal == ".unreq")
4651 parseDirectiveUnreq(Loc);
4652 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004653 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004654 parseDirectiveInst(Loc);
4655 else
4656 return true;
4657 } else if (IDVal == MCLOHDirectiveName())
4658 parseDirectiveLOH(IDVal, Loc);
4659 else
4660 return true;
4661 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004662}
4663
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004664static const struct {
4665 const char *Name;
4666 const FeatureBitset Features;
4667} ExtensionMap[] = {
4668 { "crc", {AArch64::FeatureCRC} },
4669 { "crypto", {AArch64::FeatureCrypto} },
4670 { "fp", {AArch64::FeatureFPARMv8} },
4671 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004672 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004673 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004674
4675 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004676 { "pan", {} },
4677 { "lor", {} },
4678 { "rdma", {} },
4679 { "profile", {} },
4680};
4681
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004682/// parseDirectiveArch
4683/// ::= .arch token
4684bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4685 SMLoc ArchLoc = getLoc();
4686
4687 StringRef Arch, ExtensionString;
4688 std::tie(Arch, ExtensionString) =
4689 getParser().parseStringToEndOfStatement().trim().split('+');
4690
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004691 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4692 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004693 return Error(ArchLoc, "unknown arch name");
4694
4695 if (parseToken(AsmToken::EndOfStatement))
4696 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004697
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004698 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004699 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004700 AArch64::getArchFeatures(ID, AArch64Features);
4701 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4702 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004703
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004704 MCSubtargetInfo &STI = copySTI();
4705 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4706 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4707
4708 SmallVector<StringRef, 4> RequestedExtensions;
4709 if (!ExtensionString.empty())
4710 ExtensionString.split(RequestedExtensions, '+');
4711
4712 FeatureBitset Features = STI.getFeatureBits();
4713 for (auto Name : RequestedExtensions) {
4714 bool EnableFeature = true;
4715
4716 if (Name.startswith_lower("no")) {
4717 EnableFeature = false;
4718 Name = Name.substr(2);
4719 }
4720
4721 for (const auto &Extension : ExtensionMap) {
4722 if (Extension.Name != Name)
4723 continue;
4724
4725 if (Extension.Features.none())
4726 report_fatal_error("unsupported architectural extension: " + Name);
4727
4728 FeatureBitset ToggleFeatures = EnableFeature
4729 ? (~Features & Extension.Features)
4730 : ( Features & Extension.Features);
4731 uint64_t Features =
4732 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4733 setAvailableFeatures(Features);
4734 break;
4735 }
4736 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004737 return false;
4738}
4739
Tim Northover8b96c7e2017-05-15 19:42:15 +00004740static SMLoc incrementLoc(SMLoc L, int Offset) {
4741 return SMLoc::getFromPointer(L.getPointer() + Offset);
4742}
4743
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004744/// parseDirectiveCPU
4745/// ::= .cpu id
4746bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004747 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004748
4749 StringRef CPU, ExtensionString;
4750 std::tie(CPU, ExtensionString) =
4751 getParser().parseStringToEndOfStatement().trim().split('+');
4752
Nirav Davee833c6c2016-11-08 18:31:04 +00004753 if (parseToken(AsmToken::EndOfStatement))
4754 return true;
4755
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004756 SmallVector<StringRef, 4> RequestedExtensions;
4757 if (!ExtensionString.empty())
4758 ExtensionString.split(RequestedExtensions, '+');
4759
4760 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4761 // once that is tablegen'ed
4762 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004763 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004764 return false;
4765 }
4766
4767 MCSubtargetInfo &STI = copySTI();
4768 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004769 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004770
4771 FeatureBitset Features = STI.getFeatureBits();
4772 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004773 // Advance source location past '+'.
4774 CurLoc = incrementLoc(CurLoc, 1);
4775
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004776 bool EnableFeature = true;
4777
4778 if (Name.startswith_lower("no")) {
4779 EnableFeature = false;
4780 Name = Name.substr(2);
4781 }
4782
Tim Northover8b96c7e2017-05-15 19:42:15 +00004783 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004784 for (const auto &Extension : ExtensionMap) {
4785 if (Extension.Name != Name)
4786 continue;
4787
4788 if (Extension.Features.none())
4789 report_fatal_error("unsupported architectural extension: " + Name);
4790
4791 FeatureBitset ToggleFeatures = EnableFeature
4792 ? (~Features & Extension.Features)
4793 : ( Features & Extension.Features);
4794 uint64_t Features =
4795 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4796 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004797 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004798
4799 break;
4800 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004801
4802 if (!FoundExtension)
4803 Error(CurLoc, "unsupported architectural extension");
4804
4805 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004806 }
4807 return false;
4808}
4809
Chad Rosierdcd2a302014-10-22 20:35:57 +00004810/// parseDirectiveInst
4811/// ::= .inst opcode [, ...]
4812bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004813 if (getLexer().is(AsmToken::EndOfStatement))
4814 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004815
Nirav Davee833c6c2016-11-08 18:31:04 +00004816 auto parseOp = [&]() -> bool {
4817 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004818 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004819 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4820 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004821 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004822 if (check(!Value, L, "expected constant expression"))
4823 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004824 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004825 return false;
4826 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004827
Nirav Davee833c6c2016-11-08 18:31:04 +00004828 if (parseMany(parseOp))
4829 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004830 return false;
4831}
4832
Tim Northover3b0846e2014-05-24 12:50:23 +00004833// parseDirectiveTLSDescCall:
4834// ::= .tlsdesccall symbol
4835bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4836 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004837 if (check(getParser().parseIdentifier(Name), L,
4838 "expected symbol after directive") ||
4839 parseToken(AsmToken::EndOfStatement))
4840 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004841
Jim Grosbach6f482002015-05-18 18:43:14 +00004842 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004843 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4844 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004845
4846 MCInst Inst;
4847 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004848 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004849
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004850 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004851 return false;
4852}
4853
4854/// ::= .loh <lohName | lohId> label1, ..., labelN
4855/// The number of arguments depends on the loh identifier.
4856bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004857 MCLOHType Kind;
4858 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4859 if (getParser().getTok().isNot(AsmToken::Integer))
4860 return TokError("expected an identifier or a number in directive");
4861 // We successfully get a numeric value for the identifier.
4862 // Check if it is valid.
4863 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004864 if (Id <= -1U && !isValidMCLOHType(Id))
4865 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004866 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004867 } else {
4868 StringRef Name = getTok().getIdentifier();
4869 // We successfully parse an identifier.
4870 // Check if it is a recognized one.
4871 int Id = MCLOHNameToId(Name);
4872
4873 if (Id == -1)
4874 return TokError("invalid identifier in directive");
4875 Kind = (MCLOHType)Id;
4876 }
4877 // Consume the identifier.
4878 Lex();
4879 // Get the number of arguments of this LOH.
4880 int NbArgs = MCLOHIdToNbArgs(Kind);
4881
4882 assert(NbArgs != -1 && "Invalid number of arguments");
4883
4884 SmallVector<MCSymbol *, 3> Args;
4885 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4886 StringRef Name;
4887 if (getParser().parseIdentifier(Name))
4888 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004889 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004890
4891 if (Idx + 1 == NbArgs)
4892 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004893 if (parseToken(AsmToken::Comma,
4894 "unexpected token in '" + Twine(IDVal) + "' directive"))
4895 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004896 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004897 if (parseToken(AsmToken::EndOfStatement,
4898 "unexpected token in '" + Twine(IDVal) + "' directive"))
4899 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004900
4901 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4902 return false;
4903}
4904
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004905/// parseDirectiveLtorg
4906/// ::= .ltorg | .pool
4907bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004908 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4909 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004910 getTargetStreamer().emitCurrentConstantPool();
4911 return false;
4912}
4913
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004914/// parseDirectiveReq
4915/// ::= name .req registername
4916bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004917 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004918 Parser.Lex(); // Eat the '.req' token.
4919 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004920 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004921 unsigned RegNum;
4922 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004923
Sander de Smalen50d87022018-04-19 07:35:08 +00004924 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004925 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004926 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004927 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004928
Sander de Smalen50d87022018-04-19 07:35:08 +00004929 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004930 return true;
4931
Sander de Smalen50d87022018-04-19 07:35:08 +00004932 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004933 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004934 }
4935
Sander de Smalen50d87022018-04-19 07:35:08 +00004936 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004937 StringRef Kind;
4938 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004939 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004940 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004941
Sander de Smalen50d87022018-04-19 07:35:08 +00004942 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004943 return true;
4944
Sander de Smalen50d87022018-04-19 07:35:08 +00004945 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004946 return Error(SRegLoc,
4947 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004948 }
4949
Sander de Smalen50d87022018-04-19 07:35:08 +00004950 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00004951 StringRef Kind;
4952 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004953 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004954
Sander de Smalen50d87022018-04-19 07:35:08 +00004955 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00004956 return true;
4957
Sander de Smalen50d87022018-04-19 07:35:08 +00004958 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00004959 return Error(SRegLoc,
4960 "sve predicate register without type specifier expected");
4961 }
4962
Sander de Smalen50d87022018-04-19 07:35:08 +00004963 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00004964 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004965
4966 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004967 if (parseToken(AsmToken::EndOfStatement,
4968 "unexpected input in .req directive"))
4969 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004970
Sander de Smalen8e607342017-11-15 15:44:43 +00004971 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004972 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004973 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4974
Nirav Dave2364748a2016-09-16 18:30:20 +00004975 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004976}
4977
4978/// parseDirectiveUneq
4979/// ::= .unreq registername
4980bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004981 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004982 if (getTok().isNot(AsmToken::Identifier))
4983 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004984 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4985 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004986 if (parseToken(AsmToken::EndOfStatement))
4987 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004988 return false;
4989}
4990
Tim Northover3b0846e2014-05-24 12:50:23 +00004991bool
4992AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4993 AArch64MCExpr::VariantKind &ELFRefKind,
4994 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4995 int64_t &Addend) {
4996 ELFRefKind = AArch64MCExpr::VK_INVALID;
4997 DarwinRefKind = MCSymbolRefExpr::VK_None;
4998 Addend = 0;
4999
5000 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5001 ELFRefKind = AE->getKind();
5002 Expr = AE->getSubExpr();
5003 }
5004
5005 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5006 if (SE) {
5007 // It's a simple symbol reference with no addend.
5008 DarwinRefKind = SE->getKind();
5009 return true;
5010 }
5011
5012 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
5013 if (!BE)
5014 return false;
5015
5016 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
5017 if (!SE)
5018 return false;
5019 DarwinRefKind = SE->getKind();
5020
5021 if (BE->getOpcode() != MCBinaryExpr::Add &&
5022 BE->getOpcode() != MCBinaryExpr::Sub)
5023 return false;
5024
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00005025 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00005026 // on here than we can deal with.
5027 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
5028 if (!AddendExpr)
5029 return false;
5030
5031 Addend = AddendExpr->getValue();
5032 if (BE->getOpcode() == MCBinaryExpr::Sub)
5033 Addend = -Addend;
5034
5035 // It's some symbol reference + a constant addend, but really
5036 // shouldn't use both Darwin and ELF syntax.
5037 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5038 DarwinRefKind == MCSymbolRefExpr::VK_None;
5039}
5040
5041/// Force static initialization.
5042extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00005043 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5044 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5045 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00005046}
5047
5048#define GET_REGISTER_MATCHER
5049#define GET_SUBTARGET_FEATURE_NAME
5050#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00005051#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00005052#include "AArch64GenAsmMatcher.inc"
5053
5054// Define this matcher function after the auto-generated include so we
5055// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00005056unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00005057 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005058 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00005059 // If the kind is a token for a literal immediate, check if our asm
5060 // operand matches. This is for InstAliases which have a fixed-value
5061 // immediate in the syntax.
5062 int64_t ExpectedVal;
5063 switch (Kind) {
5064 default:
5065 return Match_InvalidOperand;
5066 case MCK__35_0:
5067 ExpectedVal = 0;
5068 break;
5069 case MCK__35_1:
5070 ExpectedVal = 1;
5071 break;
5072 case MCK__35_12:
5073 ExpectedVal = 12;
5074 break;
5075 case MCK__35_16:
5076 ExpectedVal = 16;
5077 break;
5078 case MCK__35_2:
5079 ExpectedVal = 2;
5080 break;
5081 case MCK__35_24:
5082 ExpectedVal = 24;
5083 break;
5084 case MCK__35_3:
5085 ExpectedVal = 3;
5086 break;
5087 case MCK__35_32:
5088 ExpectedVal = 32;
5089 break;
5090 case MCK__35_4:
5091 ExpectedVal = 4;
5092 break;
5093 case MCK__35_48:
5094 ExpectedVal = 48;
5095 break;
5096 case MCK__35_6:
5097 ExpectedVal = 6;
5098 break;
5099 case MCK__35_64:
5100 ExpectedVal = 64;
5101 break;
5102 case MCK__35_8:
5103 ExpectedVal = 8;
5104 break;
5105 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005106 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005107 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005108 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005109 if (!CE)
5110 return Match_InvalidOperand;
5111 if (CE->getValue() == ExpectedVal)
5112 return Match_Success;
5113 return Match_InvalidOperand;
5114}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005115
Alex Bradbury58eba092016-11-01 16:32:05 +00005116OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005117AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5118
5119 SMLoc S = getLoc();
5120
5121 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5122 Error(S, "expected register");
5123 return MatchOperand_ParseFail;
5124 }
5125
Sander de Smalen50d87022018-04-19 07:35:08 +00005126 unsigned FirstReg;
5127 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5128 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005129 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005130
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005131 const MCRegisterClass &WRegClass =
5132 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5133 const MCRegisterClass &XRegClass =
5134 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5135
5136 bool isXReg = XRegClass.contains(FirstReg),
5137 isWReg = WRegClass.contains(FirstReg);
5138 if (!isXReg && !isWReg) {
5139 Error(S, "expected first even register of a "
5140 "consecutive same-size even/odd register pair");
5141 return MatchOperand_ParseFail;
5142 }
5143
5144 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5145 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5146
5147 if (FirstEncoding & 0x1) {
5148 Error(S, "expected first even register of a "
5149 "consecutive same-size even/odd register pair");
5150 return MatchOperand_ParseFail;
5151 }
5152
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005153 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005154 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005155 return MatchOperand_ParseFail;
5156 }
5157 // Eat the comma
5158 getParser().Lex();
5159
5160 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005161 unsigned SecondReg;
5162 Res = tryParseScalarRegister(SecondReg);
5163 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005164 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005165
Eugene Zelenko049b0172017-01-06 00:30:53 +00005166 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005167 (isXReg && !XRegClass.contains(SecondReg)) ||
5168 (isWReg && !WRegClass.contains(SecondReg))) {
5169 Error(E,"expected second odd register of a "
5170 "consecutive same-size even/odd register pair");
5171 return MatchOperand_ParseFail;
5172 }
Joel Jones504bf332016-10-24 13:37:13 +00005173
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005174 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005175 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005176 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5177 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5178 } else {
5179 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5180 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5181 }
5182
Florian Hahnc4422242017-11-07 13:07:50 +00005183 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5184 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005185
5186 return MatchOperand_Success;
5187}
Florian Hahn91f11e52017-11-07 16:45:48 +00005188
Sander de Smaleneb896b12018-04-25 09:26:47 +00005189template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005190OperandMatchResultTy
5191AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005192 const SMLoc S = getLoc();
5193 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005194 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005195 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005196
Sander de Smalen8e607342017-11-15 15:44:43 +00005197 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005198 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005199
5200 if (Res != MatchOperand_Success)
5201 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005202
5203 if (ParseSuffix && Kind.empty())
5204 return MatchOperand_NoMatch;
5205
Sander de Smalen73937b72018-04-11 07:36:10 +00005206 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5207 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005208 return MatchOperand_NoMatch;
5209
Sander de Smalen73937b72018-04-11 07:36:10 +00005210 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005211
5212 // No shift/extend is the default.
5213 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5214 Operands.push_back(AArch64Operand::CreateVectorReg(
5215 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5216
Sander de Smalenc33d6682018-06-04 06:40:55 +00005217 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5218 if (Res == MatchOperand_ParseFail)
5219 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005220 return MatchOperand_Success;
5221 }
5222
5223 // Eat the comma
5224 getParser().Lex();
5225
5226 // Match the shift
5227 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5228 Res = tryParseOptionalShiftExtend(ExtOpnd);
5229 if (Res != MatchOperand_Success)
5230 return Res;
5231
5232 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005233 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005234 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5235 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5236 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005237
5238 return MatchOperand_Success;
5239}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005240
5241OperandMatchResultTy
5242AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5243 MCAsmParser &Parser = getParser();
5244
5245 SMLoc SS = getLoc();
5246 const AsmToken &TokE = Parser.getTok();
5247 bool IsHash = TokE.is(AsmToken::Hash);
5248
5249 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5250 return MatchOperand_NoMatch;
5251
5252 int64_t Pattern;
5253 if (IsHash) {
5254 Parser.Lex(); // Eat hash
5255
5256 // Parse the immediate operand.
5257 const MCExpr *ImmVal;
5258 SS = getLoc();
5259 if (Parser.parseExpression(ImmVal))
5260 return MatchOperand_ParseFail;
5261
5262 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5263 if (!MCE)
5264 return MatchOperand_ParseFail;
5265
5266 Pattern = MCE->getValue();
5267 } else {
5268 // Parse the pattern
5269 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5270 if (!Pat)
5271 return MatchOperand_NoMatch;
5272
5273 Parser.Lex();
5274 Pattern = Pat->Encoding;
5275 assert(Pattern >= 0 && Pattern < 32);
5276 }
5277
5278 Operands.push_back(
5279 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5280 SS, getLoc(), getContext()));
5281
5282 return MatchOperand_Success;
5283}