blob: f5e762e87ce1361fc9e2e292b3d5f85e9cb68cb8 [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:
Sander de Smalen8cd1f532018-07-03 15:31:04 +0000956 case AArch64::ZPR_3bRegClassID:
957 case AArch64::ZPR_4bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000958 RK = RegKind::SVEDataVector;
959 break;
960 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000961 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000962 RK = RegKind::SVEPredicateVector;
963 break;
964 default:
965 llvm_unreachable("Unsupport register class");
966 }
967
968 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000969 AArch64MCRegisterClasses[Class].contains(getReg());
970 }
971
Sander de Smalenfd54a782018-06-04 07:07:35 +0000972 template <unsigned Class> bool isFPRasZPR() const {
973 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
974 AArch64MCRegisterClasses[Class].contains(getReg());
975 }
976
Sander de Smalencd6be962017-12-20 11:02:42 +0000977 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +0000978 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
979 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
980 return DiagnosticPredicateTy::NoMatch;
981
982 if (isSVEVectorReg<Class>() &&
983 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
984 return DiagnosticPredicateTy::Match;
985
986 return DiagnosticPredicateTy::NearMatch;
987 }
988
989 template <int ElementWidth, unsigned Class>
990 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
991 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
992 return DiagnosticPredicateTy::NoMatch;
993
994 if (isSVEVectorReg<Class>() &&
995 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
996 return DiagnosticPredicateTy::Match;
997
998 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +0000999 }
1000
Sander de Smaleneb896b12018-04-25 09:26:47 +00001001 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +00001002 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
1003 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +00001004 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
1005 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
1006 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001007 return DiagnosticPredicateTy::NoMatch;
1008
Sander de Smalen5861c262018-04-30 07:24:38 +00001009 // Give a more specific diagnostic when the user has explicitly typed in
1010 // a shift-amount that does not match what is expected, but for which
1011 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
1012 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
1013 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
1014 ShiftExtendTy == AArch64_AM::SXTW) &&
1015 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
1016 return DiagnosticPredicateTy::NoMatch;
1017
1018 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001019 return DiagnosticPredicateTy::Match;
1020
1021 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +00001022 }
1023
Tim Northover3b0846e2014-05-24 12:50:23 +00001024 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001025 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001026 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
1027 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001028
Sander de Smalen0325e302018-07-02 07:34:52 +00001029 bool isGPR64as32() const {
1030 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1031 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(Reg.RegNum);
1032 }
1033
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001034 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001035 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001036 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
1037 Reg.RegNum);
1038 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001039
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001040 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001041 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001042 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1043 Reg.RegNum);
1044 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001045
Sam Parker5f934642017-08-31 09:27:04 +00001046 template<int64_t Angle, int64_t Remainder>
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001047 DiagnosticPredicate isComplexRotation() const {
1048 if (!isImm()) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001049
1050 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001051 if (!CE) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001052 uint64_t Value = CE->getValue();
1053
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001054 if (Value % Angle == Remainder && Value <= 270)
1055 return DiagnosticPredicateTy::Match;
1056 return DiagnosticPredicateTy::NearMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001057 }
1058
Sander de Smalen149916d2018-04-20 07:24:20 +00001059 template <unsigned RegClassID> bool isGPR64() const {
1060 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1061 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1062 }
1063
1064 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001065 DiagnosticPredicate isGPR64WithShiftExtend() const {
1066 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1067 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001068
Sander de Smalenfe17a782018-04-26 12:54:42 +00001069 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1070 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1071 return DiagnosticPredicateTy::Match;
1072 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001073 }
1074
Tim Northover3b0846e2014-05-24 12:50:23 +00001075 /// Is this a vector list with the type implicit (presumably attached to the
1076 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001077 template <RegKind VectorKind, unsigned NumRegs>
1078 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001079 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001080 VectorList.NumElements == 0 &&
1081 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001082 }
1083
Sander de Smalen650234b2018-04-12 11:40:52 +00001084 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1085 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001086 bool isTypedVectorList() const {
1087 if (Kind != k_VectorList)
1088 return false;
1089 if (VectorList.Count != NumRegs)
1090 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001091 if (VectorList.RegisterKind != VectorKind)
1092 return false;
1093 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001094 return false;
1095 return VectorList.NumElements == NumElements;
1096 }
1097
Sander de Smalenc33d6682018-06-04 06:40:55 +00001098 template <int Min, int Max>
1099 DiagnosticPredicate isVectorIndex() const {
1100 if (Kind != k_VectorIndex)
1101 return DiagnosticPredicateTy::NoMatch;
1102 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1103 return DiagnosticPredicateTy::Match;
1104 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001105 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001106
Tim Northover3b0846e2014-05-24 12:50:23 +00001107 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001108
Tim Northover3b0846e2014-05-24 12:50:23 +00001109 bool isTokenEqual(StringRef Str) const {
1110 return Kind == k_Token && getToken() == Str;
1111 }
1112 bool isSysCR() const { return Kind == k_SysCR; }
1113 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001114 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001115 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1116 bool isShifter() const {
1117 if (!isShiftExtend())
1118 return false;
1119
1120 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1121 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1122 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1123 ST == AArch64_AM::MSL);
1124 }
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001125
1126 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1127 if (Kind != k_FPImm)
1128 return DiagnosticPredicateTy::NoMatch;
1129
1130 if (getFPImmIsExact()) {
1131 // Lookup the immediate from table of supported immediates.
1132 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1133 assert(Desc && "Unknown enum value");
1134
1135 // Calculate its FP value.
1136 APFloat RealVal(APFloat::IEEEdouble());
1137 if (RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero) !=
1138 APFloat::opOK)
1139 llvm_unreachable("FP immediate is not exact");
1140
1141 if (getFPImm().bitwiseIsEqual(RealVal))
1142 return DiagnosticPredicateTy::Match;
1143 }
1144
1145 return DiagnosticPredicateTy::NearMatch;
1146 }
1147
1148 template <unsigned ImmA, unsigned ImmB>
1149 DiagnosticPredicate isExactFPImm() const {
1150 DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1151 if ((Res = isExactFPImm<ImmA>()))
1152 return DiagnosticPredicateTy::Match;
1153 if ((Res = isExactFPImm<ImmB>()))
1154 return DiagnosticPredicateTy::Match;
1155 return Res;
1156 }
1157
Tim Northover3b0846e2014-05-24 12:50:23 +00001158 bool isExtend() const {
1159 if (!isShiftExtend())
1160 return false;
1161
1162 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1163 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1164 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1165 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1166 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1167 ET == AArch64_AM::LSL) &&
1168 getShiftExtendAmount() <= 4;
1169 }
1170
1171 bool isExtend64() const {
1172 if (!isExtend())
1173 return false;
1174 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1175 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1176 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1177 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001178
Tim Northover3b0846e2014-05-24 12:50:23 +00001179 bool isExtendLSL64() const {
1180 if (!isExtend())
1181 return false;
1182 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1183 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1184 ET == AArch64_AM::LSL) &&
1185 getShiftExtendAmount() <= 4;
1186 }
1187
1188 template<int Width> bool isMemXExtend() const {
1189 if (!isExtend())
1190 return false;
1191 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1192 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1193 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1194 getShiftExtendAmount() == 0);
1195 }
1196
1197 template<int Width> bool isMemWExtend() const {
1198 if (!isExtend())
1199 return false;
1200 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1201 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1202 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1203 getShiftExtendAmount() == 0);
1204 }
1205
1206 template <unsigned width>
1207 bool isArithmeticShifter() const {
1208 if (!isShifter())
1209 return false;
1210
1211 // An arithmetic shifter is LSL, LSR, or ASR.
1212 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1213 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1214 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1215 }
1216
1217 template <unsigned width>
1218 bool isLogicalShifter() const {
1219 if (!isShifter())
1220 return false;
1221
1222 // A logical shifter is LSL, LSR, ASR or ROR.
1223 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1224 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1225 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1226 getShiftExtendAmount() < width;
1227 }
1228
1229 bool isMovImm32Shifter() const {
1230 if (!isShifter())
1231 return false;
1232
1233 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1234 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1235 if (ST != AArch64_AM::LSL)
1236 return false;
1237 uint64_t Val = getShiftExtendAmount();
1238 return (Val == 0 || Val == 16);
1239 }
1240
1241 bool isMovImm64Shifter() const {
1242 if (!isShifter())
1243 return false;
1244
1245 // A MOVi shifter is LSL of 0 or 16.
1246 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1247 if (ST != AArch64_AM::LSL)
1248 return false;
1249 uint64_t Val = getShiftExtendAmount();
1250 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1251 }
1252
1253 bool isLogicalVecShifter() const {
1254 if (!isShifter())
1255 return false;
1256
1257 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1258 unsigned Shift = getShiftExtendAmount();
1259 return getShiftExtendType() == AArch64_AM::LSL &&
1260 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1261 }
1262
1263 bool isLogicalVecHalfWordShifter() const {
1264 if (!isLogicalVecShifter())
1265 return false;
1266
1267 // A logical vector shifter is a left shift by 0 or 8.
1268 unsigned Shift = getShiftExtendAmount();
1269 return getShiftExtendType() == AArch64_AM::LSL &&
1270 (Shift == 0 || Shift == 8);
1271 }
1272
1273 bool isMoveVecShifter() const {
1274 if (!isShiftExtend())
1275 return false;
1276
1277 // A logical vector shifter is a left shift by 8 or 16.
1278 unsigned Shift = getShiftExtendAmount();
1279 return getShiftExtendType() == AArch64_AM::MSL &&
1280 (Shift == 8 || Shift == 16);
1281 }
1282
1283 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1284 // to LDUR/STUR when the offset is not legal for the former but is for
1285 // the latter. As such, in addition to checking for being a legal unscaled
1286 // address, also check that it is not a legal scaled address. This avoids
1287 // ambiguity in the matcher.
1288 template<int Width>
1289 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001290 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001291 }
1292
1293 bool isAdrpLabel() const {
1294 // Validation was handled during parsing, so we just sanity check that
1295 // something didn't go haywire.
1296 if (!isImm())
1297 return false;
1298
1299 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1300 int64_t Val = CE->getValue();
1301 int64_t Min = - (4096 * (1LL << (21 - 1)));
1302 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1303 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1304 }
1305
1306 return true;
1307 }
1308
1309 bool isAdrLabel() const {
1310 // Validation was handled during parsing, so we just sanity check that
1311 // something didn't go haywire.
1312 if (!isImm())
1313 return false;
1314
1315 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1316 int64_t Val = CE->getValue();
1317 int64_t Min = - (1LL << (21 - 1));
1318 int64_t Max = ((1LL << (21 - 1)) - 1);
1319 return Val >= Min && Val <= Max;
1320 }
1321
1322 return true;
1323 }
1324
1325 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1326 // Add as immediates when possible. Null MCExpr = 0.
1327 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001328 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001329 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001330 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001331 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001332 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001333 }
1334
1335 void addRegOperands(MCInst &Inst, unsigned N) const {
1336 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001337 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001338 }
1339
1340 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1341 assert(N == 1 && "Invalid number of operands!");
1342 assert(
1343 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1344
1345 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1346 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1347 RI->getEncodingValue(getReg()));
1348
Jim Grosbache9119e42015-05-13 18:37:00 +00001349 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001350 }
1351
Sander de Smalen0325e302018-07-02 07:34:52 +00001352 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1353 assert(N == 1 && "Invalid number of operands!");
1354 assert(
1355 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(getReg()));
1356
1357 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1358 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID).getRegister(
1359 RI->getEncodingValue(getReg()));
1360
1361 Inst.addOperand(MCOperand::createReg(Reg));
1362 }
1363
Sander de Smalenfd54a782018-06-04 07:07:35 +00001364 template <int Width>
1365 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1366 unsigned Base;
1367 switch (Width) {
1368 case 8: Base = AArch64::B0; break;
1369 case 16: Base = AArch64::H0; break;
1370 case 32: Base = AArch64::S0; break;
1371 case 64: Base = AArch64::D0; break;
1372 case 128: Base = AArch64::Q0; break;
1373 default:
1374 llvm_unreachable("Unsupported width");
1375 }
1376 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1377 }
1378
Tim Northover3b0846e2014-05-24 12:50:23 +00001379 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1380 assert(N == 1 && "Invalid number of operands!");
1381 assert(
1382 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001383 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001384 }
1385
1386 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1387 assert(N == 1 && "Invalid number of operands!");
1388 assert(
1389 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001390 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001391 }
1392
1393 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1394 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001395 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001396 }
1397
Sander de Smalen525e3222018-04-12 13:19:32 +00001398 enum VecListIndexType {
1399 VecListIdx_DReg = 0,
1400 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001401 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001402 };
1403
1404 template <VecListIndexType RegTy, unsigned NumRegs>
1405 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001406 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001407 static const unsigned FirstRegs[][5] = {
1408 /* DReg */ { AArch64::Q0,
1409 AArch64::D0, AArch64::D0_D1,
1410 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1411 /* QReg */ { AArch64::Q0,
1412 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001413 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1414 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001415 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001416 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001417 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001418
Sander de Smalen7a210db2018-04-16 10:46:18 +00001419 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1420 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001421
Sander de Smalen525e3222018-04-12 13:19:32 +00001422 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1423 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1424 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001425 }
1426
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001427 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001428 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001429 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001430 }
1431
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001432 template <unsigned ImmIs0, unsigned ImmIs1>
1433 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1434 assert(N == 1 && "Invalid number of operands!");
1435 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1436 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1437 }
1438
Tim Northover3b0846e2014-05-24 12:50:23 +00001439 void addImmOperands(MCInst &Inst, unsigned N) const {
1440 assert(N == 1 && "Invalid number of operands!");
1441 // If this is a pageoff symrefexpr with an addend, adjust the addend
1442 // to be only the page-offset portion. Otherwise, just add the expr
1443 // as-is.
1444 addExpr(Inst, getImm());
1445 }
1446
Sander de Smalen62770792018-05-25 09:47:52 +00001447 template <int Shift>
1448 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001449 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001450 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1451 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1452 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1453 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001454 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001455 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001456 } else {
1457 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001458 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001459 }
1460 }
1461
Sander de Smalen62770792018-05-25 09:47:52 +00001462 template <int Shift>
1463 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001464 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001465 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1466 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1467 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1468 } else
1469 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001470 }
1471
Tim Northover3b0846e2014-05-24 12:50:23 +00001472 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1473 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001474 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001475 }
1476
1477 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1478 assert(N == 1 && "Invalid number of operands!");
1479 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1480 if (!MCE)
1481 addExpr(Inst, getImm());
1482 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001483 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001484 }
1485
1486 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1487 addImmOperands(Inst, N);
1488 }
1489
1490 template<int Scale>
1491 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1492 assert(N == 1 && "Invalid number of operands!");
1493 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1494
1495 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001496 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001497 return;
1498 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001499 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001500 }
1501
Sander de Smalen5c625982018-04-13 12:56:14 +00001502 template <int Scale>
1503 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1504 assert(N == 1 && "Invalid number of operands!");
1505 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1506 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1507 }
1508
Sander de Smalena1c259c2018-01-29 13:05:38 +00001509 template <typename T>
1510 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001511 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001512 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001513 typename std::make_unsigned<T>::type Val = MCE->getValue();
1514 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001515 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001516 }
1517
Sander de Smalena1c259c2018-01-29 13:05:38 +00001518 template <typename T>
1519 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001520 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001521 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001522 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1523 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001524 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001525 }
1526
Tim Northover3b0846e2014-05-24 12:50:23 +00001527 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1528 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001529 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001530 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001531 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001532 }
1533
1534 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1535 // Branch operands don't encode the low bits, so shift them off
1536 // here. If it's a label, however, just put it on directly as there's
1537 // not enough information now to do anything.
1538 assert(N == 1 && "Invalid number of operands!");
1539 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1540 if (!MCE) {
1541 addExpr(Inst, getImm());
1542 return;
1543 }
1544 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001545 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001546 }
1547
1548 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1549 // Branch operands don't encode the low bits, so shift them off
1550 // here. If it's a label, however, just put it on directly as there's
1551 // not enough information now to do anything.
1552 assert(N == 1 && "Invalid number of operands!");
1553 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1554 if (!MCE) {
1555 addExpr(Inst, getImm());
1556 return;
1557 }
1558 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001559 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001560 }
1561
1562 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1563 // Branch operands don't encode the low bits, so shift them off
1564 // here. If it's a label, however, just put it on directly as there's
1565 // not enough information now to do anything.
1566 assert(N == 1 && "Invalid number of operands!");
1567 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1568 if (!MCE) {
1569 addExpr(Inst, getImm());
1570 return;
1571 }
1572 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001573 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001574 }
1575
1576 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1577 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001578 Inst.addOperand(MCOperand::createImm(
1579 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
Tim Northover3b0846e2014-05-24 12:50:23 +00001580 }
1581
1582 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1583 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001584 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001585 }
1586
1587 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1588 assert(N == 1 && "Invalid number of operands!");
1589
Jim Grosbache9119e42015-05-13 18:37:00 +00001590 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001591 }
1592
1593 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1594 assert(N == 1 && "Invalid number of operands!");
1595
Jim Grosbache9119e42015-05-13 18:37:00 +00001596 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001597 }
1598
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001599 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1600 assert(N == 1 && "Invalid number of operands!");
1601
1602 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1603 }
1604
1605 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001606 assert(N == 1 && "Invalid number of operands!");
1607
Jim Grosbache9119e42015-05-13 18:37:00 +00001608 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001609 }
1610
1611 void addSysCROperands(MCInst &Inst, unsigned N) const {
1612 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001613 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001614 }
1615
1616 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1617 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001618 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001619 }
1620
Oliver Stannarda34e4702015-12-01 10:48:51 +00001621 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1622 assert(N == 1 && "Invalid number of operands!");
1623 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1624 }
1625
Tim Northover3b0846e2014-05-24 12:50:23 +00001626 void addShifterOperands(MCInst &Inst, unsigned N) const {
1627 assert(N == 1 && "Invalid number of operands!");
1628 unsigned Imm =
1629 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001630 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001631 }
1632
1633 void addExtendOperands(MCInst &Inst, unsigned N) const {
1634 assert(N == 1 && "Invalid number of operands!");
1635 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1636 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1637 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001638 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001639 }
1640
1641 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1642 assert(N == 1 && "Invalid number of operands!");
1643 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1644 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1645 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001646 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001647 }
1648
1649 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1650 assert(N == 2 && "Invalid number of operands!");
1651 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1652 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001653 Inst.addOperand(MCOperand::createImm(IsSigned));
1654 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001655 }
1656
1657 // For 8-bit load/store instructions with a register offset, both the
1658 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1659 // they're disambiguated by whether the shift was explicit or implicit rather
1660 // than its size.
1661 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1662 assert(N == 2 && "Invalid number of operands!");
1663 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1664 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001665 Inst.addOperand(MCOperand::createImm(IsSigned));
1666 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001667 }
1668
1669 template<int Shift>
1670 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1671 assert(N == 1 && "Invalid number of operands!");
1672
1673 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1674 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001675 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001676 }
1677
1678 template<int Shift>
1679 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1680 assert(N == 1 && "Invalid number of operands!");
1681
1682 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1683 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001684 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001685 }
1686
Sam Parker5f934642017-08-31 09:27:04 +00001687 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1688 assert(N == 1 && "Invalid number of operands!");
1689 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1690 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1691 }
1692
1693 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1694 assert(N == 1 && "Invalid number of operands!");
1695 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1696 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1697 }
1698
Tim Northover3b0846e2014-05-24 12:50:23 +00001699 void print(raw_ostream &OS) const override;
1700
David Blaikie960ea3f2014-06-08 16:18:35 +00001701 static std::unique_ptr<AArch64Operand>
1702 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1703 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001704 Op->Tok.Data = Str.data();
1705 Op->Tok.Length = Str.size();
1706 Op->Tok.IsSuffix = IsSuffix;
1707 Op->StartLoc = S;
1708 Op->EndLoc = S;
1709 return Op;
1710 }
1711
David Blaikie960ea3f2014-06-08 16:18:35 +00001712 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001713 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
Sander de Smalen0325e302018-07-02 07:34:52 +00001714 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
Sander de Smalen149916d2018-04-20 07:24:20 +00001715 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1716 unsigned ShiftAmount = 0,
1717 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001718 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001719 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001720 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001721 Op->Reg.ElementWidth = 0;
Sander de Smalen0325e302018-07-02 07:34:52 +00001722 Op->Reg.EqualityTy = EqTy;
Sander de Smalen149916d2018-04-20 07:24:20 +00001723 Op->Reg.ShiftExtend.Type = ExtTy;
1724 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1725 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001726 Op->StartLoc = S;
1727 Op->EndLoc = E;
1728 return Op;
1729 }
1730
David Blaikie960ea3f2014-06-08 16:18:35 +00001731 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001732 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001733 SMLoc S, SMLoc E, MCContext &Ctx,
1734 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1735 unsigned ShiftAmount = 0,
1736 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001737 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1738 Kind == RegKind::SVEPredicateVector) &&
1739 "Invalid vector kind");
Sander de Smalen0325e302018-07-02 07:34:52 +00001740 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
Sander de Smalen149916d2018-04-20 07:24:20 +00001741 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001742 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001743 return Op;
1744 }
1745
1746 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001747 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001748 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1749 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001750 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001751 Op->VectorList.RegNum = RegNum;
1752 Op->VectorList.Count = Count;
1753 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001754 Op->VectorList.ElementWidth = ElementWidth;
1755 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001756 Op->StartLoc = S;
1757 Op->EndLoc = E;
1758 return Op;
1759 }
1760
David Blaikie960ea3f2014-06-08 16:18:35 +00001761 static std::unique_ptr<AArch64Operand>
1762 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1763 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001764 Op->VectorIndex.Val = Idx;
1765 Op->StartLoc = S;
1766 Op->EndLoc = E;
1767 return Op;
1768 }
1769
David Blaikie960ea3f2014-06-08 16:18:35 +00001770 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1771 SMLoc E, MCContext &Ctx) {
1772 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001773 Op->Imm.Val = Val;
1774 Op->StartLoc = S;
1775 Op->EndLoc = E;
1776 return Op;
1777 }
1778
David Blaikie960ea3f2014-06-08 16:18:35 +00001779 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1780 unsigned ShiftAmount,
1781 SMLoc S, SMLoc E,
1782 MCContext &Ctx) {
1783 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001784 Op->ShiftedImm .Val = Val;
1785 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1786 Op->StartLoc = S;
1787 Op->EndLoc = E;
1788 return Op;
1789 }
1790
David Blaikie960ea3f2014-06-08 16:18:35 +00001791 static std::unique_ptr<AArch64Operand>
1792 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1793 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001794 Op->CondCode.Code = Code;
1795 Op->StartLoc = S;
1796 Op->EndLoc = E;
1797 return Op;
1798 }
1799
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001800 static std::unique_ptr<AArch64Operand>
1801 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001802 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001803 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
1804 Op->FPImm.IsExact = IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +00001805 Op->StartLoc = S;
1806 Op->EndLoc = S;
1807 return Op;
1808 }
1809
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001810 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1811 StringRef Str,
1812 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001813 MCContext &Ctx) {
1814 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001815 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001816 Op->Barrier.Data = Str.data();
1817 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001818 Op->StartLoc = S;
1819 Op->EndLoc = S;
1820 return Op;
1821 }
1822
Tim Northover7cd58932015-01-22 17:23:04 +00001823 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1824 uint32_t MRSReg,
1825 uint32_t MSRReg,
1826 uint32_t PStateField,
1827 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001828 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001829 Op->SysReg.Data = Str.data();
1830 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001831 Op->SysReg.MRSReg = MRSReg;
1832 Op->SysReg.MSRReg = MSRReg;
1833 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001834 Op->StartLoc = S;
1835 Op->EndLoc = S;
1836 return Op;
1837 }
1838
David Blaikie960ea3f2014-06-08 16:18:35 +00001839 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1840 SMLoc E, MCContext &Ctx) {
1841 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001842 Op->SysCRImm.Val = Val;
1843 Op->StartLoc = S;
1844 Op->EndLoc = E;
1845 return Op;
1846 }
1847
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001848 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1849 StringRef Str,
1850 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001851 MCContext &Ctx) {
1852 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001853 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001854 Op->Barrier.Data = Str.data();
1855 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001856 Op->StartLoc = S;
1857 Op->EndLoc = S;
1858 return Op;
1859 }
1860
Oliver Stannarda34e4702015-12-01 10:48:51 +00001861 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1862 StringRef Str,
1863 SMLoc S,
1864 MCContext &Ctx) {
1865 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1866 Op->PSBHint.Val = Val;
1867 Op->PSBHint.Data = Str.data();
1868 Op->PSBHint.Length = Str.size();
1869 Op->StartLoc = S;
1870 Op->EndLoc = S;
1871 return Op;
1872 }
1873
David Blaikie960ea3f2014-06-08 16:18:35 +00001874 static std::unique_ptr<AArch64Operand>
1875 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1876 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1877 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001878 Op->ShiftExtend.Type = ShOp;
1879 Op->ShiftExtend.Amount = Val;
1880 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1881 Op->StartLoc = S;
1882 Op->EndLoc = E;
1883 return Op;
1884 }
1885};
1886
1887} // end anonymous namespace.
1888
1889void AArch64Operand::print(raw_ostream &OS) const {
1890 switch (Kind) {
1891 case k_FPImm:
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001892 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
1893 if (!getFPImmIsExact())
1894 OS << " (inexact)";
1895 OS << ">";
Tim Northover3b0846e2014-05-24 12:50:23 +00001896 break;
1897 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001898 StringRef Name = getBarrierName();
1899 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001900 OS << "<barrier " << Name << ">";
1901 else
1902 OS << "<barrier invalid #" << getBarrier() << ">";
1903 break;
1904 }
1905 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001906 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001907 break;
1908 case k_ShiftedImm: {
1909 unsigned Shift = getShiftedImmShift();
1910 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001911 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001912 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1913 break;
1914 }
1915 case k_CondCode:
1916 OS << "<condcode " << getCondCode() << ">";
1917 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001918 case k_VectorList: {
1919 OS << "<vectorlist ";
1920 unsigned Reg = getVectorListStart();
1921 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1922 OS << Reg + i << " ";
1923 OS << ">";
1924 break;
1925 }
1926 case k_VectorIndex:
1927 OS << "<vectorindex " << getVectorIndex() << ">";
1928 break;
1929 case k_SysReg:
1930 OS << "<sysreg: " << getSysReg() << '>';
1931 break;
1932 case k_Token:
1933 OS << "'" << getToken() << "'";
1934 break;
1935 case k_SysCR:
1936 OS << "c" << getSysCR();
1937 break;
1938 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001939 StringRef Name = getPrefetchName();
1940 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001941 OS << "<prfop " << Name << ">";
1942 else
1943 OS << "<prfop invalid #" << getPrefetch() << ">";
1944 break;
1945 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001946 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001947 OS << getPSBHintName();
1948 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00001949 case k_Register:
1950 OS << "<register " << getReg() << ">";
1951 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
1952 break;
1953 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001954 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001955 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1956 << getShiftExtendAmount();
1957 if (!hasShiftExtendAmount())
1958 OS << "<imp>";
1959 OS << '>';
1960 break;
1961 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001962}
1963
1964/// @name Auto-generated Match Functions
1965/// {
1966
1967static unsigned MatchRegisterName(StringRef Name);
1968
1969/// }
1970
Florian Hahnc4422242017-11-07 13:07:50 +00001971static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001972 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001973 .Case("v0", AArch64::Q0)
1974 .Case("v1", AArch64::Q1)
1975 .Case("v2", AArch64::Q2)
1976 .Case("v3", AArch64::Q3)
1977 .Case("v4", AArch64::Q4)
1978 .Case("v5", AArch64::Q5)
1979 .Case("v6", AArch64::Q6)
1980 .Case("v7", AArch64::Q7)
1981 .Case("v8", AArch64::Q8)
1982 .Case("v9", AArch64::Q9)
1983 .Case("v10", AArch64::Q10)
1984 .Case("v11", AArch64::Q11)
1985 .Case("v12", AArch64::Q12)
1986 .Case("v13", AArch64::Q13)
1987 .Case("v14", AArch64::Q14)
1988 .Case("v15", AArch64::Q15)
1989 .Case("v16", AArch64::Q16)
1990 .Case("v17", AArch64::Q17)
1991 .Case("v18", AArch64::Q18)
1992 .Case("v19", AArch64::Q19)
1993 .Case("v20", AArch64::Q20)
1994 .Case("v21", AArch64::Q21)
1995 .Case("v22", AArch64::Q22)
1996 .Case("v23", AArch64::Q23)
1997 .Case("v24", AArch64::Q24)
1998 .Case("v25", AArch64::Q25)
1999 .Case("v26", AArch64::Q26)
2000 .Case("v27", AArch64::Q27)
2001 .Case("v28", AArch64::Q28)
2002 .Case("v29", AArch64::Q29)
2003 .Case("v30", AArch64::Q30)
2004 .Case("v31", AArch64::Q31)
2005 .Default(0);
2006}
2007
Sander de Smalen73937b72018-04-11 07:36:10 +00002008/// Returns an optional pair of (#elements, element-width) if Suffix
2009/// is a valid vector kind. Where the number of elements in a vector
2010/// or the vector width is implicit or explicitly unknown (but still a
2011/// valid suffix kind), 0 is used.
2012static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2013 RegKind VectorKind) {
2014 std::pair<int, int> Res = {-1, -1};
2015
2016 switch (VectorKind) {
2017 case RegKind::NeonVector:
2018 Res =
2019 StringSwitch<std::pair<int, int>>(Suffix.lower())
2020 .Case("", {0, 0})
2021 .Case(".1d", {1, 64})
2022 .Case(".1q", {1, 128})
2023 // '.2h' needed for fp16 scalar pairwise reductions
2024 .Case(".2h", {2, 16})
2025 .Case(".2s", {2, 32})
2026 .Case(".2d", {2, 64})
2027 // '.4b' is another special case for the ARMv8.2a dot product
2028 // operand
2029 .Case(".4b", {4, 8})
2030 .Case(".4h", {4, 16})
2031 .Case(".4s", {4, 32})
2032 .Case(".8b", {8, 8})
2033 .Case(".8h", {8, 16})
2034 .Case(".16b", {16, 8})
2035 // Accept the width neutral ones, too, for verbose syntax. If those
2036 // aren't used in the right places, the token operand won't match so
2037 // all will work out.
2038 .Case(".b", {0, 8})
2039 .Case(".h", {0, 16})
2040 .Case(".s", {0, 32})
2041 .Case(".d", {0, 64})
2042 .Default({-1, -1});
2043 break;
2044 case RegKind::SVEPredicateVector:
2045 case RegKind::SVEDataVector:
2046 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2047 .Case("", {0, 0})
2048 .Case(".b", {0, 8})
2049 .Case(".h", {0, 16})
2050 .Case(".s", {0, 32})
2051 .Case(".d", {0, 64})
2052 .Case(".q", {0, 128})
2053 .Default({-1, -1});
2054 break;
2055 default:
2056 llvm_unreachable("Unsupported RegKind");
2057 }
2058
2059 if (Res == std::make_pair(-1, -1))
2060 return Optional<std::pair<int, int>>();
2061
2062 return Optional<std::pair<int, int>>(Res);
2063}
2064
2065static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2066 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002067}
2068
Florian Hahn91f11e52017-11-07 16:45:48 +00002069static unsigned matchSVEDataVectorRegName(StringRef Name) {
2070 return StringSwitch<unsigned>(Name.lower())
2071 .Case("z0", AArch64::Z0)
2072 .Case("z1", AArch64::Z1)
2073 .Case("z2", AArch64::Z2)
2074 .Case("z3", AArch64::Z3)
2075 .Case("z4", AArch64::Z4)
2076 .Case("z5", AArch64::Z5)
2077 .Case("z6", AArch64::Z6)
2078 .Case("z7", AArch64::Z7)
2079 .Case("z8", AArch64::Z8)
2080 .Case("z9", AArch64::Z9)
2081 .Case("z10", AArch64::Z10)
2082 .Case("z11", AArch64::Z11)
2083 .Case("z12", AArch64::Z12)
2084 .Case("z13", AArch64::Z13)
2085 .Case("z14", AArch64::Z14)
2086 .Case("z15", AArch64::Z15)
2087 .Case("z16", AArch64::Z16)
2088 .Case("z17", AArch64::Z17)
2089 .Case("z18", AArch64::Z18)
2090 .Case("z19", AArch64::Z19)
2091 .Case("z20", AArch64::Z20)
2092 .Case("z21", AArch64::Z21)
2093 .Case("z22", AArch64::Z22)
2094 .Case("z23", AArch64::Z23)
2095 .Case("z24", AArch64::Z24)
2096 .Case("z25", AArch64::Z25)
2097 .Case("z26", AArch64::Z26)
2098 .Case("z27", AArch64::Z27)
2099 .Case("z28", AArch64::Z28)
2100 .Case("z29", AArch64::Z29)
2101 .Case("z30", AArch64::Z30)
2102 .Case("z31", AArch64::Z31)
2103 .Default(0);
2104}
2105
Sander de Smalencd6be962017-12-20 11:02:42 +00002106static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2107 return StringSwitch<unsigned>(Name.lower())
2108 .Case("p0", AArch64::P0)
2109 .Case("p1", AArch64::P1)
2110 .Case("p2", AArch64::P2)
2111 .Case("p3", AArch64::P3)
2112 .Case("p4", AArch64::P4)
2113 .Case("p5", AArch64::P5)
2114 .Case("p6", AArch64::P6)
2115 .Case("p7", AArch64::P7)
2116 .Case("p8", AArch64::P8)
2117 .Case("p9", AArch64::P9)
2118 .Case("p10", AArch64::P10)
2119 .Case("p11", AArch64::P11)
2120 .Case("p12", AArch64::P12)
2121 .Case("p13", AArch64::P13)
2122 .Case("p14", AArch64::P14)
2123 .Case("p15", AArch64::P15)
2124 .Default(0);
2125}
2126
Tim Northover3b0846e2014-05-24 12:50:23 +00002127bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2128 SMLoc &EndLoc) {
2129 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002130 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002131 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002132 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002133}
2134
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002135// Matches a register name or register alias previously defined by '.req'
2136unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002137 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002138 unsigned RegNum = 0;
2139 if ((RegNum = matchSVEDataVectorRegName(Name)))
2140 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2141
Sander de Smalencd6be962017-12-20 11:02:42 +00002142 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2143 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2144
Sander de Smalenc067c302017-12-20 09:45:45 +00002145 if ((RegNum = MatchNeonVectorRegName(Name)))
2146 return Kind == RegKind::NeonVector ? RegNum : 0;
2147
2148 // The parsed register must be of RegKind Scalar
2149 if ((RegNum = MatchRegisterName(Name)))
2150 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002151
Florian Hahnc4422242017-11-07 13:07:50 +00002152 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002153 // Handle a few common aliases of registers.
2154 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2155 .Case("fp", AArch64::FP)
2156 .Case("lr", AArch64::LR)
2157 .Case("x31", AArch64::XZR)
2158 .Case("w31", AArch64::WZR)
2159 .Default(0))
2160 return Kind == RegKind::Scalar ? RegNum : 0;
2161
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002162 // Check for aliases registered via .req. Canonicalize to lower case.
2163 // That's more consistent since register names are case insensitive, and
2164 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2165 auto Entry = RegisterReqs.find(Name.lower());
2166 if (Entry == RegisterReqs.end())
2167 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002168
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002169 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002170 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002171 RegNum = Entry->getValue().second;
2172 }
2173 return RegNum;
2174}
2175
Sander de Smalen50d87022018-04-19 07:35:08 +00002176/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002177/// Identifier when called, and if it is a register name the token is eaten and
2178/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002179OperandMatchResultTy
2180AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002181 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002182 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002183 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002184 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002185
2186 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002187 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2188 if (Reg == 0)
2189 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002190
Sander de Smalen50d87022018-04-19 07:35:08 +00002191 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002192 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002193 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002194}
2195
Tim Northover3b0846e2014-05-24 12:50:23 +00002196/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002197OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002198AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002199 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002200 SMLoc S = getLoc();
2201
2202 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2203 Error(S, "Expected cN operand where 0 <= N <= 15");
2204 return MatchOperand_ParseFail;
2205 }
2206
2207 StringRef Tok = Parser.getTok().getIdentifier();
2208 if (Tok[0] != 'c' && Tok[0] != 'C') {
2209 Error(S, "Expected cN operand where 0 <= N <= 15");
2210 return MatchOperand_ParseFail;
2211 }
2212
2213 uint32_t CRNum;
2214 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2215 if (BadNum || CRNum > 15) {
2216 Error(S, "Expected cN operand where 0 <= N <= 15");
2217 return MatchOperand_ParseFail;
2218 }
2219
2220 Parser.Lex(); // Eat identifier token.
2221 Operands.push_back(
2222 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2223 return MatchOperand_Success;
2224}
2225
2226/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002227template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002228OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002229AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002230 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002231 SMLoc S = getLoc();
2232 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002233
2234 auto LookupByName = [](StringRef N) {
2235 if (IsSVEPrefetch) {
2236 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2237 return Optional<unsigned>(Res->Encoding);
2238 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2239 return Optional<unsigned>(Res->Encoding);
2240 return Optional<unsigned>();
2241 };
2242
2243 auto LookupByEncoding = [](unsigned E) {
2244 if (IsSVEPrefetch) {
2245 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2246 return Optional<StringRef>(Res->Name);
2247 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2248 return Optional<StringRef>(Res->Name);
2249 return Optional<StringRef>();
2250 };
2251 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2252
Tim Northover3b0846e2014-05-24 12:50:23 +00002253 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002254 // Eat optional hash.
2255 if (parseOptionalToken(AsmToken::Hash) ||
2256 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002257 const MCExpr *ImmVal;
2258 if (getParser().parseExpression(ImmVal))
2259 return MatchOperand_ParseFail;
2260
2261 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2262 if (!MCE) {
2263 TokError("immediate value expected for prefetch operand");
2264 return MatchOperand_ParseFail;
2265 }
2266 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002267 if (prfop > MaxVal) {
2268 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2269 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002270 return MatchOperand_ParseFail;
2271 }
2272
Sander de Smalen93380372018-05-14 11:54:41 +00002273 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002274 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002275 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002276 return MatchOperand_Success;
2277 }
2278
2279 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002280 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002281 return MatchOperand_ParseFail;
2282 }
2283
Sander de Smalen93380372018-05-14 11:54:41 +00002284 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002285 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002286 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002287 return MatchOperand_ParseFail;
2288 }
2289
2290 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002291 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002292 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002293 return MatchOperand_Success;
2294}
2295
Oliver Stannarda34e4702015-12-01 10:48:51 +00002296/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002297OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002298AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2299 MCAsmParser &Parser = getParser();
2300 SMLoc S = getLoc();
2301 const AsmToken &Tok = Parser.getTok();
2302 if (Tok.isNot(AsmToken::Identifier)) {
2303 TokError("invalid operand for instruction");
2304 return MatchOperand_ParseFail;
2305 }
2306
Tim Northovere6ae6762016-07-05 21:23:04 +00002307 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2308 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002309 TokError("invalid operand for instruction");
2310 return MatchOperand_ParseFail;
2311 }
2312
2313 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002314 Operands.push_back(AArch64Operand::CreatePSBHint(
2315 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002316 return MatchOperand_Success;
2317}
2318
Tim Northover3b0846e2014-05-24 12:50:23 +00002319/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2320/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002321OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002322AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002323 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002324 SMLoc S = getLoc();
2325 const MCExpr *Expr;
2326
2327 if (Parser.getTok().is(AsmToken::Hash)) {
2328 Parser.Lex(); // Eat hash token.
2329 }
2330
2331 if (parseSymbolicImmVal(Expr))
2332 return MatchOperand_ParseFail;
2333
2334 AArch64MCExpr::VariantKind ELFRefKind;
2335 MCSymbolRefExpr::VariantKind DarwinRefKind;
2336 int64_t Addend;
2337 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2338 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2339 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2340 // No modifier was specified at all; this is the syntax for an ELF basic
2341 // ADRP relocation (unfortunately).
2342 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002343 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002344 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2345 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2346 Addend != 0) {
2347 Error(S, "gotpage label reference not allowed an addend");
2348 return MatchOperand_ParseFail;
2349 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2350 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2351 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2352 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2353 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2354 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2355 // The operand must be an @page or @gotpage qualified symbolref.
2356 Error(S, "page or gotpage label reference expected");
2357 return MatchOperand_ParseFail;
2358 }
2359 }
2360
2361 // We have either a label reference possibly with addend or an immediate. The
2362 // addend is a raw value here. The linker will adjust it to only reference the
2363 // page.
2364 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2365 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2366
2367 return MatchOperand_Success;
2368}
2369
2370/// tryParseAdrLabel - Parse and validate a source label for the ADR
2371/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002372OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002373AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2374 SMLoc S = getLoc();
2375 const MCExpr *Expr;
2376
Nirav Davee833c6c2016-11-08 18:31:04 +00002377 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002378 if (getParser().parseExpression(Expr))
2379 return MatchOperand_ParseFail;
2380
2381 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2382 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2383
2384 return MatchOperand_Success;
2385}
2386
2387/// tryParseFPImm - A floating point immediate expression operand.
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002388template<bool AddFPZeroAsLiteral>
Alex Bradbury58eba092016-11-01 16:32:05 +00002389OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002390AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002391 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002392 SMLoc S = getLoc();
2393
Nirav Davee833c6c2016-11-08 18:31:04 +00002394 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002395
2396 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002397 bool isNegative = parseOptionalToken(AsmToken::Minus);
2398
Tim Northover3b0846e2014-05-24 12:50:23 +00002399 const AsmToken &Tok = Parser.getTok();
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002400 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2401 if (!Hash)
2402 return MatchOperand_NoMatch;
2403 TokError("invalid floating point immediate");
2404 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002405 }
2406
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002407 // Parse hexadecimal representation.
2408 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2409 if (Tok.getIntVal() > 255 || isNegative) {
2410 TokError("encoded floating point value out of range");
2411 return MatchOperand_ParseFail;
2412 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002413
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002414 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2415 Operands.push_back(
2416 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2417 } else {
2418 // Parse FP representation.
2419 APFloat RealVal(APFloat::IEEEdouble());
2420 auto Status =
2421 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2422 if (isNegative)
2423 RealVal.changeSign();
2424
2425 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2426 Operands.push_back(
2427 AArch64Operand::CreateToken("#0", false, S, getContext()));
2428 Operands.push_back(
2429 AArch64Operand::CreateToken(".0", false, S, getContext()));
2430 } else
2431 Operands.push_back(AArch64Operand::CreateFPImm(
2432 RealVal, Status == APFloat::opOK, S, getContext()));
2433 }
2434
2435 Parser.Lex(); // Eat the token.
2436
2437 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002438}
2439
Sander de Smalen62770792018-05-25 09:47:52 +00002440/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2441/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002442OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002443AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002444 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002445 SMLoc S = getLoc();
2446
2447 if (Parser.getTok().is(AsmToken::Hash))
2448 Parser.Lex(); // Eat '#'
2449 else if (Parser.getTok().isNot(AsmToken::Integer))
2450 // Operand should start from # or should be integer, emit error otherwise.
2451 return MatchOperand_NoMatch;
2452
2453 const MCExpr *Imm;
2454 if (parseSymbolicImmVal(Imm))
2455 return MatchOperand_ParseFail;
2456 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002457 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002458 Operands.push_back(
2459 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002460 return MatchOperand_Success;
2461 }
2462
2463 // Eat ','
2464 Parser.Lex();
2465
2466 // The optional operand must be "lsl #N" where N is non-negative.
2467 if (!Parser.getTok().is(AsmToken::Identifier) ||
2468 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2469 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2470 return MatchOperand_ParseFail;
2471 }
2472
2473 // Eat 'lsl'
2474 Parser.Lex();
2475
Nirav Davee833c6c2016-11-08 18:31:04 +00002476 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002477
2478 if (Parser.getTok().isNot(AsmToken::Integer)) {
2479 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2480 return MatchOperand_ParseFail;
2481 }
2482
2483 int64_t ShiftAmount = Parser.getTok().getIntVal();
2484
2485 if (ShiftAmount < 0) {
2486 Error(Parser.getTok().getLoc(), "positive shift amount required");
2487 return MatchOperand_ParseFail;
2488 }
2489 Parser.Lex(); // Eat the number
2490
Sander de Smalen62770792018-05-25 09:47:52 +00002491 // Just in case the optional lsl #0 is used for immediates other than zero.
2492 if (ShiftAmount == 0 && Imm != 0) {
2493 SMLoc E = Parser.getTok().getLoc();
2494 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2495 return MatchOperand_Success;
2496 }
2497
Tim Northover3b0846e2014-05-24 12:50:23 +00002498 SMLoc E = Parser.getTok().getLoc();
2499 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2500 S, E, getContext()));
2501 return MatchOperand_Success;
2502}
2503
2504/// parseCondCodeString - Parse a Condition Code string.
2505AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2506 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2507 .Case("eq", AArch64CC::EQ)
2508 .Case("ne", AArch64CC::NE)
2509 .Case("cs", AArch64CC::HS)
2510 .Case("hs", AArch64CC::HS)
2511 .Case("cc", AArch64CC::LO)
2512 .Case("lo", AArch64CC::LO)
2513 .Case("mi", AArch64CC::MI)
2514 .Case("pl", AArch64CC::PL)
2515 .Case("vs", AArch64CC::VS)
2516 .Case("vc", AArch64CC::VC)
2517 .Case("hi", AArch64CC::HI)
2518 .Case("ls", AArch64CC::LS)
2519 .Case("ge", AArch64CC::GE)
2520 .Case("lt", AArch64CC::LT)
2521 .Case("gt", AArch64CC::GT)
2522 .Case("le", AArch64CC::LE)
2523 .Case("al", AArch64CC::AL)
2524 .Case("nv", AArch64CC::NV)
2525 .Default(AArch64CC::Invalid);
Sander de Smalene31e6d42018-07-04 08:50:49 +00002526
2527 if (CC == AArch64CC::Invalid &&
2528 getSTI().getFeatureBits()[AArch64::FeatureSVE])
2529 CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2530 .Case("none", AArch64CC::EQ)
2531 .Case("any", AArch64CC::NE)
2532 .Case("nlast", AArch64CC::HS)
2533 .Case("last", AArch64CC::LO)
2534 .Case("first", AArch64CC::MI)
2535 .Case("nfrst", AArch64CC::PL)
2536 .Case("pmore", AArch64CC::HI)
2537 .Case("plast", AArch64CC::LS)
2538 .Case("tcont", AArch64CC::GE)
2539 .Case("tstop", AArch64CC::LT)
2540 .Default(AArch64CC::Invalid);
2541
Tim Northover3b0846e2014-05-24 12:50:23 +00002542 return CC;
2543}
2544
2545/// parseCondCode - Parse a Condition Code operand.
2546bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2547 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002548 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002549 SMLoc S = getLoc();
2550 const AsmToken &Tok = Parser.getTok();
2551 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2552
2553 StringRef Cond = Tok.getString();
2554 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2555 if (CC == AArch64CC::Invalid)
2556 return TokError("invalid condition code");
2557 Parser.Lex(); // Eat identifier token.
2558
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002559 if (invertCondCode) {
2560 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2561 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002562 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002563 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002564
2565 Operands.push_back(
2566 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2567 return false;
2568}
2569
2570/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2571/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002572OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002573AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002574 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002575 const AsmToken &Tok = Parser.getTok();
2576 std::string LowerID = Tok.getString().lower();
2577 AArch64_AM::ShiftExtendType ShOp =
2578 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2579 .Case("lsl", AArch64_AM::LSL)
2580 .Case("lsr", AArch64_AM::LSR)
2581 .Case("asr", AArch64_AM::ASR)
2582 .Case("ror", AArch64_AM::ROR)
2583 .Case("msl", AArch64_AM::MSL)
2584 .Case("uxtb", AArch64_AM::UXTB)
2585 .Case("uxth", AArch64_AM::UXTH)
2586 .Case("uxtw", AArch64_AM::UXTW)
2587 .Case("uxtx", AArch64_AM::UXTX)
2588 .Case("sxtb", AArch64_AM::SXTB)
2589 .Case("sxth", AArch64_AM::SXTH)
2590 .Case("sxtw", AArch64_AM::SXTW)
2591 .Case("sxtx", AArch64_AM::SXTX)
2592 .Default(AArch64_AM::InvalidShiftExtend);
2593
2594 if (ShOp == AArch64_AM::InvalidShiftExtend)
2595 return MatchOperand_NoMatch;
2596
2597 SMLoc S = Tok.getLoc();
2598 Parser.Lex();
2599
Nirav Davee833c6c2016-11-08 18:31:04 +00002600 bool Hash = parseOptionalToken(AsmToken::Hash);
2601
Tim Northover3b0846e2014-05-24 12:50:23 +00002602 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2603 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2604 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2605 ShOp == AArch64_AM::MSL) {
2606 // We expect a number here.
2607 TokError("expected #imm after shift specifier");
2608 return MatchOperand_ParseFail;
2609 }
2610
Chad Rosier2ff37b82016-12-27 16:58:09 +00002611 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002612 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2613 Operands.push_back(
2614 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2615 return MatchOperand_Success;
2616 }
2617
Chad Rosier2ff37b82016-12-27 16:58:09 +00002618 // Make sure we do actually have a number, identifier or a parenthesized
2619 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002620 SMLoc E = Parser.getTok().getLoc();
2621 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002622 !Parser.getTok().is(AsmToken::LParen) &&
2623 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002624 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002625 return MatchOperand_ParseFail;
2626 }
2627
2628 const MCExpr *ImmVal;
2629 if (getParser().parseExpression(ImmVal))
2630 return MatchOperand_ParseFail;
2631
2632 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2633 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002634 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002635 return MatchOperand_ParseFail;
2636 }
2637
Jim Grosbach57fd2622014-09-23 22:16:02 +00002638 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002639 Operands.push_back(AArch64Operand::CreateShiftExtend(
2640 ShOp, MCE->getValue(), true, S, E, getContext()));
2641 return MatchOperand_Success;
2642}
2643
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002644static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2645 if (FBS[AArch64::HasV8_1aOps])
2646 Str += "ARMv8.1a";
2647 else if (FBS[AArch64::HasV8_2aOps])
2648 Str += "ARMv8.2a";
2649 else
2650 Str += "(unknown)";
2651}
2652
2653void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2654 SMLoc S) {
2655 const uint16_t Op2 = Encoding & 7;
2656 const uint16_t Cm = (Encoding & 0x78) >> 3;
2657 const uint16_t Cn = (Encoding & 0x780) >> 7;
2658 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2659
2660 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2661
2662 Operands.push_back(
2663 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2664 Operands.push_back(
2665 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2666 Operands.push_back(
2667 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2668 Expr = MCConstantExpr::create(Op2, getContext());
2669 Operands.push_back(
2670 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2671}
2672
Tim Northover3b0846e2014-05-24 12:50:23 +00002673/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2674/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2675bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2676 OperandVector &Operands) {
2677 if (Name.find('.') != StringRef::npos)
2678 return TokError("invalid operand");
2679
2680 Mnemonic = Name;
2681 Operands.push_back(
2682 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2683
Rafael Espindola961d4692014-11-11 05:18:41 +00002684 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002685 const AsmToken &Tok = Parser.getTok();
2686 StringRef Op = Tok.getString();
2687 SMLoc S = Tok.getLoc();
2688
Tim Northover3b0846e2014-05-24 12:50:23 +00002689 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002690 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2691 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002692 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002693 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2694 std::string Str("IC " + std::string(IC->Name) + " requires ");
2695 setRequiredFeatureString(IC->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(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002699 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002700 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2701 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002702 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002703 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2704 std::string Str("DC " + std::string(DC->Name) + " requires ");
2705 setRequiredFeatureString(DC->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(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002709 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002710 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2711 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002712 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002713 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2714 std::string Str("AT " + std::string(AT->Name) + " requires ");
2715 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2716 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002717 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002718 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002719 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002720 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2721 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002722 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002723 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2724 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2725 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2726 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002727 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002728 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002729 }
2730
Tim Northover3b0846e2014-05-24 12:50:23 +00002731 Parser.Lex(); // Eat operand.
2732
2733 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2734 bool HasRegister = false;
2735
2736 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002737 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002738 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2739 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002740 HasRegister = true;
2741 }
2742
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002743 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002744 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002745 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002746 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002747
Nirav Davee833c6c2016-11-08 18:31:04 +00002748 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2749 return true;
2750
Tim Northover3b0846e2014-05-24 12:50:23 +00002751 return false;
2752}
2753
Alex Bradbury58eba092016-11-01 16:32:05 +00002754OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002755AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002756 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002757 const AsmToken &Tok = Parser.getTok();
2758
2759 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002760 if (parseOptionalToken(AsmToken::Hash) ||
2761 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002762 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002763 const MCExpr *ImmVal;
2764 SMLoc ExprLoc = getLoc();
2765 if (getParser().parseExpression(ImmVal))
2766 return MatchOperand_ParseFail;
2767 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2768 if (!MCE) {
2769 Error(ExprLoc, "immediate value expected for barrier operand");
2770 return MatchOperand_ParseFail;
2771 }
2772 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2773 Error(ExprLoc, "barrier operand out of range");
2774 return MatchOperand_ParseFail;
2775 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002776 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2777 Operands.push_back(AArch64Operand::CreateBarrier(
2778 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002779 return MatchOperand_Success;
2780 }
2781
2782 if (Tok.isNot(AsmToken::Identifier)) {
2783 TokError("invalid operand for instruction");
2784 return MatchOperand_ParseFail;
2785 }
2786
Tim Northover3b0846e2014-05-24 12:50:23 +00002787 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002788 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2789 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002790 TokError("'sy' or #imm operand expected");
2791 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002792 } else if (!DB) {
2793 TokError("invalid barrier option name");
2794 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002795 }
2796
Tim Northovere6ae6762016-07-05 21:23:04 +00002797 Operands.push_back(AArch64Operand::CreateBarrier(
2798 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002799 Parser.Lex(); // Consume the option
2800
2801 return MatchOperand_Success;
2802}
2803
Alex Bradbury58eba092016-11-01 16:32:05 +00002804OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002805AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002806 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002807 const AsmToken &Tok = Parser.getTok();
2808
2809 if (Tok.isNot(AsmToken::Identifier))
2810 return MatchOperand_NoMatch;
2811
Tim Northovere6ae6762016-07-05 21:23:04 +00002812 int MRSReg, MSRReg;
2813 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2814 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2815 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2816 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2817 } else
2818 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002819
Tim Northovere6ae6762016-07-05 21:23:04 +00002820 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2821 unsigned PStateImm = -1;
2822 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2823 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002824
Tim Northovere6ae6762016-07-05 21:23:04 +00002825 Operands.push_back(
2826 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2827 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002828 Parser.Lex(); // Eat identifier
2829
2830 return MatchOperand_Success;
2831}
2832
Florian Hahnc4422242017-11-07 13:07:50 +00002833/// tryParseNeonVectorRegister - Parse a vector register operand.
2834bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002835 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002836 if (Parser.getTok().isNot(AsmToken::Identifier))
2837 return true;
2838
2839 SMLoc S = getLoc();
2840 // Check for a vector register specifier first.
2841 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002842 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002843 OperandMatchResultTy Res =
2844 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2845 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002846 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002847
2848 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2849 if (!KindRes)
2850 return true;
2851
2852 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002853 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002854 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2855 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002856
Tim Northover3b0846e2014-05-24 12:50:23 +00002857 // If there was an explicit qualifier, that goes on as a literal text
2858 // operand.
2859 if (!Kind.empty())
2860 Operands.push_back(
2861 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2862
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002863 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2864}
2865
2866OperandMatchResultTy
2867AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002868 SMLoc SIdx = getLoc();
2869 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002870 const MCExpr *ImmVal;
2871 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002872 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002873 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2874 if (!MCE) {
2875 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002876 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002877 }
2878
2879 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002880
Nirav Davee833c6c2016-11-08 18:31:04 +00002881 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002882 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002883
2884 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2885 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002886 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002887 }
2888
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002889 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002890}
2891
Sander de Smalen73937b72018-04-11 07:36:10 +00002892// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002893// optional kind specifier. If it is a register specifier, eat the token
2894// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002895OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002896AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002897 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002898 MCAsmParser &Parser = getParser();
2899 const AsmToken &Tok = Parser.getTok();
2900
Florian Hahn91f11e52017-11-07 16:45:48 +00002901 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002902 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002903
2904 StringRef Name = Tok.getString();
2905 // If there is a kind specifier, it's separated from the register name by
2906 // a '.'.
2907 size_t Start = 0, Next = Name.find('.');
2908 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002909 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002910
2911 if (RegNum) {
2912 if (Next != StringRef::npos) {
2913 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002914 if (!isValidVectorKind(Kind, MatchKind)) {
2915 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002916 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002917 }
2918 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002919 Parser.Lex(); // Eat the register token.
2920
2921 Reg = RegNum;
2922 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002923 }
2924
Sander de Smalen8e607342017-11-15 15:44:43 +00002925 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002926}
2927
Sander de Smalencd6be962017-12-20 11:02:42 +00002928/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2929OperandMatchResultTy
2930AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2931 // Check for a SVE predicate register specifier first.
2932 const SMLoc S = getLoc();
2933 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002934 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002935 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002936 if (Res != MatchOperand_Success)
2937 return Res;
2938
Sander de Smalen73937b72018-04-11 07:36:10 +00002939 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2940 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002941 return MatchOperand_NoMatch;
2942
Sander de Smalen73937b72018-04-11 07:36:10 +00002943 unsigned ElementWidth = KindRes->second;
2944 Operands.push_back(AArch64Operand::CreateVectorReg(
2945 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2946 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002947
Sander de Smalen7868e742018-01-09 11:17:06 +00002948 // Not all predicates are followed by a '/m' or '/z'.
2949 MCAsmParser &Parser = getParser();
2950 if (Parser.getTok().isNot(AsmToken::Slash))
2951 return MatchOperand_Success;
2952
2953 // But when they do they shouldn't have an element type suffix.
2954 if (!Kind.empty()) {
2955 Error(S, "not expecting size suffix");
2956 return MatchOperand_ParseFail;
2957 }
2958
2959 // Add a literal slash as operand
2960 Operands.push_back(
2961 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2962
2963 Parser.Lex(); // Eat the slash.
2964
2965 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002966 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002967 if (Pred != "z" && Pred != "m") {
2968 Error(getLoc(), "expecting 'm' or 'z' predication");
2969 return MatchOperand_ParseFail;
2970 }
2971
2972 // Add zero/merge token.
2973 const char *ZM = Pred == "z" ? "z" : "m";
2974 Operands.push_back(
2975 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2976
2977 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002978 return MatchOperand_Success;
2979}
2980
Sander de Smalen50d87022018-04-19 07:35:08 +00002981/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002982bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002983 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002984 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002985 return false;
2986
Sander de Smalen149916d2018-04-20 07:24:20 +00002987 // Otherwise try for a scalar register.
2988 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
2989 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002990
Sander de Smalen149916d2018-04-20 07:24:20 +00002991 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002992}
2993
2994bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002995 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002996 bool HasELFModifier = false;
2997 AArch64MCExpr::VariantKind RefKind;
2998
Nirav Davee833c6c2016-11-08 18:31:04 +00002999 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003000 HasELFModifier = true;
3001
Nirav Davee833c6c2016-11-08 18:31:04 +00003002 if (Parser.getTok().isNot(AsmToken::Identifier))
3003 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003004
3005 std::string LowerCase = Parser.getTok().getIdentifier().lower();
3006 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
3007 .Case("lo12", AArch64MCExpr::VK_LO12)
3008 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
3009 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
3010 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
3011 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
3012 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
3013 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
3014 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
3015 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
3016 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
3017 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
3018 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
3019 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
3020 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3021 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3022 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3023 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3024 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3025 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3026 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3027 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3028 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3029 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3030 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3031 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3032 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3033 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3034 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3035 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3036 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3037 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3038 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3039 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3040 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3041 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003042 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3043 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00003044 .Default(AArch64MCExpr::VK_INVALID);
3045
Nirav Davee833c6c2016-11-08 18:31:04 +00003046 if (RefKind == AArch64MCExpr::VK_INVALID)
3047 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003048
3049 Parser.Lex(); // Eat identifier
3050
Nirav Davee833c6c2016-11-08 18:31:04 +00003051 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003052 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003053 }
3054
3055 if (getParser().parseExpression(ImmVal))
3056 return true;
3057
3058 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003059 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003060
3061 return false;
3062}
3063
Sander de Smalen650234b2018-04-12 11:40:52 +00003064template <RegKind VectorKind>
3065OperandMatchResultTy
3066AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3067 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003068 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003069 if (!Parser.getTok().is(AsmToken::LCurly))
3070 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003071
3072 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003073 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003074 bool NoMatchIsError) {
3075 auto RegTok = Parser.getTok();
3076 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3077 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003078 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003079 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003080 llvm_unreachable("Expected a valid vector kind");
3081 }
3082
Sander de Smalen650234b2018-04-12 11:40:52 +00003083 if (RegTok.isNot(AsmToken::Identifier) ||
3084 ParseRes == MatchOperand_ParseFail ||
3085 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3086 Error(Loc, "vector register expected");
3087 return MatchOperand_ParseFail;
3088 }
3089
3090 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003091 };
3092
Tim Northover3b0846e2014-05-24 12:50:23 +00003093 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003094 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003095 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003096
Tim Northover3b0846e2014-05-24 12:50:23 +00003097 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003098 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003099 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3100
3101 // Put back the original left bracket if there was no match, so that
3102 // different types of list-operands can be matched (e.g. SVE, Neon).
3103 if (ParseRes == MatchOperand_NoMatch)
3104 Parser.getLexer().UnLex(LCurly);
3105
3106 if (ParseRes != MatchOperand_Success)
3107 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003108
Tim Northover3b0846e2014-05-24 12:50:23 +00003109 int64_t PrevReg = FirstReg;
3110 unsigned Count = 1;
3111
Nirav Davee833c6c2016-11-08 18:31:04 +00003112 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003113 SMLoc Loc = getLoc();
3114 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003115
Sander de Smalen50d87022018-04-19 07:35:08 +00003116 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003117 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3118 if (ParseRes != MatchOperand_Success)
3119 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003120
Tim Northover3b0846e2014-05-24 12:50:23 +00003121 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003122 if (Kind != NextKind) {
3123 Error(Loc, "mismatched register size suffix");
3124 return MatchOperand_ParseFail;
3125 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003126
3127 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3128
3129 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003130 Error(Loc, "invalid number of vectors");
3131 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003132 }
3133
3134 Count += Space;
3135 }
3136 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003137 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003138 SMLoc Loc = getLoc();
3139 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003140 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003141 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3142 if (ParseRes != MatchOperand_Success)
3143 return ParseRes;
3144
Tim Northover3b0846e2014-05-24 12:50:23 +00003145 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003146 if (Kind != NextKind) {
3147 Error(Loc, "mismatched register size suffix");
3148 return MatchOperand_ParseFail;
3149 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003150
3151 // Registers must be incremental (with wraparound at 31)
3152 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003153 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3154 Error(Loc, "registers must be sequential");
3155 return MatchOperand_ParseFail;
3156 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003157
3158 PrevReg = Reg;
3159 ++Count;
3160 }
3161 }
3162
Nirav Davee833c6c2016-11-08 18:31:04 +00003163 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003164 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003165
Sander de Smalen650234b2018-04-12 11:40:52 +00003166 if (Count > 4) {
3167 Error(S, "invalid number of vectors");
3168 return MatchOperand_ParseFail;
3169 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003170
3171 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003172 unsigned ElementWidth = 0;
3173 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003174 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003175 std::tie(NumElements, ElementWidth) = *VK;
3176 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003177
3178 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003179 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3180 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003181
Sander de Smalen650234b2018-04-12 11:40:52 +00003182 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003183}
3184
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003185/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3186bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003187 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3188 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003189 return true;
3190
3191 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3192}
3193
Alex Bradbury58eba092016-11-01 16:32:05 +00003194OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003195AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003196 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003197
Sander de Smalen50d87022018-04-19 07:35:08 +00003198 unsigned RegNum;
3199 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3200 if (Res != MatchOperand_Success)
3201 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003202
Nirav Davee833c6c2016-11-08 18:31:04 +00003203 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003204 Operands.push_back(AArch64Operand::CreateReg(
3205 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003206 return MatchOperand_Success;
3207 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003208
Nirav Davee833c6c2016-11-08 18:31:04 +00003209 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003210
Sander de Smalen50d87022018-04-19 07:35:08 +00003211 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003212 Error(getLoc(), "index must be absent or #0");
3213 return MatchOperand_ParseFail;
3214 }
3215
3216 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003217 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003218 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3219 Error(getLoc(), "index must be absent or #0");
3220 return MatchOperand_ParseFail;
3221 }
3222
Sander de Smalen50d87022018-04-19 07:35:08 +00003223 Operands.push_back(AArch64Operand::CreateReg(
3224 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003225 return MatchOperand_Success;
3226}
3227
Sander de Smalen0325e302018-07-02 07:34:52 +00003228template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
Sander de Smalen149916d2018-04-20 07:24:20 +00003229OperandMatchResultTy
3230AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3231 SMLoc StartLoc = getLoc();
3232
3233 unsigned RegNum;
3234 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3235 if (Res != MatchOperand_Success)
3236 return Res;
3237
3238 // No shift/extend is the default.
3239 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3240 Operands.push_back(AArch64Operand::CreateReg(
Sander de Smalen0325e302018-07-02 07:34:52 +00003241 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
Sander de Smalen149916d2018-04-20 07:24:20 +00003242 return MatchOperand_Success;
3243 }
3244
3245 // Eat the comma
3246 getParser().Lex();
3247
3248 // Match the shift
3249 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3250 Res = tryParseOptionalShiftExtend(ExtOpnd);
3251 if (Res != MatchOperand_Success)
3252 return Res;
3253
3254 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
Sander de Smalen0325e302018-07-02 07:34:52 +00003255 Operands.push_back(AArch64Operand::CreateReg(
3256 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3257 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3258 Ext->hasShiftExtendAmount()));
Sander de Smalen149916d2018-04-20 07:24:20 +00003259
3260 return MatchOperand_Success;
3261}
3262
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003263bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
Sander de Smalen5c625982018-04-13 12:56:14 +00003264 MCAsmParser &Parser = getParser();
3265
3266 // Some SVE instructions have a decoration after the immediate, i.e.
3267 // "mul vl". We parse them here and add tokens, which must be present in the
3268 // asm string in the tablegen instruction.
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003269 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3270 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
Sander de Smalen5c625982018-04-13 12:56:14 +00003271 if (!Parser.getTok().getString().equals_lower("mul") ||
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003272 !(NextIsVL || NextIsHash))
Sander de Smalen5c625982018-04-13 12:56:14 +00003273 return true;
3274
Sander de Smalen5c625982018-04-13 12:56:14 +00003275 Operands.push_back(
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003276 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
Sander de Smalen5c625982018-04-13 12:56:14 +00003277 Parser.Lex(); // Eat the "mul"
3278
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003279 if (NextIsVL) {
3280 Operands.push_back(
3281 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3282 Parser.Lex(); // Eat the "vl"
3283 return false;
3284 }
Sander de Smalen5c625982018-04-13 12:56:14 +00003285
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003286 if (NextIsHash) {
3287 Parser.Lex(); // Eat the #
3288 SMLoc S = getLoc();
3289
3290 // Parse immediate operand.
3291 const MCExpr *ImmVal;
3292 if (!Parser.parseExpression(ImmVal))
3293 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3294 Operands.push_back(AArch64Operand::CreateImm(
3295 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3296 getContext()));
3297 return MatchOperand_Success;
3298 }
3299 }
3300
3301 return Error(getLoc(), "expected 'vl' or '#<imm>'");
Sander de Smalen5c625982018-04-13 12:56:14 +00003302}
3303
Tim Northover3b0846e2014-05-24 12:50:23 +00003304/// parseOperand - Parse a arm instruction operand. For now this parses the
3305/// operand regardless of the mnemonic.
3306bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3307 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003308 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003309
3310 OperandMatchResultTy ResTy =
3311 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3312
Tim Northover3b0846e2014-05-24 12:50:23 +00003313 // Check if the current operand has a custom associated parser, if so, try to
3314 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003315 if (ResTy == MatchOperand_Success)
3316 return false;
3317 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3318 // there was a match, but an error occurred, in which case, just return that
3319 // the operand parsing failed.
3320 if (ResTy == MatchOperand_ParseFail)
3321 return true;
3322
3323 // Nothing custom, so do general case parsing.
3324 SMLoc S, E;
3325 switch (getLexer().getKind()) {
3326 default: {
3327 SMLoc S = getLoc();
3328 const MCExpr *Expr;
3329 if (parseSymbolicImmVal(Expr))
3330 return Error(S, "invalid operand");
3331
3332 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3333 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3334 return false;
3335 }
3336 case AsmToken::LBrac: {
3337 SMLoc Loc = Parser.getTok().getLoc();
3338 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3339 getContext()));
3340 Parser.Lex(); // Eat '['
3341
3342 // There's no comma after a '[', so we can parse the next operand
3343 // immediately.
3344 return parseOperand(Operands, false, false);
3345 }
3346 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003347 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003348 case AsmToken::Identifier: {
3349 // If we're expecting a Condition Code operand, then just parse that.
3350 if (isCondCode)
3351 return parseCondCode(Operands, invertCondCode);
3352
3353 // If it's a register name, parse it.
3354 if (!parseRegister(Operands))
3355 return false;
3356
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003357 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3358 // by SVE instructions.
3359 if (!parseOptionalMulOperand(Operands))
Sander de Smalen5c625982018-04-13 12:56:14 +00003360 return false;
3361
Tim Northover3b0846e2014-05-24 12:50:23 +00003362 // This could be an optional "shift" or "extend" operand.
3363 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3364 // We can only continue if no tokens were eaten.
3365 if (GotShift != MatchOperand_NoMatch)
3366 return GotShift;
3367
3368 // This was not a register so parse other operands that start with an
3369 // identifier (like labels) as expressions and create them as immediates.
3370 const MCExpr *IdVal;
3371 S = getLoc();
3372 if (getParser().parseExpression(IdVal))
3373 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003374 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3375 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3376 return false;
3377 }
3378 case AsmToken::Integer:
3379 case AsmToken::Real:
3380 case AsmToken::Hash: {
3381 // #42 -> immediate.
3382 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003383
3384 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003385
3386 // Parse a negative sign
3387 bool isNegative = false;
3388 if (Parser.getTok().is(AsmToken::Minus)) {
3389 isNegative = true;
3390 // We need to consume this token only when we have a Real, otherwise
3391 // we let parseSymbolicImmVal take care of it
3392 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3393 Parser.Lex();
3394 }
3395
3396 // The only Real that should come through here is a literal #0.0 for
3397 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3398 // so convert the value.
3399 const AsmToken &Tok = Parser.getTok();
3400 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003401 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003402 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3403 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3404 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
Sander de Smalen8fcc3f52018-07-03 09:07:23 +00003405 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
Tim Northover3b0846e2014-05-24 12:50:23 +00003406 return TokError("unexpected floating point literal");
3407 else if (IntVal != 0 || isNegative)
3408 return TokError("expected floating-point constant #0.0");
3409 Parser.Lex(); // Eat the token.
3410
3411 Operands.push_back(
3412 AArch64Operand::CreateToken("#0", false, S, getContext()));
3413 Operands.push_back(
3414 AArch64Operand::CreateToken(".0", false, S, getContext()));
3415 return false;
3416 }
3417
3418 const MCExpr *ImmVal;
3419 if (parseSymbolicImmVal(ImmVal))
3420 return true;
3421
3422 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3423 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3424 return false;
3425 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003426 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003427 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003428 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003429 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003430 Parser.Lex(); // Eat '='
3431 const MCExpr *SubExprVal;
3432 if (getParser().parseExpression(SubExprVal))
3433 return true;
3434
David Peixottoae5ba762014-07-18 16:05:14 +00003435 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003436 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003437 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003438
3439 bool IsXReg =
3440 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3441 Operands[1]->getReg());
3442
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003443 MCContext& Ctx = getContext();
3444 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3445 // 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 +00003446 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003447 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3448 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3449 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3450 ShiftAmt += 16;
3451 Imm >>= 16;
3452 }
3453 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3454 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3455 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003456 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003457 if (ShiftAmt)
3458 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3459 ShiftAmt, true, S, E, Ctx));
3460 return false;
3461 }
David Peixottoae5ba762014-07-18 16:05:14 +00003462 APInt Simm = APInt(64, Imm << ShiftAmt);
3463 // check if the immediate is an unsigned or signed 32-bit int for W regs
3464 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3465 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003466 }
3467 // 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 +00003468 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003469 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003470 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3471 return false;
3472 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003473 }
3474}
3475
Sander de Smalen0325e302018-07-02 07:34:52 +00003476bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3477 const MCParsedAsmOperand &Op2) const {
3478 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3479 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3480 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3481 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3482 return MCTargetAsmParser::regsEqual(Op1, Op2);
3483
3484 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3485 "Testing equality of non-scalar registers not supported");
3486
3487 // Check if a registers match their sub/super register classes.
3488 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3489 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3490 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3491 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3492 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3493 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3494 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3495 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3496
3497 return false;
3498}
3499
Tim Northover3b0846e2014-05-24 12:50:23 +00003500/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3501/// operands.
3502bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3503 StringRef Name, SMLoc NameLoc,
3504 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003505 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003506 Name = StringSwitch<StringRef>(Name.lower())
3507 .Case("beq", "b.eq")
3508 .Case("bne", "b.ne")
3509 .Case("bhs", "b.hs")
3510 .Case("bcs", "b.cs")
3511 .Case("blo", "b.lo")
3512 .Case("bcc", "b.cc")
3513 .Case("bmi", "b.mi")
3514 .Case("bpl", "b.pl")
3515 .Case("bvs", "b.vs")
3516 .Case("bvc", "b.vc")
3517 .Case("bhi", "b.hi")
3518 .Case("bls", "b.ls")
3519 .Case("bge", "b.ge")
3520 .Case("blt", "b.lt")
3521 .Case("bgt", "b.gt")
3522 .Case("ble", "b.le")
3523 .Case("bal", "b.al")
3524 .Case("bnv", "b.nv")
3525 .Default(Name);
3526
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003527 // First check for the AArch64-specific .req directive.
3528 if (Parser.getTok().is(AsmToken::Identifier) &&
3529 Parser.getTok().getIdentifier() == ".req") {
3530 parseDirectiveReq(Name, NameLoc);
3531 // We always return 'error' for this, as we're done with this
3532 // statement and don't need to match the 'instruction."
3533 return true;
3534 }
3535
Tim Northover3b0846e2014-05-24 12:50:23 +00003536 // Create the leading tokens for the mnemonic, split by '.' characters.
3537 size_t Start = 0, Next = Name.find('.');
3538 StringRef Head = Name.slice(Start, Next);
3539
3540 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003541 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3542 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003543
3544 Operands.push_back(
3545 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3546 Mnemonic = Head;
3547
3548 // Handle condition codes for a branch mnemonic
3549 if (Head == "b" && Next != StringRef::npos) {
3550 Start = Next;
3551 Next = Name.find('.', Start + 1);
3552 Head = Name.slice(Start + 1, Next);
3553
3554 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3555 (Head.data() - Name.data()));
3556 AArch64CC::CondCode CC = parseCondCodeString(Head);
3557 if (CC == AArch64CC::Invalid)
3558 return Error(SuffixLoc, "invalid condition code");
3559 Operands.push_back(
3560 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3561 Operands.push_back(
3562 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3563 }
3564
3565 // Add the remaining tokens in the mnemonic.
3566 while (Next != StringRef::npos) {
3567 Start = Next;
3568 Next = Name.find('.', Start + 1);
3569 Head = Name.slice(Start, Next);
3570 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3571 (Head.data() - Name.data()) + 1);
3572 Operands.push_back(
3573 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3574 }
3575
3576 // Conditional compare instructions have a Condition Code operand, which needs
3577 // to be parsed and an immediate operand created.
3578 bool condCodeFourthOperand =
3579 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3580 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3581 Head == "csinc" || Head == "csinv" || Head == "csneg");
3582
3583 // These instructions are aliases to some of the conditional select
3584 // instructions. However, the condition code is inverted in the aliased
3585 // instruction.
3586 //
3587 // FIXME: Is this the correct way to handle these? Or should the parser
3588 // generate the aliased instructions directly?
3589 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3590 bool condCodeThirdOperand =
3591 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3592
3593 // Read the remaining operands.
3594 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3595 // Read the first operand.
3596 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003597 return true;
3598 }
3599
3600 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003601 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003602 // Parse and remember the operand.
3603 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3604 (N == 3 && condCodeThirdOperand) ||
3605 (N == 2 && condCodeSecondOperand),
3606 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003607 return true;
3608 }
3609
3610 // After successfully parsing some operands there are two special cases to
3611 // consider (i.e. notional operands not separated by commas). Both are due
3612 // to memory specifiers:
3613 // + An RBrac will end an address for load/store/prefetch
3614 // + An '!' will indicate a pre-indexed operation.
3615 //
3616 // It's someone else's responsibility to make sure these tokens are sane
3617 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003618
Nirav Davee833c6c2016-11-08 18:31:04 +00003619 SMLoc RLoc = Parser.getTok().getLoc();
3620 if (parseOptionalToken(AsmToken::RBrac))
3621 Operands.push_back(
3622 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3623 SMLoc ELoc = Parser.getTok().getLoc();
3624 if (parseOptionalToken(AsmToken::Exclaim))
3625 Operands.push_back(
3626 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003627
3628 ++N;
3629 }
3630 }
3631
Nirav Davee833c6c2016-11-08 18:31:04 +00003632 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3633 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003634
Tim Northover3b0846e2014-05-24 12:50:23 +00003635 return false;
3636}
3637
3638// FIXME: This entire function is a giant hack to provide us with decent
3639// operand range validation/diagnostics until TableGen/MC can be extended
3640// to support autogeneration of this kind of validation.
3641bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3642 SmallVectorImpl<SMLoc> &Loc) {
3643 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3644 // Check for indexed addressing modes w/ the base register being the
3645 // same as a destination/source register or pair load where
3646 // the Rt == Rt2. All of those are undefined behaviour.
3647 switch (Inst.getOpcode()) {
3648 case AArch64::LDPSWpre:
3649 case AArch64::LDPWpost:
3650 case AArch64::LDPWpre:
3651 case AArch64::LDPXpost:
3652 case AArch64::LDPXpre: {
3653 unsigned Rt = Inst.getOperand(1).getReg();
3654 unsigned Rt2 = Inst.getOperand(2).getReg();
3655 unsigned Rn = Inst.getOperand(3).getReg();
3656 if (RI->isSubRegisterEq(Rn, Rt))
3657 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3658 "is also a destination");
3659 if (RI->isSubRegisterEq(Rn, Rt2))
3660 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3661 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003662 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003663 }
3664 case AArch64::LDPDi:
3665 case AArch64::LDPQi:
3666 case AArch64::LDPSi:
3667 case AArch64::LDPSWi:
3668 case AArch64::LDPWi:
3669 case AArch64::LDPXi: {
3670 unsigned Rt = Inst.getOperand(0).getReg();
3671 unsigned Rt2 = Inst.getOperand(1).getReg();
3672 if (Rt == Rt2)
3673 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3674 break;
3675 }
3676 case AArch64::LDPDpost:
3677 case AArch64::LDPDpre:
3678 case AArch64::LDPQpost:
3679 case AArch64::LDPQpre:
3680 case AArch64::LDPSpost:
3681 case AArch64::LDPSpre:
3682 case AArch64::LDPSWpost: {
3683 unsigned Rt = Inst.getOperand(1).getReg();
3684 unsigned Rt2 = Inst.getOperand(2).getReg();
3685 if (Rt == Rt2)
3686 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3687 break;
3688 }
3689 case AArch64::STPDpost:
3690 case AArch64::STPDpre:
3691 case AArch64::STPQpost:
3692 case AArch64::STPQpre:
3693 case AArch64::STPSpost:
3694 case AArch64::STPSpre:
3695 case AArch64::STPWpost:
3696 case AArch64::STPWpre:
3697 case AArch64::STPXpost:
3698 case AArch64::STPXpre: {
3699 unsigned Rt = Inst.getOperand(1).getReg();
3700 unsigned Rt2 = Inst.getOperand(2).getReg();
3701 unsigned Rn = Inst.getOperand(3).getReg();
3702 if (RI->isSubRegisterEq(Rn, Rt))
3703 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3704 "is also a source");
3705 if (RI->isSubRegisterEq(Rn, Rt2))
3706 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3707 "is also a source");
3708 break;
3709 }
3710 case AArch64::LDRBBpre:
3711 case AArch64::LDRBpre:
3712 case AArch64::LDRHHpre:
3713 case AArch64::LDRHpre:
3714 case AArch64::LDRSBWpre:
3715 case AArch64::LDRSBXpre:
3716 case AArch64::LDRSHWpre:
3717 case AArch64::LDRSHXpre:
3718 case AArch64::LDRSWpre:
3719 case AArch64::LDRWpre:
3720 case AArch64::LDRXpre:
3721 case AArch64::LDRBBpost:
3722 case AArch64::LDRBpost:
3723 case AArch64::LDRHHpost:
3724 case AArch64::LDRHpost:
3725 case AArch64::LDRSBWpost:
3726 case AArch64::LDRSBXpost:
3727 case AArch64::LDRSHWpost:
3728 case AArch64::LDRSHXpost:
3729 case AArch64::LDRSWpost:
3730 case AArch64::LDRWpost:
3731 case AArch64::LDRXpost: {
3732 unsigned Rt = Inst.getOperand(1).getReg();
3733 unsigned Rn = Inst.getOperand(2).getReg();
3734 if (RI->isSubRegisterEq(Rn, Rt))
3735 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3736 "is also a source");
3737 break;
3738 }
3739 case AArch64::STRBBpost:
3740 case AArch64::STRBpost:
3741 case AArch64::STRHHpost:
3742 case AArch64::STRHpost:
3743 case AArch64::STRWpost:
3744 case AArch64::STRXpost:
3745 case AArch64::STRBBpre:
3746 case AArch64::STRBpre:
3747 case AArch64::STRHHpre:
3748 case AArch64::STRHpre:
3749 case AArch64::STRWpre:
3750 case AArch64::STRXpre: {
3751 unsigned Rt = Inst.getOperand(1).getReg();
3752 unsigned Rn = Inst.getOperand(2).getReg();
3753 if (RI->isSubRegisterEq(Rn, Rt))
3754 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3755 "is also a source");
3756 break;
3757 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003758 case AArch64::STXRB:
3759 case AArch64::STXRH:
3760 case AArch64::STXRW:
3761 case AArch64::STXRX:
3762 case AArch64::STLXRB:
3763 case AArch64::STLXRH:
3764 case AArch64::STLXRW:
3765 case AArch64::STLXRX: {
3766 unsigned Rs = Inst.getOperand(0).getReg();
3767 unsigned Rt = Inst.getOperand(1).getReg();
3768 unsigned Rn = Inst.getOperand(2).getReg();
3769 if (RI->isSubRegisterEq(Rt, Rs) ||
3770 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3771 return Error(Loc[0],
3772 "unpredictable STXR instruction, status is also a source");
3773 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003774 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003775 case AArch64::STXPW:
3776 case AArch64::STXPX:
3777 case AArch64::STLXPW:
3778 case AArch64::STLXPX: {
3779 unsigned Rs = Inst.getOperand(0).getReg();
3780 unsigned Rt1 = Inst.getOperand(1).getReg();
3781 unsigned Rt2 = Inst.getOperand(2).getReg();
3782 unsigned Rn = Inst.getOperand(3).getReg();
3783 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3784 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3785 return Error(Loc[0],
3786 "unpredictable STXP instruction, status is also a source");
3787 break;
3788 }
3789 }
3790
Tim Northover3b0846e2014-05-24 12:50:23 +00003791
3792 // Now check immediate ranges. Separate from the above as there is overlap
3793 // in the instructions being checked and this keeps the nested conditionals
3794 // to a minimum.
3795 switch (Inst.getOpcode()) {
3796 case AArch64::ADDSWri:
3797 case AArch64::ADDSXri:
3798 case AArch64::ADDWri:
3799 case AArch64::ADDXri:
3800 case AArch64::SUBSWri:
3801 case AArch64::SUBSXri:
3802 case AArch64::SUBWri:
3803 case AArch64::SUBXri: {
3804 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3805 // some slight duplication here.
3806 if (Inst.getOperand(2).isExpr()) {
3807 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3808 AArch64MCExpr::VariantKind ELFRefKind;
3809 MCSymbolRefExpr::VariantKind DarwinRefKind;
3810 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003811 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3812
3813 // Only allow these with ADDXri.
3814 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3815 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3816 Inst.getOpcode() == AArch64::ADDXri)
3817 return false;
3818
3819 // Only allow these with ADDXri/ADDWri
3820 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3821 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3822 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3823 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3824 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3825 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3826 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003827 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3828 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3829 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003830 (Inst.getOpcode() == AArch64::ADDXri ||
3831 Inst.getOpcode() == AArch64::ADDWri))
3832 return false;
3833
3834 // Don't allow symbol refs in the immediate field otherwise
3835 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3836 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3837 // 'cmp w0, 'borked')
3838 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003839 }
Diana Picusc93518d2016-10-11 09:17:47 +00003840 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003841 }
3842 return false;
3843 }
3844 default:
3845 return false;
3846 }
3847}
3848
Craig Topper05515562017-10-26 06:46:41 +00003849static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3850 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003851
3852bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
Sander de Smalen0325e302018-07-02 07:34:52 +00003853 uint64_t ErrorInfo,
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003854 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003855 switch (ErrCode) {
Sander de Smalen0325e302018-07-02 07:34:52 +00003856 case Match_InvalidTiedOperand: {
3857 RegConstraintEqualityTy EqTy =
3858 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
3859 .getRegEqualityTy();
3860 switch (EqTy) {
3861 case RegConstraintEqualityTy::EqualsSubReg:
3862 return Error(Loc, "operand must be 64-bit form of destination register");
3863 case RegConstraintEqualityTy::EqualsSuperReg:
3864 return Error(Loc, "operand must be 32-bit form of destination register");
3865 case RegConstraintEqualityTy::EqualsReg:
3866 return Error(Loc, "operand must match destination register");
3867 }
3868 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003869 case Match_MissingFeature:
3870 return Error(Loc,
3871 "instruction requires a CPU feature not currently enabled");
3872 case Match_InvalidOperand:
3873 return Error(Loc, "invalid operand for instruction");
3874 case Match_InvalidSuffix:
3875 return Error(Loc, "invalid type suffix for instruction");
3876 case Match_InvalidCondCode:
3877 return Error(Loc, "expected AArch64 condition code");
3878 case Match_AddSubRegExtendSmall:
3879 return Error(Loc,
3880 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3881 case Match_AddSubRegExtendLarge:
3882 return Error(Loc,
3883 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3884 case Match_AddSubSecondSource:
3885 return Error(Loc,
3886 "expected compatible register, symbol or integer in range [0, 4095]");
3887 case Match_LogicalSecondSource:
3888 return Error(Loc, "expected compatible register or logical immediate");
3889 case Match_InvalidMovImm32Shift:
3890 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3891 case Match_InvalidMovImm64Shift:
3892 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3893 case Match_AddSubRegShift32:
3894 return Error(Loc,
3895 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3896 case Match_AddSubRegShift64:
3897 return Error(Loc,
3898 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3899 case Match_InvalidFPImm:
3900 return Error(Loc,
3901 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003902 case Match_InvalidMemoryIndexedSImm6:
3903 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003904 case Match_InvalidMemoryIndexedSImm5:
3905 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003906 case Match_InvalidMemoryIndexed1SImm4:
3907 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003908 case Match_InvalidMemoryIndexed2SImm4:
3909 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003910 case Match_InvalidMemoryIndexed3SImm4:
3911 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003912 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00003913 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00003914 case Match_InvalidMemoryIndexed16SImm4:
3915 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00003916 case Match_InvalidMemoryIndexed1SImm6:
3917 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen592718f2018-07-05 07:54:10 +00003918 case Match_InvalidMemoryIndexedSImm8:
3919 return Error(Loc, "index must be an integer in range [-128, 127].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003920 case Match_InvalidMemoryIndexedSImm9:
3921 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00003922 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00003923 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003924 case Match_InvalidMemoryIndexed4SImm7:
3925 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3926 case Match_InvalidMemoryIndexed8SImm7:
3927 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3928 case Match_InvalidMemoryIndexed16SImm7:
3929 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00003930 case Match_InvalidMemoryIndexed8UImm5:
3931 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
3932 case Match_InvalidMemoryIndexed4UImm5:
3933 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
3934 case Match_InvalidMemoryIndexed2UImm5:
3935 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00003936 case Match_InvalidMemoryIndexed8UImm6:
3937 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
3938 case Match_InvalidMemoryIndexed4UImm6:
3939 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
3940 case Match_InvalidMemoryIndexed2UImm6:
3941 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
3942 case Match_InvalidMemoryIndexed1UImm6:
3943 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003944 case Match_InvalidMemoryWExtend8:
3945 return Error(Loc,
3946 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3947 case Match_InvalidMemoryWExtend16:
3948 return Error(Loc,
3949 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3950 case Match_InvalidMemoryWExtend32:
3951 return Error(Loc,
3952 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3953 case Match_InvalidMemoryWExtend64:
3954 return Error(Loc,
3955 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3956 case Match_InvalidMemoryWExtend128:
3957 return Error(Loc,
3958 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3959 case Match_InvalidMemoryXExtend8:
3960 return Error(Loc,
3961 "expected 'lsl' or 'sxtx' with optional shift of #0");
3962 case Match_InvalidMemoryXExtend16:
3963 return Error(Loc,
3964 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3965 case Match_InvalidMemoryXExtend32:
3966 return Error(Loc,
3967 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3968 case Match_InvalidMemoryXExtend64:
3969 return Error(Loc,
3970 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3971 case Match_InvalidMemoryXExtend128:
3972 return Error(Loc,
3973 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3974 case Match_InvalidMemoryIndexed1:
3975 return Error(Loc, "index must be an integer in range [0, 4095].");
3976 case Match_InvalidMemoryIndexed2:
3977 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3978 case Match_InvalidMemoryIndexed4:
3979 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3980 case Match_InvalidMemoryIndexed8:
3981 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3982 case Match_InvalidMemoryIndexed16:
3983 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003984 case Match_InvalidImm0_1:
3985 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003986 case Match_InvalidImm0_7:
3987 return Error(Loc, "immediate must be an integer in range [0, 7].");
3988 case Match_InvalidImm0_15:
3989 return Error(Loc, "immediate must be an integer in range [0, 15].");
3990 case Match_InvalidImm0_31:
3991 return Error(Loc, "immediate must be an integer in range [0, 31].");
3992 case Match_InvalidImm0_63:
3993 return Error(Loc, "immediate must be an integer in range [0, 63].");
3994 case Match_InvalidImm0_127:
3995 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003996 case Match_InvalidImm0_255:
3997 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003998 case Match_InvalidImm0_65535:
3999 return Error(Loc, "immediate must be an integer in range [0, 65535].");
4000 case Match_InvalidImm1_8:
4001 return Error(Loc, "immediate must be an integer in range [1, 8].");
4002 case Match_InvalidImm1_16:
4003 return Error(Loc, "immediate must be an integer in range [1, 16].");
4004 case Match_InvalidImm1_32:
4005 return Error(Loc, "immediate must be an integer in range [1, 32].");
4006 case Match_InvalidImm1_64:
4007 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00004008 case Match_InvalidSVEAddSubImm8:
4009 return Error(Loc, "immediate must be an integer in range [0, 255]"
4010 " with a shift amount of 0");
4011 case Match_InvalidSVEAddSubImm16:
4012 case Match_InvalidSVEAddSubImm32:
4013 case Match_InvalidSVEAddSubImm64:
4014 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
4015 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004016 case Match_InvalidSVECpyImm8:
4017 return Error(Loc, "immediate must be an integer in range [-128, 255]"
4018 " with a shift amount of 0");
4019 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00004020 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4021 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004022 case Match_InvalidSVECpyImm32:
4023 case Match_InvalidSVECpyImm64:
4024 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4025 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004026 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004027 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004028 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00004029 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004030 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00004031 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004032 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004033 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004034 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004035 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004036 case Match_InvalidSVEIndexRange0_63:
4037 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4038 case Match_InvalidSVEIndexRange0_31:
4039 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4040 case Match_InvalidSVEIndexRange0_15:
4041 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4042 case Match_InvalidSVEIndexRange0_7:
4043 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4044 case Match_InvalidSVEIndexRange0_3:
4045 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004046 case Match_InvalidLabel:
4047 return Error(Loc, "expected label or encodable integer pc offset");
4048 case Match_MRS:
4049 return Error(Loc, "expected readable system register");
4050 case Match_MSR:
4051 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00004052 case Match_InvalidComplexRotationEven:
4053 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4054 case Match_InvalidComplexRotationOdd:
4055 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004056 case Match_MnemonicFail: {
4057 std::string Suggestion = AArch64MnemonicSpellCheck(
4058 ((AArch64Operand &)*Operands[0]).getToken(),
4059 ComputeAvailableFeatures(STI->getFeatureBits()));
4060 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4061 }
Sander de Smalen367694b2018-04-20 08:54:49 +00004062 case Match_InvalidGPR64shifted8:
4063 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4064 case Match_InvalidGPR64shifted16:
4065 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4066 case Match_InvalidGPR64shifted32:
4067 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4068 case Match_InvalidGPR64shifted64:
4069 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4070 case Match_InvalidGPR64NoXZRshifted8:
4071 return Error(Loc, "register must be x0..x30 without shift");
4072 case Match_InvalidGPR64NoXZRshifted16:
4073 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4074 case Match_InvalidGPR64NoXZRshifted32:
4075 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4076 case Match_InvalidGPR64NoXZRshifted64:
4077 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004078 case Match_InvalidZPR32UXTW8:
4079 case Match_InvalidZPR32SXTW8:
4080 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4081 case Match_InvalidZPR32UXTW16:
4082 case Match_InvalidZPR32SXTW16:
4083 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4084 case Match_InvalidZPR32UXTW32:
4085 case Match_InvalidZPR32SXTW32:
4086 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4087 case Match_InvalidZPR32UXTW64:
4088 case Match_InvalidZPR32SXTW64:
4089 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4090 case Match_InvalidZPR64UXTW8:
4091 case Match_InvalidZPR64SXTW8:
4092 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4093 case Match_InvalidZPR64UXTW16:
4094 case Match_InvalidZPR64SXTW16:
4095 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4096 case Match_InvalidZPR64UXTW32:
4097 case Match_InvalidZPR64SXTW32:
4098 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4099 case Match_InvalidZPR64UXTW64:
4100 case Match_InvalidZPR64SXTW64:
4101 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
4102 case Match_InvalidZPR64LSL8:
4103 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4104 case Match_InvalidZPR64LSL16:
4105 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4106 case Match_InvalidZPR64LSL32:
4107 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4108 case Match_InvalidZPR64LSL64:
4109 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00004110 case Match_InvalidZPR0:
4111 return Error(Loc, "expected register without element width sufix");
4112 case Match_InvalidZPR8:
4113 case Match_InvalidZPR16:
4114 case Match_InvalidZPR32:
4115 case Match_InvalidZPR64:
4116 case Match_InvalidZPR128:
4117 return Error(Loc, "invalid element width");
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004118 case Match_InvalidZPR_3b8:
4119 return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b");
4120 case Match_InvalidZPR_3b16:
4121 return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h");
4122 case Match_InvalidZPR_3b32:
4123 return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s");
4124 case Match_InvalidZPR_4b16:
4125 return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h");
4126 case Match_InvalidZPR_4b32:
4127 return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s");
4128 case Match_InvalidZPR_4b64:
4129 return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004130 case Match_InvalidSVEPattern:
4131 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004132 case Match_InvalidSVEPredicateAnyReg:
4133 case Match_InvalidSVEPredicateBReg:
4134 case Match_InvalidSVEPredicateHReg:
4135 case Match_InvalidSVEPredicateSReg:
4136 case Match_InvalidSVEPredicateDReg:
4137 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004138 case Match_InvalidSVEPredicate3bAnyReg:
4139 case Match_InvalidSVEPredicate3bBReg:
4140 case Match_InvalidSVEPredicate3bHReg:
4141 case Match_InvalidSVEPredicate3bSReg:
4142 case Match_InvalidSVEPredicate3bDReg:
4143 return Error(Loc, "restricted predicate has range [0, 7].");
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004144 case Match_InvalidSVEExactFPImmOperandHalfOne:
4145 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4146 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4147 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4148 case Match_InvalidSVEExactFPImmOperandZeroOne:
4149 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004150 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004151 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004152 }
4153}
4154
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004155static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004156
4157bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4158 OperandVector &Operands,
4159 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004160 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004161 bool MatchingInlineAsm) {
4162 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004163 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4164 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004165
David Blaikie960ea3f2014-06-08 16:18:35 +00004166 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004167 unsigned NumOperands = Operands.size();
4168
4169 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004170 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4171 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004172 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004173 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004174 if (Op3CE) {
4175 uint64_t Op3Val = Op3CE->getValue();
4176 uint64_t NewOp3Val = 0;
4177 uint64_t NewOp4Val = 0;
4178 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004179 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004180 NewOp3Val = (32 - Op3Val) & 0x1f;
4181 NewOp4Val = 31 - Op3Val;
4182 } else {
4183 NewOp3Val = (64 - Op3Val) & 0x3f;
4184 NewOp4Val = 63 - Op3Val;
4185 }
4186
Jim Grosbach13760bd2015-05-30 01:25:56 +00004187 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4188 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004189
4190 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004191 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004192 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004193 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4194 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4195 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004196 }
4197 }
Tim Northover03b99f62015-04-30 18:28:58 +00004198 } else if (NumOperands == 4 && Tok == "bfc") {
4199 // FIXME: Horrible hack to handle BFC->BFM alias.
4200 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4201 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4202 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4203
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004204 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004205 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4206 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4207
4208 if (LSBCE && WidthCE) {
4209 uint64_t LSB = LSBCE->getValue();
4210 uint64_t Width = WidthCE->getValue();
4211
4212 uint64_t RegWidth = 0;
4213 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4214 Op1.getReg()))
4215 RegWidth = 64;
4216 else
4217 RegWidth = 32;
4218
4219 if (LSB >= RegWidth)
4220 return Error(LSBOp.getStartLoc(),
4221 "expected integer in range [0, 31]");
4222 if (Width < 1 || Width > RegWidth)
4223 return Error(WidthOp.getStartLoc(),
4224 "expected integer in range [1, 32]");
4225
4226 uint64_t ImmR = 0;
4227 if (RegWidth == 32)
4228 ImmR = (32 - LSB) & 0x1f;
4229 else
4230 ImmR = (64 - LSB) & 0x3f;
4231
4232 uint64_t ImmS = Width - 1;
4233
4234 if (ImmR != 0 && ImmS >= ImmR)
4235 return Error(WidthOp.getStartLoc(),
4236 "requested insert overflows register");
4237
Jim Grosbach13760bd2015-05-30 01:25:56 +00004238 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4239 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004240 Operands[0] = AArch64Operand::CreateToken(
4241 "bfm", false, Op.getStartLoc(), getContext());
4242 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004243 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4244 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004245 Operands[3] = AArch64Operand::CreateImm(
4246 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4247 Operands.emplace_back(
4248 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4249 WidthOp.getEndLoc(), getContext()));
4250 }
4251 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004252 } else if (NumOperands == 5) {
4253 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4254 // UBFIZ -> UBFM aliases.
4255 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004256 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4257 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4258 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004259
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004260 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004261 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4262 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004263
4264 if (Op3CE && Op4CE) {
4265 uint64_t Op3Val = Op3CE->getValue();
4266 uint64_t Op4Val = Op4CE->getValue();
4267
4268 uint64_t RegWidth = 0;
4269 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004270 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004271 RegWidth = 64;
4272 else
4273 RegWidth = 32;
4274
4275 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004276 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004277 "expected integer in range [0, 31]");
4278 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004279 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004280 "expected integer in range [1, 32]");
4281
4282 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004283 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004284 NewOp3Val = (32 - Op3Val) & 0x1f;
4285 else
4286 NewOp3Val = (64 - Op3Val) & 0x3f;
4287
4288 uint64_t NewOp4Val = Op4Val - 1;
4289
4290 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004291 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004292 "requested insert overflows register");
4293
4294 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004295 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004296 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004297 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004298 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004299 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004300 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004301 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004302 if (Tok == "bfi")
4303 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004304 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004305 else if (Tok == "sbfiz")
4306 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004307 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004308 else if (Tok == "ubfiz")
4309 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004310 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004311 else
4312 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004313 }
4314 }
4315
4316 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4317 // UBFX -> UBFM aliases.
4318 } else if (NumOperands == 5 &&
4319 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004320 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4321 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4322 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004323
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004324 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004325 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4326 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004327
4328 if (Op3CE && Op4CE) {
4329 uint64_t Op3Val = Op3CE->getValue();
4330 uint64_t Op4Val = Op4CE->getValue();
4331
4332 uint64_t RegWidth = 0;
4333 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004334 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004335 RegWidth = 64;
4336 else
4337 RegWidth = 32;
4338
4339 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004340 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004341 "expected integer in range [0, 31]");
4342 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004343 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004344 "expected integer in range [1, 32]");
4345
4346 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4347
4348 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004349 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004350 "requested extract overflows register");
4351
4352 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004353 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004354 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004355 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004356 if (Tok == "bfxil")
4357 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004358 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004359 else if (Tok == "sbfx")
4360 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004361 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004362 else if (Tok == "ubfx")
4363 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004364 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004365 else
4366 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004367 }
4368 }
4369 }
4370 }
Tim Northover9097a072017-12-18 10:36:00 +00004371
4372 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4373 // instruction for FP registers correctly in some rare circumstances. Convert
4374 // it to a safe instruction and warn (because silently changing someone's
4375 // assembly is rude).
4376 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4377 NumOperands == 4 && Tok == "movi") {
4378 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4379 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4380 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4381 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4382 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4383 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4384 if (Suffix.lower() == ".2d" &&
4385 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4386 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4387 " correctly on this CPU, converting to equivalent movi.16b");
4388 // Switch the suffix to .16b.
4389 unsigned Idx = Op1.isToken() ? 1 : 2;
4390 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4391 getContext());
4392 }
4393 }
4394 }
4395
Tim Northover3b0846e2014-05-24 12:50:23 +00004396 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4397 // InstAlias can't quite handle this since the reg classes aren't
4398 // subclasses.
4399 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4400 // The source register can be Wn here, but the matcher expects a
4401 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004402 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004403 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004404 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004405 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4406 Op.getStartLoc(), Op.getEndLoc(),
4407 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004408 }
4409 }
4410 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4411 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004412 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004413 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004414 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004415 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004416 // The source register can be Wn here, but the matcher expects a
4417 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004418 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004419 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004420 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004421 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4422 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004423 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004424 }
4425 }
4426 }
4427 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4428 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004429 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004430 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004431 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004432 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004433 // The source register can be Wn here, but the matcher expects a
4434 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004435 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004436 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004437 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004438 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4439 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004440 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004441 }
4442 }
4443 }
4444
Tim Northover3b0846e2014-05-24 12:50:23 +00004445 MCInst Inst;
4446 // First try to match against the secondary set of tables containing the
4447 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4448 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004449 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004450
4451 // If that fails, try against the alternate table containing long-form NEON:
4452 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004453 if (MatchResult != Match_Success) {
4454 // But first, save the short-form match result: we can use it in case the
4455 // long-form match also fails.
4456 auto ShortFormNEONErrorInfo = ErrorInfo;
4457 auto ShortFormNEONMatchResult = MatchResult;
4458
Tim Northover3b0846e2014-05-24 12:50:23 +00004459 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004460 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004461
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004462 // Now, both matches failed, and the long-form match failed on the mnemonic
4463 // suffix token operand. The short-form match failure is probably more
4464 // relevant: use it instead.
4465 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004466 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004467 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4468 MatchResult = ShortFormNEONMatchResult;
4469 ErrorInfo = ShortFormNEONErrorInfo;
4470 }
4471 }
4472
Tim Northover3b0846e2014-05-24 12:50:23 +00004473 switch (MatchResult) {
4474 case Match_Success: {
4475 // Perform range checking and other semantic validations
4476 SmallVector<SMLoc, 8> OperandLocs;
4477 NumOperands = Operands.size();
4478 for (unsigned i = 1; i < NumOperands; ++i)
4479 OperandLocs.push_back(Operands[i]->getStartLoc());
4480 if (validateInstruction(Inst, OperandLocs))
4481 return true;
4482
4483 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004484 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004485 return false;
4486 }
4487 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004488 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004489 // Special case the error message for the very common case where only
4490 // a single subtarget feature is missing (neon, e.g.).
4491 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004492 uint64_t Mask = 1;
4493 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4494 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004495 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004496 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004497 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004498 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004499 }
4500 return Error(IDLoc, Msg);
4501 }
4502 case Match_MnemonicFail:
Sander de Smalen0325e302018-07-02 07:34:52 +00004503 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004504 case Match_InvalidOperand: {
4505 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004506
Tim Northover26bb14e2014-08-18 11:49:42 +00004507 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004508 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004509 return Error(IDLoc, "too few operands for instruction",
4510 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004511
David Blaikie960ea3f2014-06-08 16:18:35 +00004512 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004513 if (ErrorLoc == SMLoc())
4514 ErrorLoc = IDLoc;
4515 }
4516 // If the match failed on a suffix token operand, tweak the diagnostic
4517 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004518 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4519 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004520 MatchResult = Match_InvalidSuffix;
4521
Sander de Smalen0325e302018-07-02 07:34:52 +00004522 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004523 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004524 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004525 case Match_InvalidMemoryIndexed1:
4526 case Match_InvalidMemoryIndexed2:
4527 case Match_InvalidMemoryIndexed4:
4528 case Match_InvalidMemoryIndexed8:
4529 case Match_InvalidMemoryIndexed16:
4530 case Match_InvalidCondCode:
4531 case Match_AddSubRegExtendSmall:
4532 case Match_AddSubRegExtendLarge:
4533 case Match_AddSubSecondSource:
4534 case Match_LogicalSecondSource:
4535 case Match_AddSubRegShift32:
4536 case Match_AddSubRegShift64:
4537 case Match_InvalidMovImm32Shift:
4538 case Match_InvalidMovImm64Shift:
4539 case Match_InvalidFPImm:
4540 case Match_InvalidMemoryWExtend8:
4541 case Match_InvalidMemoryWExtend16:
4542 case Match_InvalidMemoryWExtend32:
4543 case Match_InvalidMemoryWExtend64:
4544 case Match_InvalidMemoryWExtend128:
4545 case Match_InvalidMemoryXExtend8:
4546 case Match_InvalidMemoryXExtend16:
4547 case Match_InvalidMemoryXExtend32:
4548 case Match_InvalidMemoryXExtend64:
4549 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004550 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004551 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004552 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004553 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004554 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004555 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004556 case Match_InvalidMemoryIndexed4SImm7:
4557 case Match_InvalidMemoryIndexed8SImm7:
4558 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004559 case Match_InvalidMemoryIndexed8UImm5:
4560 case Match_InvalidMemoryIndexed4UImm5:
4561 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004562 case Match_InvalidMemoryIndexed1UImm6:
4563 case Match_InvalidMemoryIndexed2UImm6:
4564 case Match_InvalidMemoryIndexed4UImm6:
4565 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004566 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004567 case Match_InvalidMemoryIndexedSImm5:
Sander de Smalen592718f2018-07-05 07:54:10 +00004568 case Match_InvalidMemoryIndexedSImm8:
Tim Northover3b0846e2014-05-24 12:50:23 +00004569 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004570 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004571 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004572 case Match_InvalidImm0_7:
4573 case Match_InvalidImm0_15:
4574 case Match_InvalidImm0_31:
4575 case Match_InvalidImm0_63:
4576 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004577 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004578 case Match_InvalidImm0_65535:
4579 case Match_InvalidImm1_8:
4580 case Match_InvalidImm1_16:
4581 case Match_InvalidImm1_32:
4582 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004583 case Match_InvalidSVEAddSubImm8:
4584 case Match_InvalidSVEAddSubImm16:
4585 case Match_InvalidSVEAddSubImm32:
4586 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004587 case Match_InvalidSVECpyImm8:
4588 case Match_InvalidSVECpyImm16:
4589 case Match_InvalidSVECpyImm32:
4590 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004591 case Match_InvalidIndexRange1_1:
4592 case Match_InvalidIndexRange0_15:
4593 case Match_InvalidIndexRange0_7:
4594 case Match_InvalidIndexRange0_3:
4595 case Match_InvalidIndexRange0_1:
4596 case Match_InvalidSVEIndexRange0_63:
4597 case Match_InvalidSVEIndexRange0_31:
4598 case Match_InvalidSVEIndexRange0_15:
4599 case Match_InvalidSVEIndexRange0_7:
4600 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004601 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004602 case Match_InvalidComplexRotationEven:
4603 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004604 case Match_InvalidGPR64shifted8:
4605 case Match_InvalidGPR64shifted16:
4606 case Match_InvalidGPR64shifted32:
4607 case Match_InvalidGPR64shifted64:
4608 case Match_InvalidGPR64NoXZRshifted8:
4609 case Match_InvalidGPR64NoXZRshifted16:
4610 case Match_InvalidGPR64NoXZRshifted32:
4611 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004612 case Match_InvalidZPR32UXTW8:
4613 case Match_InvalidZPR32UXTW16:
4614 case Match_InvalidZPR32UXTW32:
4615 case Match_InvalidZPR32UXTW64:
4616 case Match_InvalidZPR32SXTW8:
4617 case Match_InvalidZPR32SXTW16:
4618 case Match_InvalidZPR32SXTW32:
4619 case Match_InvalidZPR32SXTW64:
4620 case Match_InvalidZPR64UXTW8:
4621 case Match_InvalidZPR64SXTW8:
4622 case Match_InvalidZPR64UXTW16:
4623 case Match_InvalidZPR64SXTW16:
4624 case Match_InvalidZPR64UXTW32:
4625 case Match_InvalidZPR64SXTW32:
4626 case Match_InvalidZPR64UXTW64:
4627 case Match_InvalidZPR64SXTW64:
4628 case Match_InvalidZPR64LSL8:
4629 case Match_InvalidZPR64LSL16:
4630 case Match_InvalidZPR64LSL32:
4631 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004632 case Match_InvalidZPR0:
4633 case Match_InvalidZPR8:
4634 case Match_InvalidZPR16:
4635 case Match_InvalidZPR32:
4636 case Match_InvalidZPR64:
4637 case Match_InvalidZPR128:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004638 case Match_InvalidZPR_3b8:
4639 case Match_InvalidZPR_3b16:
4640 case Match_InvalidZPR_3b32:
4641 case Match_InvalidZPR_4b16:
4642 case Match_InvalidZPR_4b32:
4643 case Match_InvalidZPR_4b64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004644 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004645 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004646 case Match_InvalidSVEPredicateBReg:
4647 case Match_InvalidSVEPredicateHReg:
4648 case Match_InvalidSVEPredicateSReg:
4649 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004650 case Match_InvalidSVEPredicate3bAnyReg:
4651 case Match_InvalidSVEPredicate3bBReg:
4652 case Match_InvalidSVEPredicate3bHReg:
4653 case Match_InvalidSVEPredicate3bSReg:
4654 case Match_InvalidSVEPredicate3bDReg:
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004655 case Match_InvalidSVEExactFPImmOperandHalfOne:
4656 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4657 case Match_InvalidSVEExactFPImmOperandZeroOne:
Tim Northover3b0846e2014-05-24 12:50:23 +00004658 case Match_MSR:
4659 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004660 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004661 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004662 // Any time we get here, there's nothing fancy to do. Just get the
4663 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004664 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004665 if (ErrorLoc == SMLoc())
4666 ErrorLoc = IDLoc;
Sander de Smalen0325e302018-07-02 07:34:52 +00004667 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004668 }
4669 }
4670
4671 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004672}
4673
4674/// ParseDirective parses the arm specific directives
4675bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004676 const MCObjectFileInfo::Environment Format =
4677 getContext().getObjectFileInfo()->getObjectFileType();
4678 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4679 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004680
Tim Northover3b0846e2014-05-24 12:50:23 +00004681 StringRef IDVal = DirectiveID.getIdentifier();
4682 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004683 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004684 parseDirectiveArch(Loc);
4685 else if (IDVal == ".cpu")
4686 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00004687 else if (IDVal == ".tlsdesccall")
4688 parseDirectiveTLSDescCall(Loc);
4689 else if (IDVal == ".ltorg" || IDVal == ".pool")
4690 parseDirectiveLtorg(Loc);
4691 else if (IDVal == ".unreq")
4692 parseDirectiveUnreq(Loc);
4693 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004694 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004695 parseDirectiveInst(Loc);
4696 else
4697 return true;
4698 } else if (IDVal == MCLOHDirectiveName())
4699 parseDirectiveLOH(IDVal, Loc);
4700 else
4701 return true;
4702 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004703}
4704
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004705static const struct {
4706 const char *Name;
4707 const FeatureBitset Features;
4708} ExtensionMap[] = {
4709 { "crc", {AArch64::FeatureCRC} },
4710 { "crypto", {AArch64::FeatureCrypto} },
4711 { "fp", {AArch64::FeatureFPARMv8} },
4712 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004713 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004714 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004715
4716 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004717 { "pan", {} },
4718 { "lor", {} },
4719 { "rdma", {} },
4720 { "profile", {} },
4721};
4722
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004723/// parseDirectiveArch
4724/// ::= .arch token
4725bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4726 SMLoc ArchLoc = getLoc();
4727
4728 StringRef Arch, ExtensionString;
4729 std::tie(Arch, ExtensionString) =
4730 getParser().parseStringToEndOfStatement().trim().split('+');
4731
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004732 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4733 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004734 return Error(ArchLoc, "unknown arch name");
4735
4736 if (parseToken(AsmToken::EndOfStatement))
4737 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004738
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004739 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004740 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004741 AArch64::getArchFeatures(ID, AArch64Features);
4742 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4743 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004744
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004745 MCSubtargetInfo &STI = copySTI();
4746 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4747 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4748
4749 SmallVector<StringRef, 4> RequestedExtensions;
4750 if (!ExtensionString.empty())
4751 ExtensionString.split(RequestedExtensions, '+');
4752
4753 FeatureBitset Features = STI.getFeatureBits();
4754 for (auto Name : RequestedExtensions) {
4755 bool EnableFeature = true;
4756
4757 if (Name.startswith_lower("no")) {
4758 EnableFeature = false;
4759 Name = Name.substr(2);
4760 }
4761
4762 for (const auto &Extension : ExtensionMap) {
4763 if (Extension.Name != Name)
4764 continue;
4765
4766 if (Extension.Features.none())
4767 report_fatal_error("unsupported architectural extension: " + Name);
4768
4769 FeatureBitset ToggleFeatures = EnableFeature
4770 ? (~Features & Extension.Features)
4771 : ( Features & Extension.Features);
4772 uint64_t Features =
4773 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4774 setAvailableFeatures(Features);
4775 break;
4776 }
4777 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004778 return false;
4779}
4780
Tim Northover8b96c7e2017-05-15 19:42:15 +00004781static SMLoc incrementLoc(SMLoc L, int Offset) {
4782 return SMLoc::getFromPointer(L.getPointer() + Offset);
4783}
4784
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004785/// parseDirectiveCPU
4786/// ::= .cpu id
4787bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004788 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004789
4790 StringRef CPU, ExtensionString;
4791 std::tie(CPU, ExtensionString) =
4792 getParser().parseStringToEndOfStatement().trim().split('+');
4793
Nirav Davee833c6c2016-11-08 18:31:04 +00004794 if (parseToken(AsmToken::EndOfStatement))
4795 return true;
4796
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004797 SmallVector<StringRef, 4> RequestedExtensions;
4798 if (!ExtensionString.empty())
4799 ExtensionString.split(RequestedExtensions, '+');
4800
4801 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4802 // once that is tablegen'ed
4803 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004804 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004805 return false;
4806 }
4807
4808 MCSubtargetInfo &STI = copySTI();
4809 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004810 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004811
4812 FeatureBitset Features = STI.getFeatureBits();
4813 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004814 // Advance source location past '+'.
4815 CurLoc = incrementLoc(CurLoc, 1);
4816
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004817 bool EnableFeature = true;
4818
4819 if (Name.startswith_lower("no")) {
4820 EnableFeature = false;
4821 Name = Name.substr(2);
4822 }
4823
Tim Northover8b96c7e2017-05-15 19:42:15 +00004824 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004825 for (const auto &Extension : ExtensionMap) {
4826 if (Extension.Name != Name)
4827 continue;
4828
4829 if (Extension.Features.none())
4830 report_fatal_error("unsupported architectural extension: " + Name);
4831
4832 FeatureBitset ToggleFeatures = EnableFeature
4833 ? (~Features & Extension.Features)
4834 : ( Features & Extension.Features);
4835 uint64_t Features =
4836 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4837 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004838 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004839
4840 break;
4841 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004842
4843 if (!FoundExtension)
4844 Error(CurLoc, "unsupported architectural extension");
4845
4846 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004847 }
4848 return false;
4849}
4850
Chad Rosierdcd2a302014-10-22 20:35:57 +00004851/// parseDirectiveInst
4852/// ::= .inst opcode [, ...]
4853bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004854 if (getLexer().is(AsmToken::EndOfStatement))
4855 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004856
Nirav Davee833c6c2016-11-08 18:31:04 +00004857 auto parseOp = [&]() -> bool {
4858 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004859 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004860 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4861 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004862 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004863 if (check(!Value, L, "expected constant expression"))
4864 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004865 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004866 return false;
4867 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004868
Nirav Davee833c6c2016-11-08 18:31:04 +00004869 if (parseMany(parseOp))
4870 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004871 return false;
4872}
4873
Tim Northover3b0846e2014-05-24 12:50:23 +00004874// parseDirectiveTLSDescCall:
4875// ::= .tlsdesccall symbol
4876bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4877 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004878 if (check(getParser().parseIdentifier(Name), L,
4879 "expected symbol after directive") ||
4880 parseToken(AsmToken::EndOfStatement))
4881 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004882
Jim Grosbach6f482002015-05-18 18:43:14 +00004883 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004884 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4885 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004886
4887 MCInst Inst;
4888 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004889 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004890
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004891 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004892 return false;
4893}
4894
4895/// ::= .loh <lohName | lohId> label1, ..., labelN
4896/// The number of arguments depends on the loh identifier.
4897bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004898 MCLOHType Kind;
4899 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4900 if (getParser().getTok().isNot(AsmToken::Integer))
4901 return TokError("expected an identifier or a number in directive");
4902 // We successfully get a numeric value for the identifier.
4903 // Check if it is valid.
4904 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004905 if (Id <= -1U && !isValidMCLOHType(Id))
4906 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004907 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004908 } else {
4909 StringRef Name = getTok().getIdentifier();
4910 // We successfully parse an identifier.
4911 // Check if it is a recognized one.
4912 int Id = MCLOHNameToId(Name);
4913
4914 if (Id == -1)
4915 return TokError("invalid identifier in directive");
4916 Kind = (MCLOHType)Id;
4917 }
4918 // Consume the identifier.
4919 Lex();
4920 // Get the number of arguments of this LOH.
4921 int NbArgs = MCLOHIdToNbArgs(Kind);
4922
4923 assert(NbArgs != -1 && "Invalid number of arguments");
4924
4925 SmallVector<MCSymbol *, 3> Args;
4926 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4927 StringRef Name;
4928 if (getParser().parseIdentifier(Name))
4929 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004930 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004931
4932 if (Idx + 1 == NbArgs)
4933 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004934 if (parseToken(AsmToken::Comma,
4935 "unexpected token in '" + Twine(IDVal) + "' directive"))
4936 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004937 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004938 if (parseToken(AsmToken::EndOfStatement,
4939 "unexpected token in '" + Twine(IDVal) + "' directive"))
4940 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004941
4942 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4943 return false;
4944}
4945
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004946/// parseDirectiveLtorg
4947/// ::= .ltorg | .pool
4948bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004949 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4950 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004951 getTargetStreamer().emitCurrentConstantPool();
4952 return false;
4953}
4954
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004955/// parseDirectiveReq
4956/// ::= name .req registername
4957bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004958 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004959 Parser.Lex(); // Eat the '.req' token.
4960 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004961 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004962 unsigned RegNum;
4963 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004964
Sander de Smalen50d87022018-04-19 07:35:08 +00004965 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004966 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004967 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004968 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004969
Sander de Smalen50d87022018-04-19 07:35:08 +00004970 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004971 return true;
4972
Sander de Smalen50d87022018-04-19 07:35:08 +00004973 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004974 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004975 }
4976
Sander de Smalen50d87022018-04-19 07:35:08 +00004977 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004978 StringRef Kind;
4979 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004980 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004981 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004982
Sander de Smalen50d87022018-04-19 07:35:08 +00004983 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004984 return true;
4985
Sander de Smalen50d87022018-04-19 07:35:08 +00004986 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004987 return Error(SRegLoc,
4988 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004989 }
4990
Sander de Smalen50d87022018-04-19 07:35:08 +00004991 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00004992 StringRef Kind;
4993 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004994 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004995
Sander de Smalen50d87022018-04-19 07:35:08 +00004996 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00004997 return true;
4998
Sander de Smalen50d87022018-04-19 07:35:08 +00004999 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00005000 return Error(SRegLoc,
5001 "sve predicate register without type specifier expected");
5002 }
5003
Sander de Smalen50d87022018-04-19 07:35:08 +00005004 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00005005 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005006
5007 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00005008 if (parseToken(AsmToken::EndOfStatement,
5009 "unexpected input in .req directive"))
5010 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005011
Sander de Smalen8e607342017-11-15 15:44:43 +00005012 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00005013 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005014 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
5015
Nirav Dave2364748a2016-09-16 18:30:20 +00005016 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005017}
5018
5019/// parseDirectiveUneq
5020/// ::= .unreq registername
5021bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005022 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00005023 if (getTok().isNot(AsmToken::Identifier))
5024 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005025 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
5026 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00005027 if (parseToken(AsmToken::EndOfStatement))
5028 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005029 return false;
5030}
5031
Tim Northover3b0846e2014-05-24 12:50:23 +00005032bool
5033AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
5034 AArch64MCExpr::VariantKind &ELFRefKind,
5035 MCSymbolRefExpr::VariantKind &DarwinRefKind,
5036 int64_t &Addend) {
5037 ELFRefKind = AArch64MCExpr::VK_INVALID;
5038 DarwinRefKind = MCSymbolRefExpr::VK_None;
5039 Addend = 0;
5040
5041 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5042 ELFRefKind = AE->getKind();
5043 Expr = AE->getSubExpr();
5044 }
5045
5046 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5047 if (SE) {
5048 // It's a simple symbol reference with no addend.
5049 DarwinRefKind = SE->getKind();
5050 return true;
5051 }
5052
5053 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
5054 if (!BE)
5055 return false;
5056
5057 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
5058 if (!SE)
5059 return false;
5060 DarwinRefKind = SE->getKind();
5061
5062 if (BE->getOpcode() != MCBinaryExpr::Add &&
5063 BE->getOpcode() != MCBinaryExpr::Sub)
5064 return false;
5065
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00005066 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00005067 // on here than we can deal with.
5068 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
5069 if (!AddendExpr)
5070 return false;
5071
5072 Addend = AddendExpr->getValue();
5073 if (BE->getOpcode() == MCBinaryExpr::Sub)
5074 Addend = -Addend;
5075
5076 // It's some symbol reference + a constant addend, but really
5077 // shouldn't use both Darwin and ELF syntax.
5078 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5079 DarwinRefKind == MCSymbolRefExpr::VK_None;
5080}
5081
5082/// Force static initialization.
5083extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00005084 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5085 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5086 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00005087}
5088
5089#define GET_REGISTER_MATCHER
5090#define GET_SUBTARGET_FEATURE_NAME
5091#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00005092#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00005093#include "AArch64GenAsmMatcher.inc"
5094
5095// Define this matcher function after the auto-generated include so we
5096// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00005097unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00005098 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005099 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00005100 // If the kind is a token for a literal immediate, check if our asm
5101 // operand matches. This is for InstAliases which have a fixed-value
5102 // immediate in the syntax.
5103 int64_t ExpectedVal;
5104 switch (Kind) {
5105 default:
5106 return Match_InvalidOperand;
5107 case MCK__35_0:
5108 ExpectedVal = 0;
5109 break;
5110 case MCK__35_1:
5111 ExpectedVal = 1;
5112 break;
5113 case MCK__35_12:
5114 ExpectedVal = 12;
5115 break;
5116 case MCK__35_16:
5117 ExpectedVal = 16;
5118 break;
5119 case MCK__35_2:
5120 ExpectedVal = 2;
5121 break;
5122 case MCK__35_24:
5123 ExpectedVal = 24;
5124 break;
5125 case MCK__35_3:
5126 ExpectedVal = 3;
5127 break;
5128 case MCK__35_32:
5129 ExpectedVal = 32;
5130 break;
5131 case MCK__35_4:
5132 ExpectedVal = 4;
5133 break;
5134 case MCK__35_48:
5135 ExpectedVal = 48;
5136 break;
5137 case MCK__35_6:
5138 ExpectedVal = 6;
5139 break;
5140 case MCK__35_64:
5141 ExpectedVal = 64;
5142 break;
5143 case MCK__35_8:
5144 ExpectedVal = 8;
5145 break;
5146 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005147 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005148 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005149 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005150 if (!CE)
5151 return Match_InvalidOperand;
5152 if (CE->getValue() == ExpectedVal)
5153 return Match_Success;
5154 return Match_InvalidOperand;
5155}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005156
Alex Bradbury58eba092016-11-01 16:32:05 +00005157OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005158AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5159
5160 SMLoc S = getLoc();
5161
5162 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5163 Error(S, "expected register");
5164 return MatchOperand_ParseFail;
5165 }
5166
Sander de Smalen50d87022018-04-19 07:35:08 +00005167 unsigned FirstReg;
5168 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5169 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005170 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005171
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005172 const MCRegisterClass &WRegClass =
5173 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5174 const MCRegisterClass &XRegClass =
5175 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5176
5177 bool isXReg = XRegClass.contains(FirstReg),
5178 isWReg = WRegClass.contains(FirstReg);
5179 if (!isXReg && !isWReg) {
5180 Error(S, "expected first even register of a "
5181 "consecutive same-size even/odd register pair");
5182 return MatchOperand_ParseFail;
5183 }
5184
5185 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5186 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5187
5188 if (FirstEncoding & 0x1) {
5189 Error(S, "expected first even register of a "
5190 "consecutive same-size even/odd register pair");
5191 return MatchOperand_ParseFail;
5192 }
5193
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005194 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005195 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005196 return MatchOperand_ParseFail;
5197 }
5198 // Eat the comma
5199 getParser().Lex();
5200
5201 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005202 unsigned SecondReg;
5203 Res = tryParseScalarRegister(SecondReg);
5204 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005205 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005206
Eugene Zelenko049b0172017-01-06 00:30:53 +00005207 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005208 (isXReg && !XRegClass.contains(SecondReg)) ||
5209 (isWReg && !WRegClass.contains(SecondReg))) {
5210 Error(E,"expected second odd register of a "
5211 "consecutive same-size even/odd register pair");
5212 return MatchOperand_ParseFail;
5213 }
Joel Jones504bf332016-10-24 13:37:13 +00005214
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005215 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005216 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005217 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5218 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5219 } else {
5220 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5221 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5222 }
5223
Florian Hahnc4422242017-11-07 13:07:50 +00005224 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5225 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005226
5227 return MatchOperand_Success;
5228}
Florian Hahn91f11e52017-11-07 16:45:48 +00005229
Sander de Smaleneb896b12018-04-25 09:26:47 +00005230template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005231OperandMatchResultTy
5232AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005233 const SMLoc S = getLoc();
5234 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005235 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005236 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005237
Sander de Smalen8e607342017-11-15 15:44:43 +00005238 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005239 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005240
5241 if (Res != MatchOperand_Success)
5242 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005243
5244 if (ParseSuffix && Kind.empty())
5245 return MatchOperand_NoMatch;
5246
Sander de Smalen73937b72018-04-11 07:36:10 +00005247 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5248 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005249 return MatchOperand_NoMatch;
5250
Sander de Smalen73937b72018-04-11 07:36:10 +00005251 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005252
5253 // No shift/extend is the default.
5254 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5255 Operands.push_back(AArch64Operand::CreateVectorReg(
5256 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5257
Sander de Smalenc33d6682018-06-04 06:40:55 +00005258 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5259 if (Res == MatchOperand_ParseFail)
5260 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005261 return MatchOperand_Success;
5262 }
5263
5264 // Eat the comma
5265 getParser().Lex();
5266
5267 // Match the shift
5268 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5269 Res = tryParseOptionalShiftExtend(ExtOpnd);
5270 if (Res != MatchOperand_Success)
5271 return Res;
5272
5273 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005274 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005275 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5276 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5277 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005278
5279 return MatchOperand_Success;
5280}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005281
5282OperandMatchResultTy
5283AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5284 MCAsmParser &Parser = getParser();
5285
5286 SMLoc SS = getLoc();
5287 const AsmToken &TokE = Parser.getTok();
5288 bool IsHash = TokE.is(AsmToken::Hash);
5289
5290 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5291 return MatchOperand_NoMatch;
5292
5293 int64_t Pattern;
5294 if (IsHash) {
5295 Parser.Lex(); // Eat hash
5296
5297 // Parse the immediate operand.
5298 const MCExpr *ImmVal;
5299 SS = getLoc();
5300 if (Parser.parseExpression(ImmVal))
5301 return MatchOperand_ParseFail;
5302
5303 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5304 if (!MCE)
5305 return MatchOperand_ParseFail;
5306
5307 Pattern = MCE->getValue();
5308 } else {
5309 // Parse the pattern
5310 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5311 if (!Pat)
5312 return MatchOperand_NoMatch;
5313
5314 Parser.Lex();
5315 Pattern = Pat->Encoding;
5316 assert(Pattern >= 0 && Pattern < 32);
5317 }
5318
5319 Operands.push_back(
5320 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5321 SS, getLoc(), getContext()));
5322
5323 return MatchOperand_Success;
5324}