blob: ece1dbe7987e6c69707423f9a1f3085bf92e2f72 [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);
2526 return CC;
2527}
2528
2529/// parseCondCode - Parse a Condition Code operand.
2530bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2531 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002532 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002533 SMLoc S = getLoc();
2534 const AsmToken &Tok = Parser.getTok();
2535 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2536
2537 StringRef Cond = Tok.getString();
2538 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2539 if (CC == AArch64CC::Invalid)
2540 return TokError("invalid condition code");
2541 Parser.Lex(); // Eat identifier token.
2542
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002543 if (invertCondCode) {
2544 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2545 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002546 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002547 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002548
2549 Operands.push_back(
2550 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2551 return false;
2552}
2553
2554/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2555/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002556OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002557AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002558 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002559 const AsmToken &Tok = Parser.getTok();
2560 std::string LowerID = Tok.getString().lower();
2561 AArch64_AM::ShiftExtendType ShOp =
2562 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2563 .Case("lsl", AArch64_AM::LSL)
2564 .Case("lsr", AArch64_AM::LSR)
2565 .Case("asr", AArch64_AM::ASR)
2566 .Case("ror", AArch64_AM::ROR)
2567 .Case("msl", AArch64_AM::MSL)
2568 .Case("uxtb", AArch64_AM::UXTB)
2569 .Case("uxth", AArch64_AM::UXTH)
2570 .Case("uxtw", AArch64_AM::UXTW)
2571 .Case("uxtx", AArch64_AM::UXTX)
2572 .Case("sxtb", AArch64_AM::SXTB)
2573 .Case("sxth", AArch64_AM::SXTH)
2574 .Case("sxtw", AArch64_AM::SXTW)
2575 .Case("sxtx", AArch64_AM::SXTX)
2576 .Default(AArch64_AM::InvalidShiftExtend);
2577
2578 if (ShOp == AArch64_AM::InvalidShiftExtend)
2579 return MatchOperand_NoMatch;
2580
2581 SMLoc S = Tok.getLoc();
2582 Parser.Lex();
2583
Nirav Davee833c6c2016-11-08 18:31:04 +00002584 bool Hash = parseOptionalToken(AsmToken::Hash);
2585
Tim Northover3b0846e2014-05-24 12:50:23 +00002586 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2587 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2588 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2589 ShOp == AArch64_AM::MSL) {
2590 // We expect a number here.
2591 TokError("expected #imm after shift specifier");
2592 return MatchOperand_ParseFail;
2593 }
2594
Chad Rosier2ff37b82016-12-27 16:58:09 +00002595 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002596 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2597 Operands.push_back(
2598 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2599 return MatchOperand_Success;
2600 }
2601
Chad Rosier2ff37b82016-12-27 16:58:09 +00002602 // Make sure we do actually have a number, identifier or a parenthesized
2603 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002604 SMLoc E = Parser.getTok().getLoc();
2605 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002606 !Parser.getTok().is(AsmToken::LParen) &&
2607 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002608 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002609 return MatchOperand_ParseFail;
2610 }
2611
2612 const MCExpr *ImmVal;
2613 if (getParser().parseExpression(ImmVal))
2614 return MatchOperand_ParseFail;
2615
2616 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2617 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002618 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002619 return MatchOperand_ParseFail;
2620 }
2621
Jim Grosbach57fd2622014-09-23 22:16:02 +00002622 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002623 Operands.push_back(AArch64Operand::CreateShiftExtend(
2624 ShOp, MCE->getValue(), true, S, E, getContext()));
2625 return MatchOperand_Success;
2626}
2627
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002628static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2629 if (FBS[AArch64::HasV8_1aOps])
2630 Str += "ARMv8.1a";
2631 else if (FBS[AArch64::HasV8_2aOps])
2632 Str += "ARMv8.2a";
2633 else
2634 Str += "(unknown)";
2635}
2636
2637void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2638 SMLoc S) {
2639 const uint16_t Op2 = Encoding & 7;
2640 const uint16_t Cm = (Encoding & 0x78) >> 3;
2641 const uint16_t Cn = (Encoding & 0x780) >> 7;
2642 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2643
2644 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2645
2646 Operands.push_back(
2647 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2648 Operands.push_back(
2649 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2650 Operands.push_back(
2651 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2652 Expr = MCConstantExpr::create(Op2, getContext());
2653 Operands.push_back(
2654 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2655}
2656
Tim Northover3b0846e2014-05-24 12:50:23 +00002657/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2658/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2659bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2660 OperandVector &Operands) {
2661 if (Name.find('.') != StringRef::npos)
2662 return TokError("invalid operand");
2663
2664 Mnemonic = Name;
2665 Operands.push_back(
2666 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2667
Rafael Espindola961d4692014-11-11 05:18:41 +00002668 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002669 const AsmToken &Tok = Parser.getTok();
2670 StringRef Op = Tok.getString();
2671 SMLoc S = Tok.getLoc();
2672
Tim Northover3b0846e2014-05-24 12:50:23 +00002673 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002674 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2675 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002676 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002677 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2678 std::string Str("IC " + std::string(IC->Name) + " requires ");
2679 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2680 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002681 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002682 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002683 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002684 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2685 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002686 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002687 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2688 std::string Str("DC " + std::string(DC->Name) + " requires ");
2689 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2690 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002691 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002692 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002693 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002694 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2695 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002696 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002697 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2698 std::string Str("AT " + std::string(AT->Name) + " requires ");
2699 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2700 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002701 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002702 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002703 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002704 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2705 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002706 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002707 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2708 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2709 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2710 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002711 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002712 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002713 }
2714
Tim Northover3b0846e2014-05-24 12:50:23 +00002715 Parser.Lex(); // Eat operand.
2716
2717 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2718 bool HasRegister = false;
2719
2720 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002721 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002722 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2723 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002724 HasRegister = true;
2725 }
2726
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002727 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002728 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002729 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002730 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002731
Nirav Davee833c6c2016-11-08 18:31:04 +00002732 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2733 return true;
2734
Tim Northover3b0846e2014-05-24 12:50:23 +00002735 return false;
2736}
2737
Alex Bradbury58eba092016-11-01 16:32:05 +00002738OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002739AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002740 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002741 const AsmToken &Tok = Parser.getTok();
2742
2743 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002744 if (parseOptionalToken(AsmToken::Hash) ||
2745 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002746 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002747 const MCExpr *ImmVal;
2748 SMLoc ExprLoc = getLoc();
2749 if (getParser().parseExpression(ImmVal))
2750 return MatchOperand_ParseFail;
2751 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2752 if (!MCE) {
2753 Error(ExprLoc, "immediate value expected for barrier operand");
2754 return MatchOperand_ParseFail;
2755 }
2756 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2757 Error(ExprLoc, "barrier operand out of range");
2758 return MatchOperand_ParseFail;
2759 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002760 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2761 Operands.push_back(AArch64Operand::CreateBarrier(
2762 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002763 return MatchOperand_Success;
2764 }
2765
2766 if (Tok.isNot(AsmToken::Identifier)) {
2767 TokError("invalid operand for instruction");
2768 return MatchOperand_ParseFail;
2769 }
2770
Tim Northover3b0846e2014-05-24 12:50:23 +00002771 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002772 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2773 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002774 TokError("'sy' or #imm operand expected");
2775 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002776 } else if (!DB) {
2777 TokError("invalid barrier option name");
2778 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002779 }
2780
Tim Northovere6ae6762016-07-05 21:23:04 +00002781 Operands.push_back(AArch64Operand::CreateBarrier(
2782 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002783 Parser.Lex(); // Consume the option
2784
2785 return MatchOperand_Success;
2786}
2787
Alex Bradbury58eba092016-11-01 16:32:05 +00002788OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002789AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002790 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002791 const AsmToken &Tok = Parser.getTok();
2792
2793 if (Tok.isNot(AsmToken::Identifier))
2794 return MatchOperand_NoMatch;
2795
Tim Northovere6ae6762016-07-05 21:23:04 +00002796 int MRSReg, MSRReg;
2797 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2798 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2799 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2800 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2801 } else
2802 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002803
Tim Northovere6ae6762016-07-05 21:23:04 +00002804 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2805 unsigned PStateImm = -1;
2806 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2807 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002808
Tim Northovere6ae6762016-07-05 21:23:04 +00002809 Operands.push_back(
2810 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2811 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002812 Parser.Lex(); // Eat identifier
2813
2814 return MatchOperand_Success;
2815}
2816
Florian Hahnc4422242017-11-07 13:07:50 +00002817/// tryParseNeonVectorRegister - Parse a vector register operand.
2818bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002819 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002820 if (Parser.getTok().isNot(AsmToken::Identifier))
2821 return true;
2822
2823 SMLoc S = getLoc();
2824 // Check for a vector register specifier first.
2825 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002826 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002827 OperandMatchResultTy Res =
2828 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2829 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002830 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002831
2832 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2833 if (!KindRes)
2834 return true;
2835
2836 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002837 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002838 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2839 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002840
Tim Northover3b0846e2014-05-24 12:50:23 +00002841 // If there was an explicit qualifier, that goes on as a literal text
2842 // operand.
2843 if (!Kind.empty())
2844 Operands.push_back(
2845 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2846
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002847 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2848}
2849
2850OperandMatchResultTy
2851AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002852 SMLoc SIdx = getLoc();
2853 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002854 const MCExpr *ImmVal;
2855 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002856 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002857 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2858 if (!MCE) {
2859 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002860 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002861 }
2862
2863 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002864
Nirav Davee833c6c2016-11-08 18:31:04 +00002865 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002866 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002867
2868 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2869 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002870 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002871 }
2872
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002873 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002874}
2875
Sander de Smalen73937b72018-04-11 07:36:10 +00002876// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002877// optional kind specifier. If it is a register specifier, eat the token
2878// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002879OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002880AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002881 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002882 MCAsmParser &Parser = getParser();
2883 const AsmToken &Tok = Parser.getTok();
2884
Florian Hahn91f11e52017-11-07 16:45:48 +00002885 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002886 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002887
2888 StringRef Name = Tok.getString();
2889 // If there is a kind specifier, it's separated from the register name by
2890 // a '.'.
2891 size_t Start = 0, Next = Name.find('.');
2892 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002893 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002894
2895 if (RegNum) {
2896 if (Next != StringRef::npos) {
2897 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002898 if (!isValidVectorKind(Kind, MatchKind)) {
2899 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002900 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002901 }
2902 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002903 Parser.Lex(); // Eat the register token.
2904
2905 Reg = RegNum;
2906 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002907 }
2908
Sander de Smalen8e607342017-11-15 15:44:43 +00002909 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002910}
2911
Sander de Smalencd6be962017-12-20 11:02:42 +00002912/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2913OperandMatchResultTy
2914AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2915 // Check for a SVE predicate register specifier first.
2916 const SMLoc S = getLoc();
2917 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002918 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002919 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002920 if (Res != MatchOperand_Success)
2921 return Res;
2922
Sander de Smalen73937b72018-04-11 07:36:10 +00002923 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2924 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002925 return MatchOperand_NoMatch;
2926
Sander de Smalen73937b72018-04-11 07:36:10 +00002927 unsigned ElementWidth = KindRes->second;
2928 Operands.push_back(AArch64Operand::CreateVectorReg(
2929 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2930 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002931
Sander de Smalen7868e742018-01-09 11:17:06 +00002932 // Not all predicates are followed by a '/m' or '/z'.
2933 MCAsmParser &Parser = getParser();
2934 if (Parser.getTok().isNot(AsmToken::Slash))
2935 return MatchOperand_Success;
2936
2937 // But when they do they shouldn't have an element type suffix.
2938 if (!Kind.empty()) {
2939 Error(S, "not expecting size suffix");
2940 return MatchOperand_ParseFail;
2941 }
2942
2943 // Add a literal slash as operand
2944 Operands.push_back(
2945 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2946
2947 Parser.Lex(); // Eat the slash.
2948
2949 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002950 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002951 if (Pred != "z" && Pred != "m") {
2952 Error(getLoc(), "expecting 'm' or 'z' predication");
2953 return MatchOperand_ParseFail;
2954 }
2955
2956 // Add zero/merge token.
2957 const char *ZM = Pred == "z" ? "z" : "m";
2958 Operands.push_back(
2959 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2960
2961 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002962 return MatchOperand_Success;
2963}
2964
Sander de Smalen50d87022018-04-19 07:35:08 +00002965/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002966bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002967 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002968 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002969 return false;
2970
Sander de Smalen149916d2018-04-20 07:24:20 +00002971 // Otherwise try for a scalar register.
2972 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
2973 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002974
Sander de Smalen149916d2018-04-20 07:24:20 +00002975 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002976}
2977
2978bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002979 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002980 bool HasELFModifier = false;
2981 AArch64MCExpr::VariantKind RefKind;
2982
Nirav Davee833c6c2016-11-08 18:31:04 +00002983 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002984 HasELFModifier = true;
2985
Nirav Davee833c6c2016-11-08 18:31:04 +00002986 if (Parser.getTok().isNot(AsmToken::Identifier))
2987 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002988
2989 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2990 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2991 .Case("lo12", AArch64MCExpr::VK_LO12)
2992 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2993 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2994 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2995 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2996 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2997 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2998 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2999 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
3000 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
3001 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
3002 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
3003 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
3004 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3005 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3006 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3007 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3008 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3009 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3010 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3011 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3012 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3013 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3014 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3015 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3016 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3017 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3018 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3019 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3020 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3021 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3022 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3023 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3024 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3025 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003026 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3027 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00003028 .Default(AArch64MCExpr::VK_INVALID);
3029
Nirav Davee833c6c2016-11-08 18:31:04 +00003030 if (RefKind == AArch64MCExpr::VK_INVALID)
3031 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003032
3033 Parser.Lex(); // Eat identifier
3034
Nirav Davee833c6c2016-11-08 18:31:04 +00003035 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003036 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003037 }
3038
3039 if (getParser().parseExpression(ImmVal))
3040 return true;
3041
3042 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003043 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003044
3045 return false;
3046}
3047
Sander de Smalen650234b2018-04-12 11:40:52 +00003048template <RegKind VectorKind>
3049OperandMatchResultTy
3050AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3051 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003052 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003053 if (!Parser.getTok().is(AsmToken::LCurly))
3054 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003055
3056 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003057 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003058 bool NoMatchIsError) {
3059 auto RegTok = Parser.getTok();
3060 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3061 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003062 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003063 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003064 llvm_unreachable("Expected a valid vector kind");
3065 }
3066
Sander de Smalen650234b2018-04-12 11:40:52 +00003067 if (RegTok.isNot(AsmToken::Identifier) ||
3068 ParseRes == MatchOperand_ParseFail ||
3069 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3070 Error(Loc, "vector register expected");
3071 return MatchOperand_ParseFail;
3072 }
3073
3074 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003075 };
3076
Tim Northover3b0846e2014-05-24 12:50:23 +00003077 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003078 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003079 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003080
Tim Northover3b0846e2014-05-24 12:50:23 +00003081 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003082 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003083 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3084
3085 // Put back the original left bracket if there was no match, so that
3086 // different types of list-operands can be matched (e.g. SVE, Neon).
3087 if (ParseRes == MatchOperand_NoMatch)
3088 Parser.getLexer().UnLex(LCurly);
3089
3090 if (ParseRes != MatchOperand_Success)
3091 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003092
Tim Northover3b0846e2014-05-24 12:50:23 +00003093 int64_t PrevReg = FirstReg;
3094 unsigned Count = 1;
3095
Nirav Davee833c6c2016-11-08 18:31:04 +00003096 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003097 SMLoc Loc = getLoc();
3098 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003099
Sander de Smalen50d87022018-04-19 07:35:08 +00003100 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003101 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3102 if (ParseRes != MatchOperand_Success)
3103 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003104
Tim Northover3b0846e2014-05-24 12:50:23 +00003105 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003106 if (Kind != NextKind) {
3107 Error(Loc, "mismatched register size suffix");
3108 return MatchOperand_ParseFail;
3109 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003110
3111 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3112
3113 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003114 Error(Loc, "invalid number of vectors");
3115 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003116 }
3117
3118 Count += Space;
3119 }
3120 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003121 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003122 SMLoc Loc = getLoc();
3123 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003124 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003125 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3126 if (ParseRes != MatchOperand_Success)
3127 return ParseRes;
3128
Tim Northover3b0846e2014-05-24 12:50:23 +00003129 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003130 if (Kind != NextKind) {
3131 Error(Loc, "mismatched register size suffix");
3132 return MatchOperand_ParseFail;
3133 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003134
3135 // Registers must be incremental (with wraparound at 31)
3136 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003137 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3138 Error(Loc, "registers must be sequential");
3139 return MatchOperand_ParseFail;
3140 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003141
3142 PrevReg = Reg;
3143 ++Count;
3144 }
3145 }
3146
Nirav Davee833c6c2016-11-08 18:31:04 +00003147 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003148 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003149
Sander de Smalen650234b2018-04-12 11:40:52 +00003150 if (Count > 4) {
3151 Error(S, "invalid number of vectors");
3152 return MatchOperand_ParseFail;
3153 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003154
3155 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003156 unsigned ElementWidth = 0;
3157 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003158 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003159 std::tie(NumElements, ElementWidth) = *VK;
3160 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003161
3162 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003163 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3164 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003165
Sander de Smalen650234b2018-04-12 11:40:52 +00003166 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003167}
3168
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003169/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3170bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003171 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3172 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003173 return true;
3174
3175 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3176}
3177
Alex Bradbury58eba092016-11-01 16:32:05 +00003178OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003179AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003180 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003181
Sander de Smalen50d87022018-04-19 07:35:08 +00003182 unsigned RegNum;
3183 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3184 if (Res != MatchOperand_Success)
3185 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003186
Nirav Davee833c6c2016-11-08 18:31:04 +00003187 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003188 Operands.push_back(AArch64Operand::CreateReg(
3189 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003190 return MatchOperand_Success;
3191 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003192
Nirav Davee833c6c2016-11-08 18:31:04 +00003193 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003194
Sander de Smalen50d87022018-04-19 07:35:08 +00003195 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003196 Error(getLoc(), "index must be absent or #0");
3197 return MatchOperand_ParseFail;
3198 }
3199
3200 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003201 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003202 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3203 Error(getLoc(), "index must be absent or #0");
3204 return MatchOperand_ParseFail;
3205 }
3206
Sander de Smalen50d87022018-04-19 07:35:08 +00003207 Operands.push_back(AArch64Operand::CreateReg(
3208 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003209 return MatchOperand_Success;
3210}
3211
Sander de Smalen0325e302018-07-02 07:34:52 +00003212template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
Sander de Smalen149916d2018-04-20 07:24:20 +00003213OperandMatchResultTy
3214AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3215 SMLoc StartLoc = getLoc();
3216
3217 unsigned RegNum;
3218 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3219 if (Res != MatchOperand_Success)
3220 return Res;
3221
3222 // No shift/extend is the default.
3223 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3224 Operands.push_back(AArch64Operand::CreateReg(
Sander de Smalen0325e302018-07-02 07:34:52 +00003225 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
Sander de Smalen149916d2018-04-20 07:24:20 +00003226 return MatchOperand_Success;
3227 }
3228
3229 // Eat the comma
3230 getParser().Lex();
3231
3232 // Match the shift
3233 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3234 Res = tryParseOptionalShiftExtend(ExtOpnd);
3235 if (Res != MatchOperand_Success)
3236 return Res;
3237
3238 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
Sander de Smalen0325e302018-07-02 07:34:52 +00003239 Operands.push_back(AArch64Operand::CreateReg(
3240 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3241 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3242 Ext->hasShiftExtendAmount()));
Sander de Smalen149916d2018-04-20 07:24:20 +00003243
3244 return MatchOperand_Success;
3245}
3246
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003247bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
Sander de Smalen5c625982018-04-13 12:56:14 +00003248 MCAsmParser &Parser = getParser();
3249
3250 // Some SVE instructions have a decoration after the immediate, i.e.
3251 // "mul vl". We parse them here and add tokens, which must be present in the
3252 // asm string in the tablegen instruction.
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003253 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3254 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
Sander de Smalen5c625982018-04-13 12:56:14 +00003255 if (!Parser.getTok().getString().equals_lower("mul") ||
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003256 !(NextIsVL || NextIsHash))
Sander de Smalen5c625982018-04-13 12:56:14 +00003257 return true;
3258
Sander de Smalen5c625982018-04-13 12:56:14 +00003259 Operands.push_back(
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003260 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
Sander de Smalen5c625982018-04-13 12:56:14 +00003261 Parser.Lex(); // Eat the "mul"
3262
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003263 if (NextIsVL) {
3264 Operands.push_back(
3265 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3266 Parser.Lex(); // Eat the "vl"
3267 return false;
3268 }
Sander de Smalen5c625982018-04-13 12:56:14 +00003269
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003270 if (NextIsHash) {
3271 Parser.Lex(); // Eat the #
3272 SMLoc S = getLoc();
3273
3274 // Parse immediate operand.
3275 const MCExpr *ImmVal;
3276 if (!Parser.parseExpression(ImmVal))
3277 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3278 Operands.push_back(AArch64Operand::CreateImm(
3279 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3280 getContext()));
3281 return MatchOperand_Success;
3282 }
3283 }
3284
3285 return Error(getLoc(), "expected 'vl' or '#<imm>'");
Sander de Smalen5c625982018-04-13 12:56:14 +00003286}
3287
Tim Northover3b0846e2014-05-24 12:50:23 +00003288/// parseOperand - Parse a arm instruction operand. For now this parses the
3289/// operand regardless of the mnemonic.
3290bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3291 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003292 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003293
3294 OperandMatchResultTy ResTy =
3295 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3296
Tim Northover3b0846e2014-05-24 12:50:23 +00003297 // Check if the current operand has a custom associated parser, if so, try to
3298 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003299 if (ResTy == MatchOperand_Success)
3300 return false;
3301 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3302 // there was a match, but an error occurred, in which case, just return that
3303 // the operand parsing failed.
3304 if (ResTy == MatchOperand_ParseFail)
3305 return true;
3306
3307 // Nothing custom, so do general case parsing.
3308 SMLoc S, E;
3309 switch (getLexer().getKind()) {
3310 default: {
3311 SMLoc S = getLoc();
3312 const MCExpr *Expr;
3313 if (parseSymbolicImmVal(Expr))
3314 return Error(S, "invalid operand");
3315
3316 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3317 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3318 return false;
3319 }
3320 case AsmToken::LBrac: {
3321 SMLoc Loc = Parser.getTok().getLoc();
3322 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3323 getContext()));
3324 Parser.Lex(); // Eat '['
3325
3326 // There's no comma after a '[', so we can parse the next operand
3327 // immediately.
3328 return parseOperand(Operands, false, false);
3329 }
3330 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003331 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003332 case AsmToken::Identifier: {
3333 // If we're expecting a Condition Code operand, then just parse that.
3334 if (isCondCode)
3335 return parseCondCode(Operands, invertCondCode);
3336
3337 // If it's a register name, parse it.
3338 if (!parseRegister(Operands))
3339 return false;
3340
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003341 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3342 // by SVE instructions.
3343 if (!parseOptionalMulOperand(Operands))
Sander de Smalen5c625982018-04-13 12:56:14 +00003344 return false;
3345
Tim Northover3b0846e2014-05-24 12:50:23 +00003346 // This could be an optional "shift" or "extend" operand.
3347 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3348 // We can only continue if no tokens were eaten.
3349 if (GotShift != MatchOperand_NoMatch)
3350 return GotShift;
3351
3352 // This was not a register so parse other operands that start with an
3353 // identifier (like labels) as expressions and create them as immediates.
3354 const MCExpr *IdVal;
3355 S = getLoc();
3356 if (getParser().parseExpression(IdVal))
3357 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003358 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3359 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3360 return false;
3361 }
3362 case AsmToken::Integer:
3363 case AsmToken::Real:
3364 case AsmToken::Hash: {
3365 // #42 -> immediate.
3366 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003367
3368 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003369
3370 // Parse a negative sign
3371 bool isNegative = false;
3372 if (Parser.getTok().is(AsmToken::Minus)) {
3373 isNegative = true;
3374 // We need to consume this token only when we have a Real, otherwise
3375 // we let parseSymbolicImmVal take care of it
3376 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3377 Parser.Lex();
3378 }
3379
3380 // The only Real that should come through here is a literal #0.0 for
3381 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3382 // so convert the value.
3383 const AsmToken &Tok = Parser.getTok();
3384 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003385 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003386 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3387 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3388 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
Sander de Smalen8fcc3f52018-07-03 09:07:23 +00003389 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
Tim Northover3b0846e2014-05-24 12:50:23 +00003390 return TokError("unexpected floating point literal");
3391 else if (IntVal != 0 || isNegative)
3392 return TokError("expected floating-point constant #0.0");
3393 Parser.Lex(); // Eat the token.
3394
3395 Operands.push_back(
3396 AArch64Operand::CreateToken("#0", false, S, getContext()));
3397 Operands.push_back(
3398 AArch64Operand::CreateToken(".0", false, S, getContext()));
3399 return false;
3400 }
3401
3402 const MCExpr *ImmVal;
3403 if (parseSymbolicImmVal(ImmVal))
3404 return true;
3405
3406 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3407 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3408 return false;
3409 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003410 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003411 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003412 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003413 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003414 Parser.Lex(); // Eat '='
3415 const MCExpr *SubExprVal;
3416 if (getParser().parseExpression(SubExprVal))
3417 return true;
3418
David Peixottoae5ba762014-07-18 16:05:14 +00003419 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003420 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003421 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003422
3423 bool IsXReg =
3424 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3425 Operands[1]->getReg());
3426
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003427 MCContext& Ctx = getContext();
3428 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3429 // 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 +00003430 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003431 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3432 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3433 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3434 ShiftAmt += 16;
3435 Imm >>= 16;
3436 }
3437 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3438 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3439 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003440 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003441 if (ShiftAmt)
3442 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3443 ShiftAmt, true, S, E, Ctx));
3444 return false;
3445 }
David Peixottoae5ba762014-07-18 16:05:14 +00003446 APInt Simm = APInt(64, Imm << ShiftAmt);
3447 // check if the immediate is an unsigned or signed 32-bit int for W regs
3448 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3449 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003450 }
3451 // 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 +00003452 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003453 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003454 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3455 return false;
3456 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003457 }
3458}
3459
Sander de Smalen0325e302018-07-02 07:34:52 +00003460bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3461 const MCParsedAsmOperand &Op2) const {
3462 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3463 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3464 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3465 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3466 return MCTargetAsmParser::regsEqual(Op1, Op2);
3467
3468 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3469 "Testing equality of non-scalar registers not supported");
3470
3471 // Check if a registers match their sub/super register classes.
3472 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3473 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3474 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3475 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3476 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3477 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3478 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3479 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3480
3481 return false;
3482}
3483
Tim Northover3b0846e2014-05-24 12:50:23 +00003484/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3485/// operands.
3486bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3487 StringRef Name, SMLoc NameLoc,
3488 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003489 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003490 Name = StringSwitch<StringRef>(Name.lower())
3491 .Case("beq", "b.eq")
3492 .Case("bne", "b.ne")
3493 .Case("bhs", "b.hs")
3494 .Case("bcs", "b.cs")
3495 .Case("blo", "b.lo")
3496 .Case("bcc", "b.cc")
3497 .Case("bmi", "b.mi")
3498 .Case("bpl", "b.pl")
3499 .Case("bvs", "b.vs")
3500 .Case("bvc", "b.vc")
3501 .Case("bhi", "b.hi")
3502 .Case("bls", "b.ls")
3503 .Case("bge", "b.ge")
3504 .Case("blt", "b.lt")
3505 .Case("bgt", "b.gt")
3506 .Case("ble", "b.le")
3507 .Case("bal", "b.al")
3508 .Case("bnv", "b.nv")
3509 .Default(Name);
3510
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003511 // First check for the AArch64-specific .req directive.
3512 if (Parser.getTok().is(AsmToken::Identifier) &&
3513 Parser.getTok().getIdentifier() == ".req") {
3514 parseDirectiveReq(Name, NameLoc);
3515 // We always return 'error' for this, as we're done with this
3516 // statement and don't need to match the 'instruction."
3517 return true;
3518 }
3519
Tim Northover3b0846e2014-05-24 12:50:23 +00003520 // Create the leading tokens for the mnemonic, split by '.' characters.
3521 size_t Start = 0, Next = Name.find('.');
3522 StringRef Head = Name.slice(Start, Next);
3523
3524 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003525 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3526 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003527
3528 Operands.push_back(
3529 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3530 Mnemonic = Head;
3531
3532 // Handle condition codes for a branch mnemonic
3533 if (Head == "b" && Next != StringRef::npos) {
3534 Start = Next;
3535 Next = Name.find('.', Start + 1);
3536 Head = Name.slice(Start + 1, Next);
3537
3538 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3539 (Head.data() - Name.data()));
3540 AArch64CC::CondCode CC = parseCondCodeString(Head);
3541 if (CC == AArch64CC::Invalid)
3542 return Error(SuffixLoc, "invalid condition code");
3543 Operands.push_back(
3544 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3545 Operands.push_back(
3546 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3547 }
3548
3549 // Add the remaining tokens in the mnemonic.
3550 while (Next != StringRef::npos) {
3551 Start = Next;
3552 Next = Name.find('.', Start + 1);
3553 Head = Name.slice(Start, Next);
3554 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3555 (Head.data() - Name.data()) + 1);
3556 Operands.push_back(
3557 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3558 }
3559
3560 // Conditional compare instructions have a Condition Code operand, which needs
3561 // to be parsed and an immediate operand created.
3562 bool condCodeFourthOperand =
3563 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3564 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3565 Head == "csinc" || Head == "csinv" || Head == "csneg");
3566
3567 // These instructions are aliases to some of the conditional select
3568 // instructions. However, the condition code is inverted in the aliased
3569 // instruction.
3570 //
3571 // FIXME: Is this the correct way to handle these? Or should the parser
3572 // generate the aliased instructions directly?
3573 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3574 bool condCodeThirdOperand =
3575 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3576
3577 // Read the remaining operands.
3578 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3579 // Read the first operand.
3580 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003581 return true;
3582 }
3583
3584 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003585 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003586 // Parse and remember the operand.
3587 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3588 (N == 3 && condCodeThirdOperand) ||
3589 (N == 2 && condCodeSecondOperand),
3590 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003591 return true;
3592 }
3593
3594 // After successfully parsing some operands there are two special cases to
3595 // consider (i.e. notional operands not separated by commas). Both are due
3596 // to memory specifiers:
3597 // + An RBrac will end an address for load/store/prefetch
3598 // + An '!' will indicate a pre-indexed operation.
3599 //
3600 // It's someone else's responsibility to make sure these tokens are sane
3601 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003602
Nirav Davee833c6c2016-11-08 18:31:04 +00003603 SMLoc RLoc = Parser.getTok().getLoc();
3604 if (parseOptionalToken(AsmToken::RBrac))
3605 Operands.push_back(
3606 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3607 SMLoc ELoc = Parser.getTok().getLoc();
3608 if (parseOptionalToken(AsmToken::Exclaim))
3609 Operands.push_back(
3610 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003611
3612 ++N;
3613 }
3614 }
3615
Nirav Davee833c6c2016-11-08 18:31:04 +00003616 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3617 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003618
Tim Northover3b0846e2014-05-24 12:50:23 +00003619 return false;
3620}
3621
3622// FIXME: This entire function is a giant hack to provide us with decent
3623// operand range validation/diagnostics until TableGen/MC can be extended
3624// to support autogeneration of this kind of validation.
3625bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3626 SmallVectorImpl<SMLoc> &Loc) {
3627 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3628 // Check for indexed addressing modes w/ the base register being the
3629 // same as a destination/source register or pair load where
3630 // the Rt == Rt2. All of those are undefined behaviour.
3631 switch (Inst.getOpcode()) {
3632 case AArch64::LDPSWpre:
3633 case AArch64::LDPWpost:
3634 case AArch64::LDPWpre:
3635 case AArch64::LDPXpost:
3636 case AArch64::LDPXpre: {
3637 unsigned Rt = Inst.getOperand(1).getReg();
3638 unsigned Rt2 = Inst.getOperand(2).getReg();
3639 unsigned Rn = Inst.getOperand(3).getReg();
3640 if (RI->isSubRegisterEq(Rn, Rt))
3641 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3642 "is also a destination");
3643 if (RI->isSubRegisterEq(Rn, Rt2))
3644 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3645 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003646 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003647 }
3648 case AArch64::LDPDi:
3649 case AArch64::LDPQi:
3650 case AArch64::LDPSi:
3651 case AArch64::LDPSWi:
3652 case AArch64::LDPWi:
3653 case AArch64::LDPXi: {
3654 unsigned Rt = Inst.getOperand(0).getReg();
3655 unsigned Rt2 = Inst.getOperand(1).getReg();
3656 if (Rt == Rt2)
3657 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3658 break;
3659 }
3660 case AArch64::LDPDpost:
3661 case AArch64::LDPDpre:
3662 case AArch64::LDPQpost:
3663 case AArch64::LDPQpre:
3664 case AArch64::LDPSpost:
3665 case AArch64::LDPSpre:
3666 case AArch64::LDPSWpost: {
3667 unsigned Rt = Inst.getOperand(1).getReg();
3668 unsigned Rt2 = Inst.getOperand(2).getReg();
3669 if (Rt == Rt2)
3670 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3671 break;
3672 }
3673 case AArch64::STPDpost:
3674 case AArch64::STPDpre:
3675 case AArch64::STPQpost:
3676 case AArch64::STPQpre:
3677 case AArch64::STPSpost:
3678 case AArch64::STPSpre:
3679 case AArch64::STPWpost:
3680 case AArch64::STPWpre:
3681 case AArch64::STPXpost:
3682 case AArch64::STPXpre: {
3683 unsigned Rt = Inst.getOperand(1).getReg();
3684 unsigned Rt2 = Inst.getOperand(2).getReg();
3685 unsigned Rn = Inst.getOperand(3).getReg();
3686 if (RI->isSubRegisterEq(Rn, Rt))
3687 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3688 "is also a source");
3689 if (RI->isSubRegisterEq(Rn, Rt2))
3690 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3691 "is also a source");
3692 break;
3693 }
3694 case AArch64::LDRBBpre:
3695 case AArch64::LDRBpre:
3696 case AArch64::LDRHHpre:
3697 case AArch64::LDRHpre:
3698 case AArch64::LDRSBWpre:
3699 case AArch64::LDRSBXpre:
3700 case AArch64::LDRSHWpre:
3701 case AArch64::LDRSHXpre:
3702 case AArch64::LDRSWpre:
3703 case AArch64::LDRWpre:
3704 case AArch64::LDRXpre:
3705 case AArch64::LDRBBpost:
3706 case AArch64::LDRBpost:
3707 case AArch64::LDRHHpost:
3708 case AArch64::LDRHpost:
3709 case AArch64::LDRSBWpost:
3710 case AArch64::LDRSBXpost:
3711 case AArch64::LDRSHWpost:
3712 case AArch64::LDRSHXpost:
3713 case AArch64::LDRSWpost:
3714 case AArch64::LDRWpost:
3715 case AArch64::LDRXpost: {
3716 unsigned Rt = Inst.getOperand(1).getReg();
3717 unsigned Rn = Inst.getOperand(2).getReg();
3718 if (RI->isSubRegisterEq(Rn, Rt))
3719 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3720 "is also a source");
3721 break;
3722 }
3723 case AArch64::STRBBpost:
3724 case AArch64::STRBpost:
3725 case AArch64::STRHHpost:
3726 case AArch64::STRHpost:
3727 case AArch64::STRWpost:
3728 case AArch64::STRXpost:
3729 case AArch64::STRBBpre:
3730 case AArch64::STRBpre:
3731 case AArch64::STRHHpre:
3732 case AArch64::STRHpre:
3733 case AArch64::STRWpre:
3734 case AArch64::STRXpre: {
3735 unsigned Rt = Inst.getOperand(1).getReg();
3736 unsigned Rn = Inst.getOperand(2).getReg();
3737 if (RI->isSubRegisterEq(Rn, Rt))
3738 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3739 "is also a source");
3740 break;
3741 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003742 case AArch64::STXRB:
3743 case AArch64::STXRH:
3744 case AArch64::STXRW:
3745 case AArch64::STXRX:
3746 case AArch64::STLXRB:
3747 case AArch64::STLXRH:
3748 case AArch64::STLXRW:
3749 case AArch64::STLXRX: {
3750 unsigned Rs = Inst.getOperand(0).getReg();
3751 unsigned Rt = Inst.getOperand(1).getReg();
3752 unsigned Rn = Inst.getOperand(2).getReg();
3753 if (RI->isSubRegisterEq(Rt, Rs) ||
3754 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3755 return Error(Loc[0],
3756 "unpredictable STXR instruction, status is also a source");
3757 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003758 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003759 case AArch64::STXPW:
3760 case AArch64::STXPX:
3761 case AArch64::STLXPW:
3762 case AArch64::STLXPX: {
3763 unsigned Rs = Inst.getOperand(0).getReg();
3764 unsigned Rt1 = Inst.getOperand(1).getReg();
3765 unsigned Rt2 = Inst.getOperand(2).getReg();
3766 unsigned Rn = Inst.getOperand(3).getReg();
3767 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3768 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3769 return Error(Loc[0],
3770 "unpredictable STXP instruction, status is also a source");
3771 break;
3772 }
3773 }
3774
Tim Northover3b0846e2014-05-24 12:50:23 +00003775
3776 // Now check immediate ranges. Separate from the above as there is overlap
3777 // in the instructions being checked and this keeps the nested conditionals
3778 // to a minimum.
3779 switch (Inst.getOpcode()) {
3780 case AArch64::ADDSWri:
3781 case AArch64::ADDSXri:
3782 case AArch64::ADDWri:
3783 case AArch64::ADDXri:
3784 case AArch64::SUBSWri:
3785 case AArch64::SUBSXri:
3786 case AArch64::SUBWri:
3787 case AArch64::SUBXri: {
3788 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3789 // some slight duplication here.
3790 if (Inst.getOperand(2).isExpr()) {
3791 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3792 AArch64MCExpr::VariantKind ELFRefKind;
3793 MCSymbolRefExpr::VariantKind DarwinRefKind;
3794 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003795 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3796
3797 // Only allow these with ADDXri.
3798 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3799 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3800 Inst.getOpcode() == AArch64::ADDXri)
3801 return false;
3802
3803 // Only allow these with ADDXri/ADDWri
3804 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3805 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3806 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3807 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3808 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3809 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3810 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003811 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3812 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3813 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003814 (Inst.getOpcode() == AArch64::ADDXri ||
3815 Inst.getOpcode() == AArch64::ADDWri))
3816 return false;
3817
3818 // Don't allow symbol refs in the immediate field otherwise
3819 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3820 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3821 // 'cmp w0, 'borked')
3822 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003823 }
Diana Picusc93518d2016-10-11 09:17:47 +00003824 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003825 }
3826 return false;
3827 }
3828 default:
3829 return false;
3830 }
3831}
3832
Craig Topper05515562017-10-26 06:46:41 +00003833static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3834 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003835
3836bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
Sander de Smalen0325e302018-07-02 07:34:52 +00003837 uint64_t ErrorInfo,
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003838 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003839 switch (ErrCode) {
Sander de Smalen0325e302018-07-02 07:34:52 +00003840 case Match_InvalidTiedOperand: {
3841 RegConstraintEqualityTy EqTy =
3842 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
3843 .getRegEqualityTy();
3844 switch (EqTy) {
3845 case RegConstraintEqualityTy::EqualsSubReg:
3846 return Error(Loc, "operand must be 64-bit form of destination register");
3847 case RegConstraintEqualityTy::EqualsSuperReg:
3848 return Error(Loc, "operand must be 32-bit form of destination register");
3849 case RegConstraintEqualityTy::EqualsReg:
3850 return Error(Loc, "operand must match destination register");
3851 }
3852 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003853 case Match_MissingFeature:
3854 return Error(Loc,
3855 "instruction requires a CPU feature not currently enabled");
3856 case Match_InvalidOperand:
3857 return Error(Loc, "invalid operand for instruction");
3858 case Match_InvalidSuffix:
3859 return Error(Loc, "invalid type suffix for instruction");
3860 case Match_InvalidCondCode:
3861 return Error(Loc, "expected AArch64 condition code");
3862 case Match_AddSubRegExtendSmall:
3863 return Error(Loc,
3864 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3865 case Match_AddSubRegExtendLarge:
3866 return Error(Loc,
3867 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3868 case Match_AddSubSecondSource:
3869 return Error(Loc,
3870 "expected compatible register, symbol or integer in range [0, 4095]");
3871 case Match_LogicalSecondSource:
3872 return Error(Loc, "expected compatible register or logical immediate");
3873 case Match_InvalidMovImm32Shift:
3874 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3875 case Match_InvalidMovImm64Shift:
3876 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3877 case Match_AddSubRegShift32:
3878 return Error(Loc,
3879 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3880 case Match_AddSubRegShift64:
3881 return Error(Loc,
3882 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3883 case Match_InvalidFPImm:
3884 return Error(Loc,
3885 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003886 case Match_InvalidMemoryIndexedSImm6:
3887 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003888 case Match_InvalidMemoryIndexedSImm5:
3889 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003890 case Match_InvalidMemoryIndexed1SImm4:
3891 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003892 case Match_InvalidMemoryIndexed2SImm4:
3893 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003894 case Match_InvalidMemoryIndexed3SImm4:
3895 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003896 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00003897 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00003898 case Match_InvalidMemoryIndexed16SImm4:
3899 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00003900 case Match_InvalidMemoryIndexed1SImm6:
3901 return Error(Loc, "index must be an integer in range [-32, 31].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003902 case Match_InvalidMemoryIndexedSImm9:
3903 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00003904 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00003905 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003906 case Match_InvalidMemoryIndexed4SImm7:
3907 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3908 case Match_InvalidMemoryIndexed8SImm7:
3909 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3910 case Match_InvalidMemoryIndexed16SImm7:
3911 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00003912 case Match_InvalidMemoryIndexed8UImm5:
3913 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
3914 case Match_InvalidMemoryIndexed4UImm5:
3915 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
3916 case Match_InvalidMemoryIndexed2UImm5:
3917 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00003918 case Match_InvalidMemoryIndexed8UImm6:
3919 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
3920 case Match_InvalidMemoryIndexed4UImm6:
3921 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
3922 case Match_InvalidMemoryIndexed2UImm6:
3923 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
3924 case Match_InvalidMemoryIndexed1UImm6:
3925 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003926 case Match_InvalidMemoryWExtend8:
3927 return Error(Loc,
3928 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3929 case Match_InvalidMemoryWExtend16:
3930 return Error(Loc,
3931 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3932 case Match_InvalidMemoryWExtend32:
3933 return Error(Loc,
3934 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3935 case Match_InvalidMemoryWExtend64:
3936 return Error(Loc,
3937 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3938 case Match_InvalidMemoryWExtend128:
3939 return Error(Loc,
3940 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3941 case Match_InvalidMemoryXExtend8:
3942 return Error(Loc,
3943 "expected 'lsl' or 'sxtx' with optional shift of #0");
3944 case Match_InvalidMemoryXExtend16:
3945 return Error(Loc,
3946 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3947 case Match_InvalidMemoryXExtend32:
3948 return Error(Loc,
3949 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3950 case Match_InvalidMemoryXExtend64:
3951 return Error(Loc,
3952 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3953 case Match_InvalidMemoryXExtend128:
3954 return Error(Loc,
3955 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3956 case Match_InvalidMemoryIndexed1:
3957 return Error(Loc, "index must be an integer in range [0, 4095].");
3958 case Match_InvalidMemoryIndexed2:
3959 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3960 case Match_InvalidMemoryIndexed4:
3961 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3962 case Match_InvalidMemoryIndexed8:
3963 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3964 case Match_InvalidMemoryIndexed16:
3965 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003966 case Match_InvalidImm0_1:
3967 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003968 case Match_InvalidImm0_7:
3969 return Error(Loc, "immediate must be an integer in range [0, 7].");
3970 case Match_InvalidImm0_15:
3971 return Error(Loc, "immediate must be an integer in range [0, 15].");
3972 case Match_InvalidImm0_31:
3973 return Error(Loc, "immediate must be an integer in range [0, 31].");
3974 case Match_InvalidImm0_63:
3975 return Error(Loc, "immediate must be an integer in range [0, 63].");
3976 case Match_InvalidImm0_127:
3977 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003978 case Match_InvalidImm0_255:
3979 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003980 case Match_InvalidImm0_65535:
3981 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3982 case Match_InvalidImm1_8:
3983 return Error(Loc, "immediate must be an integer in range [1, 8].");
3984 case Match_InvalidImm1_16:
3985 return Error(Loc, "immediate must be an integer in range [1, 16].");
3986 case Match_InvalidImm1_32:
3987 return Error(Loc, "immediate must be an integer in range [1, 32].");
3988 case Match_InvalidImm1_64:
3989 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00003990 case Match_InvalidSVEAddSubImm8:
3991 return Error(Loc, "immediate must be an integer in range [0, 255]"
3992 " with a shift amount of 0");
3993 case Match_InvalidSVEAddSubImm16:
3994 case Match_InvalidSVEAddSubImm32:
3995 case Match_InvalidSVEAddSubImm64:
3996 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
3997 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00003998 case Match_InvalidSVECpyImm8:
3999 return Error(Loc, "immediate must be an integer in range [-128, 255]"
4000 " with a shift amount of 0");
4001 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00004002 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4003 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004004 case Match_InvalidSVECpyImm32:
4005 case Match_InvalidSVECpyImm64:
4006 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4007 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004008 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004009 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004010 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00004011 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004012 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00004013 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004014 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004015 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004016 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004017 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004018 case Match_InvalidSVEIndexRange0_63:
4019 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4020 case Match_InvalidSVEIndexRange0_31:
4021 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4022 case Match_InvalidSVEIndexRange0_15:
4023 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4024 case Match_InvalidSVEIndexRange0_7:
4025 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4026 case Match_InvalidSVEIndexRange0_3:
4027 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004028 case Match_InvalidLabel:
4029 return Error(Loc, "expected label or encodable integer pc offset");
4030 case Match_MRS:
4031 return Error(Loc, "expected readable system register");
4032 case Match_MSR:
4033 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00004034 case Match_InvalidComplexRotationEven:
4035 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4036 case Match_InvalidComplexRotationOdd:
4037 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004038 case Match_MnemonicFail: {
4039 std::string Suggestion = AArch64MnemonicSpellCheck(
4040 ((AArch64Operand &)*Operands[0]).getToken(),
4041 ComputeAvailableFeatures(STI->getFeatureBits()));
4042 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4043 }
Sander de Smalen367694b2018-04-20 08:54:49 +00004044 case Match_InvalidGPR64shifted8:
4045 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4046 case Match_InvalidGPR64shifted16:
4047 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4048 case Match_InvalidGPR64shifted32:
4049 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4050 case Match_InvalidGPR64shifted64:
4051 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4052 case Match_InvalidGPR64NoXZRshifted8:
4053 return Error(Loc, "register must be x0..x30 without shift");
4054 case Match_InvalidGPR64NoXZRshifted16:
4055 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4056 case Match_InvalidGPR64NoXZRshifted32:
4057 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4058 case Match_InvalidGPR64NoXZRshifted64:
4059 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004060 case Match_InvalidZPR32UXTW8:
4061 case Match_InvalidZPR32SXTW8:
4062 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4063 case Match_InvalidZPR32UXTW16:
4064 case Match_InvalidZPR32SXTW16:
4065 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4066 case Match_InvalidZPR32UXTW32:
4067 case Match_InvalidZPR32SXTW32:
4068 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4069 case Match_InvalidZPR32UXTW64:
4070 case Match_InvalidZPR32SXTW64:
4071 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4072 case Match_InvalidZPR64UXTW8:
4073 case Match_InvalidZPR64SXTW8:
4074 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4075 case Match_InvalidZPR64UXTW16:
4076 case Match_InvalidZPR64SXTW16:
4077 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4078 case Match_InvalidZPR64UXTW32:
4079 case Match_InvalidZPR64SXTW32:
4080 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4081 case Match_InvalidZPR64UXTW64:
4082 case Match_InvalidZPR64SXTW64:
4083 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
4084 case Match_InvalidZPR64LSL8:
4085 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4086 case Match_InvalidZPR64LSL16:
4087 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4088 case Match_InvalidZPR64LSL32:
4089 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4090 case Match_InvalidZPR64LSL64:
4091 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00004092 case Match_InvalidZPR0:
4093 return Error(Loc, "expected register without element width sufix");
4094 case Match_InvalidZPR8:
4095 case Match_InvalidZPR16:
4096 case Match_InvalidZPR32:
4097 case Match_InvalidZPR64:
4098 case Match_InvalidZPR128:
4099 return Error(Loc, "invalid element width");
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004100 case Match_InvalidZPR_3b8:
4101 return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b");
4102 case Match_InvalidZPR_3b16:
4103 return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h");
4104 case Match_InvalidZPR_3b32:
4105 return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s");
4106 case Match_InvalidZPR_4b16:
4107 return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h");
4108 case Match_InvalidZPR_4b32:
4109 return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s");
4110 case Match_InvalidZPR_4b64:
4111 return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004112 case Match_InvalidSVEPattern:
4113 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004114 case Match_InvalidSVEPredicateAnyReg:
4115 case Match_InvalidSVEPredicateBReg:
4116 case Match_InvalidSVEPredicateHReg:
4117 case Match_InvalidSVEPredicateSReg:
4118 case Match_InvalidSVEPredicateDReg:
4119 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004120 case Match_InvalidSVEPredicate3bAnyReg:
4121 case Match_InvalidSVEPredicate3bBReg:
4122 case Match_InvalidSVEPredicate3bHReg:
4123 case Match_InvalidSVEPredicate3bSReg:
4124 case Match_InvalidSVEPredicate3bDReg:
4125 return Error(Loc, "restricted predicate has range [0, 7].");
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004126 case Match_InvalidSVEExactFPImmOperandHalfOne:
4127 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4128 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4129 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4130 case Match_InvalidSVEExactFPImmOperandZeroOne:
4131 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004132 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004133 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004134 }
4135}
4136
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004137static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004138
4139bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4140 OperandVector &Operands,
4141 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004142 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004143 bool MatchingInlineAsm) {
4144 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004145 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4146 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004147
David Blaikie960ea3f2014-06-08 16:18:35 +00004148 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004149 unsigned NumOperands = Operands.size();
4150
4151 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004152 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4153 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004154 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004155 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004156 if (Op3CE) {
4157 uint64_t Op3Val = Op3CE->getValue();
4158 uint64_t NewOp3Val = 0;
4159 uint64_t NewOp4Val = 0;
4160 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004161 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004162 NewOp3Val = (32 - Op3Val) & 0x1f;
4163 NewOp4Val = 31 - Op3Val;
4164 } else {
4165 NewOp3Val = (64 - Op3Val) & 0x3f;
4166 NewOp4Val = 63 - Op3Val;
4167 }
4168
Jim Grosbach13760bd2015-05-30 01:25:56 +00004169 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4170 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004171
4172 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004173 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004174 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004175 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4176 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4177 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004178 }
4179 }
Tim Northover03b99f62015-04-30 18:28:58 +00004180 } else if (NumOperands == 4 && Tok == "bfc") {
4181 // FIXME: Horrible hack to handle BFC->BFM alias.
4182 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4183 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4184 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4185
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004186 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004187 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4188 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4189
4190 if (LSBCE && WidthCE) {
4191 uint64_t LSB = LSBCE->getValue();
4192 uint64_t Width = WidthCE->getValue();
4193
4194 uint64_t RegWidth = 0;
4195 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4196 Op1.getReg()))
4197 RegWidth = 64;
4198 else
4199 RegWidth = 32;
4200
4201 if (LSB >= RegWidth)
4202 return Error(LSBOp.getStartLoc(),
4203 "expected integer in range [0, 31]");
4204 if (Width < 1 || Width > RegWidth)
4205 return Error(WidthOp.getStartLoc(),
4206 "expected integer in range [1, 32]");
4207
4208 uint64_t ImmR = 0;
4209 if (RegWidth == 32)
4210 ImmR = (32 - LSB) & 0x1f;
4211 else
4212 ImmR = (64 - LSB) & 0x3f;
4213
4214 uint64_t ImmS = Width - 1;
4215
4216 if (ImmR != 0 && ImmS >= ImmR)
4217 return Error(WidthOp.getStartLoc(),
4218 "requested insert overflows register");
4219
Jim Grosbach13760bd2015-05-30 01:25:56 +00004220 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4221 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004222 Operands[0] = AArch64Operand::CreateToken(
4223 "bfm", false, Op.getStartLoc(), getContext());
4224 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004225 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4226 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004227 Operands[3] = AArch64Operand::CreateImm(
4228 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4229 Operands.emplace_back(
4230 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4231 WidthOp.getEndLoc(), getContext()));
4232 }
4233 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004234 } else if (NumOperands == 5) {
4235 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4236 // UBFIZ -> UBFM aliases.
4237 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004238 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4239 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4240 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004241
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004242 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004243 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4244 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004245
4246 if (Op3CE && Op4CE) {
4247 uint64_t Op3Val = Op3CE->getValue();
4248 uint64_t Op4Val = Op4CE->getValue();
4249
4250 uint64_t RegWidth = 0;
4251 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004252 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004253 RegWidth = 64;
4254 else
4255 RegWidth = 32;
4256
4257 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004258 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004259 "expected integer in range [0, 31]");
4260 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004261 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004262 "expected integer in range [1, 32]");
4263
4264 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004265 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004266 NewOp3Val = (32 - Op3Val) & 0x1f;
4267 else
4268 NewOp3Val = (64 - Op3Val) & 0x3f;
4269
4270 uint64_t NewOp4Val = Op4Val - 1;
4271
4272 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004273 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004274 "requested insert overflows register");
4275
4276 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004277 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004278 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004279 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004280 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004281 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004282 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004283 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004284 if (Tok == "bfi")
4285 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004286 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004287 else if (Tok == "sbfiz")
4288 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004289 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004290 else if (Tok == "ubfiz")
4291 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004292 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004293 else
4294 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004295 }
4296 }
4297
4298 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4299 // UBFX -> UBFM aliases.
4300 } else if (NumOperands == 5 &&
4301 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004302 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4303 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4304 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004305
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004306 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004307 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4308 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004309
4310 if (Op3CE && Op4CE) {
4311 uint64_t Op3Val = Op3CE->getValue();
4312 uint64_t Op4Val = Op4CE->getValue();
4313
4314 uint64_t RegWidth = 0;
4315 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004316 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004317 RegWidth = 64;
4318 else
4319 RegWidth = 32;
4320
4321 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004322 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004323 "expected integer in range [0, 31]");
4324 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004325 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004326 "expected integer in range [1, 32]");
4327
4328 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4329
4330 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004331 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004332 "requested extract overflows register");
4333
4334 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004335 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004336 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004337 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004338 if (Tok == "bfxil")
4339 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004340 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004341 else if (Tok == "sbfx")
4342 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004343 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004344 else if (Tok == "ubfx")
4345 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004346 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004347 else
4348 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004349 }
4350 }
4351 }
4352 }
Tim Northover9097a072017-12-18 10:36:00 +00004353
4354 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4355 // instruction for FP registers correctly in some rare circumstances. Convert
4356 // it to a safe instruction and warn (because silently changing someone's
4357 // assembly is rude).
4358 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4359 NumOperands == 4 && Tok == "movi") {
4360 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4361 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4362 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4363 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4364 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4365 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4366 if (Suffix.lower() == ".2d" &&
4367 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4368 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4369 " correctly on this CPU, converting to equivalent movi.16b");
4370 // Switch the suffix to .16b.
4371 unsigned Idx = Op1.isToken() ? 1 : 2;
4372 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4373 getContext());
4374 }
4375 }
4376 }
4377
Tim Northover3b0846e2014-05-24 12:50:23 +00004378 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4379 // InstAlias can't quite handle this since the reg classes aren't
4380 // subclasses.
4381 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4382 // The source register can be Wn here, but the matcher expects a
4383 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004384 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004385 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004386 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004387 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4388 Op.getStartLoc(), Op.getEndLoc(),
4389 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004390 }
4391 }
4392 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4393 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004394 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004395 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004396 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004397 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004398 // The source register can be Wn here, but the matcher expects a
4399 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004400 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004401 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004402 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004403 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4404 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004405 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004406 }
4407 }
4408 }
4409 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4410 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004411 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004412 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004413 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004414 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004415 // The source register can be Wn here, but the matcher expects a
4416 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004417 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004418 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004419 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004420 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4421 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004422 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004423 }
4424 }
4425 }
4426
Tim Northover3b0846e2014-05-24 12:50:23 +00004427 MCInst Inst;
4428 // First try to match against the secondary set of tables containing the
4429 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4430 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004431 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004432
4433 // If that fails, try against the alternate table containing long-form NEON:
4434 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004435 if (MatchResult != Match_Success) {
4436 // But first, save the short-form match result: we can use it in case the
4437 // long-form match also fails.
4438 auto ShortFormNEONErrorInfo = ErrorInfo;
4439 auto ShortFormNEONMatchResult = MatchResult;
4440
Tim Northover3b0846e2014-05-24 12:50:23 +00004441 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004442 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004443
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004444 // Now, both matches failed, and the long-form match failed on the mnemonic
4445 // suffix token operand. The short-form match failure is probably more
4446 // relevant: use it instead.
4447 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004448 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004449 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4450 MatchResult = ShortFormNEONMatchResult;
4451 ErrorInfo = ShortFormNEONErrorInfo;
4452 }
4453 }
4454
Tim Northover3b0846e2014-05-24 12:50:23 +00004455 switch (MatchResult) {
4456 case Match_Success: {
4457 // Perform range checking and other semantic validations
4458 SmallVector<SMLoc, 8> OperandLocs;
4459 NumOperands = Operands.size();
4460 for (unsigned i = 1; i < NumOperands; ++i)
4461 OperandLocs.push_back(Operands[i]->getStartLoc());
4462 if (validateInstruction(Inst, OperandLocs))
4463 return true;
4464
4465 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004466 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004467 return false;
4468 }
4469 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004470 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004471 // Special case the error message for the very common case where only
4472 // a single subtarget feature is missing (neon, e.g.).
4473 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004474 uint64_t Mask = 1;
4475 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4476 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004477 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004478 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004479 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004480 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004481 }
4482 return Error(IDLoc, Msg);
4483 }
4484 case Match_MnemonicFail:
Sander de Smalen0325e302018-07-02 07:34:52 +00004485 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004486 case Match_InvalidOperand: {
4487 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004488
Tim Northover26bb14e2014-08-18 11:49:42 +00004489 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004490 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004491 return Error(IDLoc, "too few operands for instruction",
4492 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004493
David Blaikie960ea3f2014-06-08 16:18:35 +00004494 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004495 if (ErrorLoc == SMLoc())
4496 ErrorLoc = IDLoc;
4497 }
4498 // If the match failed on a suffix token operand, tweak the diagnostic
4499 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004500 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4501 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004502 MatchResult = Match_InvalidSuffix;
4503
Sander de Smalen0325e302018-07-02 07:34:52 +00004504 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004505 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004506 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004507 case Match_InvalidMemoryIndexed1:
4508 case Match_InvalidMemoryIndexed2:
4509 case Match_InvalidMemoryIndexed4:
4510 case Match_InvalidMemoryIndexed8:
4511 case Match_InvalidMemoryIndexed16:
4512 case Match_InvalidCondCode:
4513 case Match_AddSubRegExtendSmall:
4514 case Match_AddSubRegExtendLarge:
4515 case Match_AddSubSecondSource:
4516 case Match_LogicalSecondSource:
4517 case Match_AddSubRegShift32:
4518 case Match_AddSubRegShift64:
4519 case Match_InvalidMovImm32Shift:
4520 case Match_InvalidMovImm64Shift:
4521 case Match_InvalidFPImm:
4522 case Match_InvalidMemoryWExtend8:
4523 case Match_InvalidMemoryWExtend16:
4524 case Match_InvalidMemoryWExtend32:
4525 case Match_InvalidMemoryWExtend64:
4526 case Match_InvalidMemoryWExtend128:
4527 case Match_InvalidMemoryXExtend8:
4528 case Match_InvalidMemoryXExtend16:
4529 case Match_InvalidMemoryXExtend32:
4530 case Match_InvalidMemoryXExtend64:
4531 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004532 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004533 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004534 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004535 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004536 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004537 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004538 case Match_InvalidMemoryIndexed4SImm7:
4539 case Match_InvalidMemoryIndexed8SImm7:
4540 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004541 case Match_InvalidMemoryIndexed8UImm5:
4542 case Match_InvalidMemoryIndexed4UImm5:
4543 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004544 case Match_InvalidMemoryIndexed1UImm6:
4545 case Match_InvalidMemoryIndexed2UImm6:
4546 case Match_InvalidMemoryIndexed4UImm6:
4547 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004548 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004549 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004550 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004551 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004552 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004553 case Match_InvalidImm0_7:
4554 case Match_InvalidImm0_15:
4555 case Match_InvalidImm0_31:
4556 case Match_InvalidImm0_63:
4557 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004558 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004559 case Match_InvalidImm0_65535:
4560 case Match_InvalidImm1_8:
4561 case Match_InvalidImm1_16:
4562 case Match_InvalidImm1_32:
4563 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004564 case Match_InvalidSVEAddSubImm8:
4565 case Match_InvalidSVEAddSubImm16:
4566 case Match_InvalidSVEAddSubImm32:
4567 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004568 case Match_InvalidSVECpyImm8:
4569 case Match_InvalidSVECpyImm16:
4570 case Match_InvalidSVECpyImm32:
4571 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004572 case Match_InvalidIndexRange1_1:
4573 case Match_InvalidIndexRange0_15:
4574 case Match_InvalidIndexRange0_7:
4575 case Match_InvalidIndexRange0_3:
4576 case Match_InvalidIndexRange0_1:
4577 case Match_InvalidSVEIndexRange0_63:
4578 case Match_InvalidSVEIndexRange0_31:
4579 case Match_InvalidSVEIndexRange0_15:
4580 case Match_InvalidSVEIndexRange0_7:
4581 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004582 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004583 case Match_InvalidComplexRotationEven:
4584 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004585 case Match_InvalidGPR64shifted8:
4586 case Match_InvalidGPR64shifted16:
4587 case Match_InvalidGPR64shifted32:
4588 case Match_InvalidGPR64shifted64:
4589 case Match_InvalidGPR64NoXZRshifted8:
4590 case Match_InvalidGPR64NoXZRshifted16:
4591 case Match_InvalidGPR64NoXZRshifted32:
4592 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004593 case Match_InvalidZPR32UXTW8:
4594 case Match_InvalidZPR32UXTW16:
4595 case Match_InvalidZPR32UXTW32:
4596 case Match_InvalidZPR32UXTW64:
4597 case Match_InvalidZPR32SXTW8:
4598 case Match_InvalidZPR32SXTW16:
4599 case Match_InvalidZPR32SXTW32:
4600 case Match_InvalidZPR32SXTW64:
4601 case Match_InvalidZPR64UXTW8:
4602 case Match_InvalidZPR64SXTW8:
4603 case Match_InvalidZPR64UXTW16:
4604 case Match_InvalidZPR64SXTW16:
4605 case Match_InvalidZPR64UXTW32:
4606 case Match_InvalidZPR64SXTW32:
4607 case Match_InvalidZPR64UXTW64:
4608 case Match_InvalidZPR64SXTW64:
4609 case Match_InvalidZPR64LSL8:
4610 case Match_InvalidZPR64LSL16:
4611 case Match_InvalidZPR64LSL32:
4612 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004613 case Match_InvalidZPR0:
4614 case Match_InvalidZPR8:
4615 case Match_InvalidZPR16:
4616 case Match_InvalidZPR32:
4617 case Match_InvalidZPR64:
4618 case Match_InvalidZPR128:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004619 case Match_InvalidZPR_3b8:
4620 case Match_InvalidZPR_3b16:
4621 case Match_InvalidZPR_3b32:
4622 case Match_InvalidZPR_4b16:
4623 case Match_InvalidZPR_4b32:
4624 case Match_InvalidZPR_4b64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004625 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004626 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004627 case Match_InvalidSVEPredicateBReg:
4628 case Match_InvalidSVEPredicateHReg:
4629 case Match_InvalidSVEPredicateSReg:
4630 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004631 case Match_InvalidSVEPredicate3bAnyReg:
4632 case Match_InvalidSVEPredicate3bBReg:
4633 case Match_InvalidSVEPredicate3bHReg:
4634 case Match_InvalidSVEPredicate3bSReg:
4635 case Match_InvalidSVEPredicate3bDReg:
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004636 case Match_InvalidSVEExactFPImmOperandHalfOne:
4637 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4638 case Match_InvalidSVEExactFPImmOperandZeroOne:
Tim Northover3b0846e2014-05-24 12:50:23 +00004639 case Match_MSR:
4640 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004641 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004642 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004643 // Any time we get here, there's nothing fancy to do. Just get the
4644 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004645 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004646 if (ErrorLoc == SMLoc())
4647 ErrorLoc = IDLoc;
Sander de Smalen0325e302018-07-02 07:34:52 +00004648 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004649 }
4650 }
4651
4652 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004653}
4654
4655/// ParseDirective parses the arm specific directives
4656bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004657 const MCObjectFileInfo::Environment Format =
4658 getContext().getObjectFileInfo()->getObjectFileType();
4659 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4660 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004661
Tim Northover3b0846e2014-05-24 12:50:23 +00004662 StringRef IDVal = DirectiveID.getIdentifier();
4663 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004664 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004665 parseDirectiveArch(Loc);
4666 else if (IDVal == ".cpu")
4667 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00004668 else if (IDVal == ".tlsdesccall")
4669 parseDirectiveTLSDescCall(Loc);
4670 else if (IDVal == ".ltorg" || IDVal == ".pool")
4671 parseDirectiveLtorg(Loc);
4672 else if (IDVal == ".unreq")
4673 parseDirectiveUnreq(Loc);
4674 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004675 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004676 parseDirectiveInst(Loc);
4677 else
4678 return true;
4679 } else if (IDVal == MCLOHDirectiveName())
4680 parseDirectiveLOH(IDVal, Loc);
4681 else
4682 return true;
4683 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004684}
4685
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004686static const struct {
4687 const char *Name;
4688 const FeatureBitset Features;
4689} ExtensionMap[] = {
4690 { "crc", {AArch64::FeatureCRC} },
4691 { "crypto", {AArch64::FeatureCrypto} },
4692 { "fp", {AArch64::FeatureFPARMv8} },
4693 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004694 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004695 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004696
4697 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004698 { "pan", {} },
4699 { "lor", {} },
4700 { "rdma", {} },
4701 { "profile", {} },
4702};
4703
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004704/// parseDirectiveArch
4705/// ::= .arch token
4706bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4707 SMLoc ArchLoc = getLoc();
4708
4709 StringRef Arch, ExtensionString;
4710 std::tie(Arch, ExtensionString) =
4711 getParser().parseStringToEndOfStatement().trim().split('+');
4712
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004713 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4714 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004715 return Error(ArchLoc, "unknown arch name");
4716
4717 if (parseToken(AsmToken::EndOfStatement))
4718 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004719
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004720 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004721 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004722 AArch64::getArchFeatures(ID, AArch64Features);
4723 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4724 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004725
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004726 MCSubtargetInfo &STI = copySTI();
4727 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4728 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4729
4730 SmallVector<StringRef, 4> RequestedExtensions;
4731 if (!ExtensionString.empty())
4732 ExtensionString.split(RequestedExtensions, '+');
4733
4734 FeatureBitset Features = STI.getFeatureBits();
4735 for (auto Name : RequestedExtensions) {
4736 bool EnableFeature = true;
4737
4738 if (Name.startswith_lower("no")) {
4739 EnableFeature = false;
4740 Name = Name.substr(2);
4741 }
4742
4743 for (const auto &Extension : ExtensionMap) {
4744 if (Extension.Name != Name)
4745 continue;
4746
4747 if (Extension.Features.none())
4748 report_fatal_error("unsupported architectural extension: " + Name);
4749
4750 FeatureBitset ToggleFeatures = EnableFeature
4751 ? (~Features & Extension.Features)
4752 : ( Features & Extension.Features);
4753 uint64_t Features =
4754 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4755 setAvailableFeatures(Features);
4756 break;
4757 }
4758 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004759 return false;
4760}
4761
Tim Northover8b96c7e2017-05-15 19:42:15 +00004762static SMLoc incrementLoc(SMLoc L, int Offset) {
4763 return SMLoc::getFromPointer(L.getPointer() + Offset);
4764}
4765
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004766/// parseDirectiveCPU
4767/// ::= .cpu id
4768bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004769 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004770
4771 StringRef CPU, ExtensionString;
4772 std::tie(CPU, ExtensionString) =
4773 getParser().parseStringToEndOfStatement().trim().split('+');
4774
Nirav Davee833c6c2016-11-08 18:31:04 +00004775 if (parseToken(AsmToken::EndOfStatement))
4776 return true;
4777
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004778 SmallVector<StringRef, 4> RequestedExtensions;
4779 if (!ExtensionString.empty())
4780 ExtensionString.split(RequestedExtensions, '+');
4781
4782 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4783 // once that is tablegen'ed
4784 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004785 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004786 return false;
4787 }
4788
4789 MCSubtargetInfo &STI = copySTI();
4790 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004791 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004792
4793 FeatureBitset Features = STI.getFeatureBits();
4794 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004795 // Advance source location past '+'.
4796 CurLoc = incrementLoc(CurLoc, 1);
4797
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004798 bool EnableFeature = true;
4799
4800 if (Name.startswith_lower("no")) {
4801 EnableFeature = false;
4802 Name = Name.substr(2);
4803 }
4804
Tim Northover8b96c7e2017-05-15 19:42:15 +00004805 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004806 for (const auto &Extension : ExtensionMap) {
4807 if (Extension.Name != Name)
4808 continue;
4809
4810 if (Extension.Features.none())
4811 report_fatal_error("unsupported architectural extension: " + Name);
4812
4813 FeatureBitset ToggleFeatures = EnableFeature
4814 ? (~Features & Extension.Features)
4815 : ( Features & Extension.Features);
4816 uint64_t Features =
4817 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4818 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004819 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004820
4821 break;
4822 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004823
4824 if (!FoundExtension)
4825 Error(CurLoc, "unsupported architectural extension");
4826
4827 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004828 }
4829 return false;
4830}
4831
Chad Rosierdcd2a302014-10-22 20:35:57 +00004832/// parseDirectiveInst
4833/// ::= .inst opcode [, ...]
4834bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004835 if (getLexer().is(AsmToken::EndOfStatement))
4836 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004837
Nirav Davee833c6c2016-11-08 18:31:04 +00004838 auto parseOp = [&]() -> bool {
4839 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004840 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004841 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4842 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004843 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004844 if (check(!Value, L, "expected constant expression"))
4845 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004846 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004847 return false;
4848 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004849
Nirav Davee833c6c2016-11-08 18:31:04 +00004850 if (parseMany(parseOp))
4851 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004852 return false;
4853}
4854
Tim Northover3b0846e2014-05-24 12:50:23 +00004855// parseDirectiveTLSDescCall:
4856// ::= .tlsdesccall symbol
4857bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4858 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004859 if (check(getParser().parseIdentifier(Name), L,
4860 "expected symbol after directive") ||
4861 parseToken(AsmToken::EndOfStatement))
4862 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004863
Jim Grosbach6f482002015-05-18 18:43:14 +00004864 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004865 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4866 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004867
4868 MCInst Inst;
4869 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004870 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004871
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004872 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004873 return false;
4874}
4875
4876/// ::= .loh <lohName | lohId> label1, ..., labelN
4877/// The number of arguments depends on the loh identifier.
4878bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004879 MCLOHType Kind;
4880 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4881 if (getParser().getTok().isNot(AsmToken::Integer))
4882 return TokError("expected an identifier or a number in directive");
4883 // We successfully get a numeric value for the identifier.
4884 // Check if it is valid.
4885 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004886 if (Id <= -1U && !isValidMCLOHType(Id))
4887 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004888 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004889 } else {
4890 StringRef Name = getTok().getIdentifier();
4891 // We successfully parse an identifier.
4892 // Check if it is a recognized one.
4893 int Id = MCLOHNameToId(Name);
4894
4895 if (Id == -1)
4896 return TokError("invalid identifier in directive");
4897 Kind = (MCLOHType)Id;
4898 }
4899 // Consume the identifier.
4900 Lex();
4901 // Get the number of arguments of this LOH.
4902 int NbArgs = MCLOHIdToNbArgs(Kind);
4903
4904 assert(NbArgs != -1 && "Invalid number of arguments");
4905
4906 SmallVector<MCSymbol *, 3> Args;
4907 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4908 StringRef Name;
4909 if (getParser().parseIdentifier(Name))
4910 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004911 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004912
4913 if (Idx + 1 == NbArgs)
4914 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004915 if (parseToken(AsmToken::Comma,
4916 "unexpected token in '" + Twine(IDVal) + "' directive"))
4917 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004918 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004919 if (parseToken(AsmToken::EndOfStatement,
4920 "unexpected token in '" + Twine(IDVal) + "' directive"))
4921 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004922
4923 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4924 return false;
4925}
4926
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004927/// parseDirectiveLtorg
4928/// ::= .ltorg | .pool
4929bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004930 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4931 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004932 getTargetStreamer().emitCurrentConstantPool();
4933 return false;
4934}
4935
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004936/// parseDirectiveReq
4937/// ::= name .req registername
4938bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004939 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004940 Parser.Lex(); // Eat the '.req' token.
4941 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004942 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004943 unsigned RegNum;
4944 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004945
Sander de Smalen50d87022018-04-19 07:35:08 +00004946 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004947 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004948 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004949 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004950
Sander de Smalen50d87022018-04-19 07:35:08 +00004951 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004952 return true;
4953
Sander de Smalen50d87022018-04-19 07:35:08 +00004954 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004955 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004956 }
4957
Sander de Smalen50d87022018-04-19 07:35:08 +00004958 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004959 StringRef Kind;
4960 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004961 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004962 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004963
Sander de Smalen50d87022018-04-19 07:35:08 +00004964 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004965 return true;
4966
Sander de Smalen50d87022018-04-19 07:35:08 +00004967 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004968 return Error(SRegLoc,
4969 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004970 }
4971
Sander de Smalen50d87022018-04-19 07:35:08 +00004972 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00004973 StringRef Kind;
4974 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004975 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004976
Sander de Smalen50d87022018-04-19 07:35:08 +00004977 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00004978 return true;
4979
Sander de Smalen50d87022018-04-19 07:35:08 +00004980 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00004981 return Error(SRegLoc,
4982 "sve predicate register without type specifier expected");
4983 }
4984
Sander de Smalen50d87022018-04-19 07:35:08 +00004985 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00004986 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004987
4988 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004989 if (parseToken(AsmToken::EndOfStatement,
4990 "unexpected input in .req directive"))
4991 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004992
Sander de Smalen8e607342017-11-15 15:44:43 +00004993 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004994 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004995 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4996
Nirav Dave2364748a2016-09-16 18:30:20 +00004997 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004998}
4999
5000/// parseDirectiveUneq
5001/// ::= .unreq registername
5002bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005003 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00005004 if (getTok().isNot(AsmToken::Identifier))
5005 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005006 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
5007 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00005008 if (parseToken(AsmToken::EndOfStatement))
5009 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005010 return false;
5011}
5012
Tim Northover3b0846e2014-05-24 12:50:23 +00005013bool
5014AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
5015 AArch64MCExpr::VariantKind &ELFRefKind,
5016 MCSymbolRefExpr::VariantKind &DarwinRefKind,
5017 int64_t &Addend) {
5018 ELFRefKind = AArch64MCExpr::VK_INVALID;
5019 DarwinRefKind = MCSymbolRefExpr::VK_None;
5020 Addend = 0;
5021
5022 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5023 ELFRefKind = AE->getKind();
5024 Expr = AE->getSubExpr();
5025 }
5026
5027 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5028 if (SE) {
5029 // It's a simple symbol reference with no addend.
5030 DarwinRefKind = SE->getKind();
5031 return true;
5032 }
5033
5034 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
5035 if (!BE)
5036 return false;
5037
5038 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
5039 if (!SE)
5040 return false;
5041 DarwinRefKind = SE->getKind();
5042
5043 if (BE->getOpcode() != MCBinaryExpr::Add &&
5044 BE->getOpcode() != MCBinaryExpr::Sub)
5045 return false;
5046
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00005047 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00005048 // on here than we can deal with.
5049 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
5050 if (!AddendExpr)
5051 return false;
5052
5053 Addend = AddendExpr->getValue();
5054 if (BE->getOpcode() == MCBinaryExpr::Sub)
5055 Addend = -Addend;
5056
5057 // It's some symbol reference + a constant addend, but really
5058 // shouldn't use both Darwin and ELF syntax.
5059 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5060 DarwinRefKind == MCSymbolRefExpr::VK_None;
5061}
5062
5063/// Force static initialization.
5064extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00005065 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5066 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5067 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00005068}
5069
5070#define GET_REGISTER_MATCHER
5071#define GET_SUBTARGET_FEATURE_NAME
5072#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00005073#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00005074#include "AArch64GenAsmMatcher.inc"
5075
5076// Define this matcher function after the auto-generated include so we
5077// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00005078unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00005079 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005080 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00005081 // If the kind is a token for a literal immediate, check if our asm
5082 // operand matches. This is for InstAliases which have a fixed-value
5083 // immediate in the syntax.
5084 int64_t ExpectedVal;
5085 switch (Kind) {
5086 default:
5087 return Match_InvalidOperand;
5088 case MCK__35_0:
5089 ExpectedVal = 0;
5090 break;
5091 case MCK__35_1:
5092 ExpectedVal = 1;
5093 break;
5094 case MCK__35_12:
5095 ExpectedVal = 12;
5096 break;
5097 case MCK__35_16:
5098 ExpectedVal = 16;
5099 break;
5100 case MCK__35_2:
5101 ExpectedVal = 2;
5102 break;
5103 case MCK__35_24:
5104 ExpectedVal = 24;
5105 break;
5106 case MCK__35_3:
5107 ExpectedVal = 3;
5108 break;
5109 case MCK__35_32:
5110 ExpectedVal = 32;
5111 break;
5112 case MCK__35_4:
5113 ExpectedVal = 4;
5114 break;
5115 case MCK__35_48:
5116 ExpectedVal = 48;
5117 break;
5118 case MCK__35_6:
5119 ExpectedVal = 6;
5120 break;
5121 case MCK__35_64:
5122 ExpectedVal = 64;
5123 break;
5124 case MCK__35_8:
5125 ExpectedVal = 8;
5126 break;
5127 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005128 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005129 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005130 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005131 if (!CE)
5132 return Match_InvalidOperand;
5133 if (CE->getValue() == ExpectedVal)
5134 return Match_Success;
5135 return Match_InvalidOperand;
5136}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005137
Alex Bradbury58eba092016-11-01 16:32:05 +00005138OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005139AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5140
5141 SMLoc S = getLoc();
5142
5143 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5144 Error(S, "expected register");
5145 return MatchOperand_ParseFail;
5146 }
5147
Sander de Smalen50d87022018-04-19 07:35:08 +00005148 unsigned FirstReg;
5149 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5150 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005151 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005152
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005153 const MCRegisterClass &WRegClass =
5154 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5155 const MCRegisterClass &XRegClass =
5156 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5157
5158 bool isXReg = XRegClass.contains(FirstReg),
5159 isWReg = WRegClass.contains(FirstReg);
5160 if (!isXReg && !isWReg) {
5161 Error(S, "expected first even register of a "
5162 "consecutive same-size even/odd register pair");
5163 return MatchOperand_ParseFail;
5164 }
5165
5166 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5167 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5168
5169 if (FirstEncoding & 0x1) {
5170 Error(S, "expected first even register of a "
5171 "consecutive same-size even/odd register pair");
5172 return MatchOperand_ParseFail;
5173 }
5174
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005175 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005176 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005177 return MatchOperand_ParseFail;
5178 }
5179 // Eat the comma
5180 getParser().Lex();
5181
5182 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005183 unsigned SecondReg;
5184 Res = tryParseScalarRegister(SecondReg);
5185 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005186 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005187
Eugene Zelenko049b0172017-01-06 00:30:53 +00005188 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005189 (isXReg && !XRegClass.contains(SecondReg)) ||
5190 (isWReg && !WRegClass.contains(SecondReg))) {
5191 Error(E,"expected second odd register of a "
5192 "consecutive same-size even/odd register pair");
5193 return MatchOperand_ParseFail;
5194 }
Joel Jones504bf332016-10-24 13:37:13 +00005195
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005196 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005197 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005198 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5199 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5200 } else {
5201 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5202 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5203 }
5204
Florian Hahnc4422242017-11-07 13:07:50 +00005205 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5206 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005207
5208 return MatchOperand_Success;
5209}
Florian Hahn91f11e52017-11-07 16:45:48 +00005210
Sander de Smaleneb896b12018-04-25 09:26:47 +00005211template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005212OperandMatchResultTy
5213AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005214 const SMLoc S = getLoc();
5215 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005216 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005217 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005218
Sander de Smalen8e607342017-11-15 15:44:43 +00005219 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005220 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005221
5222 if (Res != MatchOperand_Success)
5223 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005224
5225 if (ParseSuffix && Kind.empty())
5226 return MatchOperand_NoMatch;
5227
Sander de Smalen73937b72018-04-11 07:36:10 +00005228 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5229 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005230 return MatchOperand_NoMatch;
5231
Sander de Smalen73937b72018-04-11 07:36:10 +00005232 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005233
5234 // No shift/extend is the default.
5235 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5236 Operands.push_back(AArch64Operand::CreateVectorReg(
5237 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5238
Sander de Smalenc33d6682018-06-04 06:40:55 +00005239 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5240 if (Res == MatchOperand_ParseFail)
5241 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005242 return MatchOperand_Success;
5243 }
5244
5245 // Eat the comma
5246 getParser().Lex();
5247
5248 // Match the shift
5249 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5250 Res = tryParseOptionalShiftExtend(ExtOpnd);
5251 if (Res != MatchOperand_Success)
5252 return Res;
5253
5254 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005255 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005256 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5257 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5258 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005259
5260 return MatchOperand_Success;
5261}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005262
5263OperandMatchResultTy
5264AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5265 MCAsmParser &Parser = getParser();
5266
5267 SMLoc SS = getLoc();
5268 const AsmToken &TokE = Parser.getTok();
5269 bool IsHash = TokE.is(AsmToken::Hash);
5270
5271 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5272 return MatchOperand_NoMatch;
5273
5274 int64_t Pattern;
5275 if (IsHash) {
5276 Parser.Lex(); // Eat hash
5277
5278 // Parse the immediate operand.
5279 const MCExpr *ImmVal;
5280 SS = getLoc();
5281 if (Parser.parseExpression(ImmVal))
5282 return MatchOperand_ParseFail;
5283
5284 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5285 if (!MCE)
5286 return MatchOperand_ParseFail;
5287
5288 Pattern = MCE->getValue();
5289 } else {
5290 // Parse the pattern
5291 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5292 if (!Pat)
5293 return MatchOperand_NoMatch;
5294
5295 Parser.Lex();
5296 Pattern = Pat->Encoding;
5297 assert(Pattern >= 0 && Pattern < 32);
5298 }
5299
5300 Operands.push_back(
5301 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5302 SS, getLoc(), getContext()));
5303
5304 return MatchOperand_Success;
5305}