blob: 61a8205efd5e8494414470d9ebab9c3dd5c216f1 [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>
1047 bool isComplexRotation() const {
1048 if (!isImm()) return false;
1049
1050 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1051 if (!CE) return false;
1052 uint64_t Value = CE->getValue();
1053
1054 return (Value % Angle == Remainder && Value <= 270);
1055 }
1056
Sander de Smalen149916d2018-04-20 07:24:20 +00001057 template <unsigned RegClassID> bool isGPR64() const {
1058 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1059 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1060 }
1061
1062 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001063 DiagnosticPredicate isGPR64WithShiftExtend() const {
1064 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1065 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001066
Sander de Smalenfe17a782018-04-26 12:54:42 +00001067 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1068 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1069 return DiagnosticPredicateTy::Match;
1070 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001071 }
1072
Tim Northover3b0846e2014-05-24 12:50:23 +00001073 /// Is this a vector list with the type implicit (presumably attached to the
1074 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001075 template <RegKind VectorKind, unsigned NumRegs>
1076 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001077 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001078 VectorList.NumElements == 0 &&
1079 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001080 }
1081
Sander de Smalen650234b2018-04-12 11:40:52 +00001082 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1083 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001084 bool isTypedVectorList() const {
1085 if (Kind != k_VectorList)
1086 return false;
1087 if (VectorList.Count != NumRegs)
1088 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001089 if (VectorList.RegisterKind != VectorKind)
1090 return false;
1091 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001092 return false;
1093 return VectorList.NumElements == NumElements;
1094 }
1095
Sander de Smalenc33d6682018-06-04 06:40:55 +00001096 template <int Min, int Max>
1097 DiagnosticPredicate isVectorIndex() const {
1098 if (Kind != k_VectorIndex)
1099 return DiagnosticPredicateTy::NoMatch;
1100 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1101 return DiagnosticPredicateTy::Match;
1102 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001103 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001104
Tim Northover3b0846e2014-05-24 12:50:23 +00001105 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001106
Tim Northover3b0846e2014-05-24 12:50:23 +00001107 bool isTokenEqual(StringRef Str) const {
1108 return Kind == k_Token && getToken() == Str;
1109 }
1110 bool isSysCR() const { return Kind == k_SysCR; }
1111 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001112 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001113 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1114 bool isShifter() const {
1115 if (!isShiftExtend())
1116 return false;
1117
1118 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1119 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1120 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1121 ST == AArch64_AM::MSL);
1122 }
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001123
1124 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1125 if (Kind != k_FPImm)
1126 return DiagnosticPredicateTy::NoMatch;
1127
1128 if (getFPImmIsExact()) {
1129 // Lookup the immediate from table of supported immediates.
1130 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1131 assert(Desc && "Unknown enum value");
1132
1133 // Calculate its FP value.
1134 APFloat RealVal(APFloat::IEEEdouble());
1135 if (RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero) !=
1136 APFloat::opOK)
1137 llvm_unreachable("FP immediate is not exact");
1138
1139 if (getFPImm().bitwiseIsEqual(RealVal))
1140 return DiagnosticPredicateTy::Match;
1141 }
1142
1143 return DiagnosticPredicateTy::NearMatch;
1144 }
1145
1146 template <unsigned ImmA, unsigned ImmB>
1147 DiagnosticPredicate isExactFPImm() const {
1148 DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1149 if ((Res = isExactFPImm<ImmA>()))
1150 return DiagnosticPredicateTy::Match;
1151 if ((Res = isExactFPImm<ImmB>()))
1152 return DiagnosticPredicateTy::Match;
1153 return Res;
1154 }
1155
Tim Northover3b0846e2014-05-24 12:50:23 +00001156 bool isExtend() const {
1157 if (!isShiftExtend())
1158 return false;
1159
1160 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1161 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1162 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1163 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1164 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1165 ET == AArch64_AM::LSL) &&
1166 getShiftExtendAmount() <= 4;
1167 }
1168
1169 bool isExtend64() const {
1170 if (!isExtend())
1171 return false;
1172 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1173 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1174 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1175 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001176
Tim Northover3b0846e2014-05-24 12:50:23 +00001177 bool isExtendLSL64() const {
1178 if (!isExtend())
1179 return false;
1180 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1181 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1182 ET == AArch64_AM::LSL) &&
1183 getShiftExtendAmount() <= 4;
1184 }
1185
1186 template<int Width> bool isMemXExtend() const {
1187 if (!isExtend())
1188 return false;
1189 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1190 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1191 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1192 getShiftExtendAmount() == 0);
1193 }
1194
1195 template<int Width> bool isMemWExtend() const {
1196 if (!isExtend())
1197 return false;
1198 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1199 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1200 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1201 getShiftExtendAmount() == 0);
1202 }
1203
1204 template <unsigned width>
1205 bool isArithmeticShifter() const {
1206 if (!isShifter())
1207 return false;
1208
1209 // An arithmetic shifter is LSL, LSR, or ASR.
1210 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1211 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1212 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1213 }
1214
1215 template <unsigned width>
1216 bool isLogicalShifter() const {
1217 if (!isShifter())
1218 return false;
1219
1220 // A logical shifter is LSL, LSR, ASR or ROR.
1221 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1222 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1223 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1224 getShiftExtendAmount() < width;
1225 }
1226
1227 bool isMovImm32Shifter() const {
1228 if (!isShifter())
1229 return false;
1230
1231 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1232 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1233 if (ST != AArch64_AM::LSL)
1234 return false;
1235 uint64_t Val = getShiftExtendAmount();
1236 return (Val == 0 || Val == 16);
1237 }
1238
1239 bool isMovImm64Shifter() const {
1240 if (!isShifter())
1241 return false;
1242
1243 // A MOVi shifter is LSL of 0 or 16.
1244 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1245 if (ST != AArch64_AM::LSL)
1246 return false;
1247 uint64_t Val = getShiftExtendAmount();
1248 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1249 }
1250
1251 bool isLogicalVecShifter() const {
1252 if (!isShifter())
1253 return false;
1254
1255 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1256 unsigned Shift = getShiftExtendAmount();
1257 return getShiftExtendType() == AArch64_AM::LSL &&
1258 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1259 }
1260
1261 bool isLogicalVecHalfWordShifter() const {
1262 if (!isLogicalVecShifter())
1263 return false;
1264
1265 // A logical vector shifter is a left shift by 0 or 8.
1266 unsigned Shift = getShiftExtendAmount();
1267 return getShiftExtendType() == AArch64_AM::LSL &&
1268 (Shift == 0 || Shift == 8);
1269 }
1270
1271 bool isMoveVecShifter() const {
1272 if (!isShiftExtend())
1273 return false;
1274
1275 // A logical vector shifter is a left shift by 8 or 16.
1276 unsigned Shift = getShiftExtendAmount();
1277 return getShiftExtendType() == AArch64_AM::MSL &&
1278 (Shift == 8 || Shift == 16);
1279 }
1280
1281 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1282 // to LDUR/STUR when the offset is not legal for the former but is for
1283 // the latter. As such, in addition to checking for being a legal unscaled
1284 // address, also check that it is not a legal scaled address. This avoids
1285 // ambiguity in the matcher.
1286 template<int Width>
1287 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001288 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001289 }
1290
1291 bool isAdrpLabel() const {
1292 // Validation was handled during parsing, so we just sanity check that
1293 // something didn't go haywire.
1294 if (!isImm())
1295 return false;
1296
1297 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1298 int64_t Val = CE->getValue();
1299 int64_t Min = - (4096 * (1LL << (21 - 1)));
1300 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1301 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1302 }
1303
1304 return true;
1305 }
1306
1307 bool isAdrLabel() const {
1308 // Validation was handled during parsing, so we just sanity check that
1309 // something didn't go haywire.
1310 if (!isImm())
1311 return false;
1312
1313 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1314 int64_t Val = CE->getValue();
1315 int64_t Min = - (1LL << (21 - 1));
1316 int64_t Max = ((1LL << (21 - 1)) - 1);
1317 return Val >= Min && Val <= Max;
1318 }
1319
1320 return true;
1321 }
1322
1323 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1324 // Add as immediates when possible. Null MCExpr = 0.
1325 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001326 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001327 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001328 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001329 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001330 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001331 }
1332
1333 void addRegOperands(MCInst &Inst, unsigned N) const {
1334 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001335 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001336 }
1337
1338 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1339 assert(N == 1 && "Invalid number of operands!");
1340 assert(
1341 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1342
1343 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1344 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1345 RI->getEncodingValue(getReg()));
1346
Jim Grosbache9119e42015-05-13 18:37:00 +00001347 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001348 }
1349
Sander de Smalen0325e302018-07-02 07:34:52 +00001350 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1351 assert(N == 1 && "Invalid number of operands!");
1352 assert(
1353 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(getReg()));
1354
1355 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1356 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID).getRegister(
1357 RI->getEncodingValue(getReg()));
1358
1359 Inst.addOperand(MCOperand::createReg(Reg));
1360 }
1361
Sander de Smalenfd54a782018-06-04 07:07:35 +00001362 template <int Width>
1363 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1364 unsigned Base;
1365 switch (Width) {
1366 case 8: Base = AArch64::B0; break;
1367 case 16: Base = AArch64::H0; break;
1368 case 32: Base = AArch64::S0; break;
1369 case 64: Base = AArch64::D0; break;
1370 case 128: Base = AArch64::Q0; break;
1371 default:
1372 llvm_unreachable("Unsupported width");
1373 }
1374 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1375 }
1376
Tim Northover3b0846e2014-05-24 12:50:23 +00001377 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1378 assert(N == 1 && "Invalid number of operands!");
1379 assert(
1380 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001381 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001382 }
1383
1384 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1385 assert(N == 1 && "Invalid number of operands!");
1386 assert(
1387 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001388 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001389 }
1390
1391 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1392 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001393 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001394 }
1395
Sander de Smalen525e3222018-04-12 13:19:32 +00001396 enum VecListIndexType {
1397 VecListIdx_DReg = 0,
1398 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001399 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001400 };
1401
1402 template <VecListIndexType RegTy, unsigned NumRegs>
1403 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001404 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001405 static const unsigned FirstRegs[][5] = {
1406 /* DReg */ { AArch64::Q0,
1407 AArch64::D0, AArch64::D0_D1,
1408 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1409 /* QReg */ { AArch64::Q0,
1410 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001411 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1412 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001413 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001414 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001415 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001416
Sander de Smalen7a210db2018-04-16 10:46:18 +00001417 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1418 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001419
Sander de Smalen525e3222018-04-12 13:19:32 +00001420 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1421 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1422 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001423 }
1424
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001425 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001426 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001427 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001428 }
1429
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001430 template <unsigned ImmIs0, unsigned ImmIs1>
1431 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1432 assert(N == 1 && "Invalid number of operands!");
1433 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1434 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1435 }
1436
Tim Northover3b0846e2014-05-24 12:50:23 +00001437 void addImmOperands(MCInst &Inst, unsigned N) const {
1438 assert(N == 1 && "Invalid number of operands!");
1439 // If this is a pageoff symrefexpr with an addend, adjust the addend
1440 // to be only the page-offset portion. Otherwise, just add the expr
1441 // as-is.
1442 addExpr(Inst, getImm());
1443 }
1444
Sander de Smalen62770792018-05-25 09:47:52 +00001445 template <int Shift>
1446 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001447 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001448 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1449 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1450 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1451 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001452 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001453 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001454 } else {
1455 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001456 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001457 }
1458 }
1459
Sander de Smalen62770792018-05-25 09:47:52 +00001460 template <int Shift>
1461 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001462 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001463 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1464 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1465 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1466 } else
1467 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001468 }
1469
Tim Northover3b0846e2014-05-24 12:50:23 +00001470 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1471 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001472 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001473 }
1474
1475 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 1 && "Invalid number of operands!");
1477 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1478 if (!MCE)
1479 addExpr(Inst, getImm());
1480 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001481 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001482 }
1483
1484 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1485 addImmOperands(Inst, N);
1486 }
1487
1488 template<int Scale>
1489 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1490 assert(N == 1 && "Invalid number of operands!");
1491 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1492
1493 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001494 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001495 return;
1496 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001497 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001498 }
1499
Sander de Smalen5c625982018-04-13 12:56:14 +00001500 template <int Scale>
1501 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1502 assert(N == 1 && "Invalid number of operands!");
1503 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1504 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1505 }
1506
Sander de Smalena1c259c2018-01-29 13:05:38 +00001507 template <typename T>
1508 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001509 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001510 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001511 typename std::make_unsigned<T>::type Val = MCE->getValue();
1512 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001513 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001514 }
1515
Sander de Smalena1c259c2018-01-29 13:05:38 +00001516 template <typename T>
1517 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001518 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001519 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001520 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1521 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001522 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001523 }
1524
Tim Northover3b0846e2014-05-24 12:50:23 +00001525 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1526 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001527 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001528 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001529 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001530 }
1531
1532 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1533 // Branch operands don't encode the low bits, so shift them off
1534 // here. If it's a label, however, just put it on directly as there's
1535 // not enough information now to do anything.
1536 assert(N == 1 && "Invalid number of operands!");
1537 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1538 if (!MCE) {
1539 addExpr(Inst, getImm());
1540 return;
1541 }
1542 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001543 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001544 }
1545
1546 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1547 // Branch operands don't encode the low bits, so shift them off
1548 // here. If it's a label, however, just put it on directly as there's
1549 // not enough information now to do anything.
1550 assert(N == 1 && "Invalid number of operands!");
1551 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1552 if (!MCE) {
1553 addExpr(Inst, getImm());
1554 return;
1555 }
1556 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001557 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001558 }
1559
1560 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1561 // Branch operands don't encode the low bits, so shift them off
1562 // here. If it's a label, however, just put it on directly as there's
1563 // not enough information now to do anything.
1564 assert(N == 1 && "Invalid number of operands!");
1565 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1566 if (!MCE) {
1567 addExpr(Inst, getImm());
1568 return;
1569 }
1570 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001571 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001572 }
1573
1574 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1575 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001576 Inst.addOperand(MCOperand::createImm(
1577 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
Tim Northover3b0846e2014-05-24 12:50:23 +00001578 }
1579
1580 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1581 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001582 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001583 }
1584
1585 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1586 assert(N == 1 && "Invalid number of operands!");
1587
Jim Grosbache9119e42015-05-13 18:37:00 +00001588 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001589 }
1590
1591 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1592 assert(N == 1 && "Invalid number of operands!");
1593
Jim Grosbache9119e42015-05-13 18:37:00 +00001594 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001595 }
1596
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001597 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1598 assert(N == 1 && "Invalid number of operands!");
1599
1600 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1601 }
1602
1603 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001604 assert(N == 1 && "Invalid number of operands!");
1605
Jim Grosbache9119e42015-05-13 18:37:00 +00001606 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001607 }
1608
1609 void addSysCROperands(MCInst &Inst, unsigned N) const {
1610 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001611 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001612 }
1613
1614 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1615 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001616 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001617 }
1618
Oliver Stannarda34e4702015-12-01 10:48:51 +00001619 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1620 assert(N == 1 && "Invalid number of operands!");
1621 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1622 }
1623
Tim Northover3b0846e2014-05-24 12:50:23 +00001624 void addShifterOperands(MCInst &Inst, unsigned N) const {
1625 assert(N == 1 && "Invalid number of operands!");
1626 unsigned Imm =
1627 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001628 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001629 }
1630
1631 void addExtendOperands(MCInst &Inst, unsigned N) const {
1632 assert(N == 1 && "Invalid number of operands!");
1633 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1634 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1635 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001636 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001637 }
1638
1639 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1640 assert(N == 1 && "Invalid number of operands!");
1641 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1642 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1643 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001644 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001645 }
1646
1647 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1648 assert(N == 2 && "Invalid number of operands!");
1649 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1650 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001651 Inst.addOperand(MCOperand::createImm(IsSigned));
1652 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001653 }
1654
1655 // For 8-bit load/store instructions with a register offset, both the
1656 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1657 // they're disambiguated by whether the shift was explicit or implicit rather
1658 // than its size.
1659 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1660 assert(N == 2 && "Invalid number of operands!");
1661 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1662 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001663 Inst.addOperand(MCOperand::createImm(IsSigned));
1664 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001665 }
1666
1667 template<int Shift>
1668 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1669 assert(N == 1 && "Invalid number of operands!");
1670
1671 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1672 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001673 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001674 }
1675
1676 template<int Shift>
1677 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1678 assert(N == 1 && "Invalid number of operands!");
1679
1680 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1681 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001682 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001683 }
1684
Sam Parker5f934642017-08-31 09:27:04 +00001685 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1686 assert(N == 1 && "Invalid number of operands!");
1687 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1688 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1689 }
1690
1691 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1692 assert(N == 1 && "Invalid number of operands!");
1693 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1694 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1695 }
1696
Tim Northover3b0846e2014-05-24 12:50:23 +00001697 void print(raw_ostream &OS) const override;
1698
David Blaikie960ea3f2014-06-08 16:18:35 +00001699 static std::unique_ptr<AArch64Operand>
1700 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1701 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001702 Op->Tok.Data = Str.data();
1703 Op->Tok.Length = Str.size();
1704 Op->Tok.IsSuffix = IsSuffix;
1705 Op->StartLoc = S;
1706 Op->EndLoc = S;
1707 return Op;
1708 }
1709
David Blaikie960ea3f2014-06-08 16:18:35 +00001710 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001711 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
Sander de Smalen0325e302018-07-02 07:34:52 +00001712 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
Sander de Smalen149916d2018-04-20 07:24:20 +00001713 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1714 unsigned ShiftAmount = 0,
1715 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001716 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001717 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001718 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001719 Op->Reg.ElementWidth = 0;
Sander de Smalen0325e302018-07-02 07:34:52 +00001720 Op->Reg.EqualityTy = EqTy;
Sander de Smalen149916d2018-04-20 07:24:20 +00001721 Op->Reg.ShiftExtend.Type = ExtTy;
1722 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1723 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001724 Op->StartLoc = S;
1725 Op->EndLoc = E;
1726 return Op;
1727 }
1728
David Blaikie960ea3f2014-06-08 16:18:35 +00001729 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001730 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001731 SMLoc S, SMLoc E, MCContext &Ctx,
1732 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1733 unsigned ShiftAmount = 0,
1734 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001735 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1736 Kind == RegKind::SVEPredicateVector) &&
1737 "Invalid vector kind");
Sander de Smalen0325e302018-07-02 07:34:52 +00001738 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
Sander de Smalen149916d2018-04-20 07:24:20 +00001739 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001740 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001741 return Op;
1742 }
1743
1744 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001745 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001746 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1747 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001748 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001749 Op->VectorList.RegNum = RegNum;
1750 Op->VectorList.Count = Count;
1751 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001752 Op->VectorList.ElementWidth = ElementWidth;
1753 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001754 Op->StartLoc = S;
1755 Op->EndLoc = E;
1756 return Op;
1757 }
1758
David Blaikie960ea3f2014-06-08 16:18:35 +00001759 static std::unique_ptr<AArch64Operand>
1760 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1761 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001762 Op->VectorIndex.Val = Idx;
1763 Op->StartLoc = S;
1764 Op->EndLoc = E;
1765 return Op;
1766 }
1767
David Blaikie960ea3f2014-06-08 16:18:35 +00001768 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1769 SMLoc E, MCContext &Ctx) {
1770 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001771 Op->Imm.Val = Val;
1772 Op->StartLoc = S;
1773 Op->EndLoc = E;
1774 return Op;
1775 }
1776
David Blaikie960ea3f2014-06-08 16:18:35 +00001777 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1778 unsigned ShiftAmount,
1779 SMLoc S, SMLoc E,
1780 MCContext &Ctx) {
1781 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001782 Op->ShiftedImm .Val = Val;
1783 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1784 Op->StartLoc = S;
1785 Op->EndLoc = E;
1786 return Op;
1787 }
1788
David Blaikie960ea3f2014-06-08 16:18:35 +00001789 static std::unique_ptr<AArch64Operand>
1790 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1791 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001792 Op->CondCode.Code = Code;
1793 Op->StartLoc = S;
1794 Op->EndLoc = E;
1795 return Op;
1796 }
1797
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001798 static std::unique_ptr<AArch64Operand>
1799 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001800 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001801 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
1802 Op->FPImm.IsExact = IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +00001803 Op->StartLoc = S;
1804 Op->EndLoc = S;
1805 return Op;
1806 }
1807
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001808 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1809 StringRef Str,
1810 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001811 MCContext &Ctx) {
1812 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001813 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001814 Op->Barrier.Data = Str.data();
1815 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001816 Op->StartLoc = S;
1817 Op->EndLoc = S;
1818 return Op;
1819 }
1820
Tim Northover7cd58932015-01-22 17:23:04 +00001821 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1822 uint32_t MRSReg,
1823 uint32_t MSRReg,
1824 uint32_t PStateField,
1825 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001826 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001827 Op->SysReg.Data = Str.data();
1828 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001829 Op->SysReg.MRSReg = MRSReg;
1830 Op->SysReg.MSRReg = MSRReg;
1831 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001832 Op->StartLoc = S;
1833 Op->EndLoc = S;
1834 return Op;
1835 }
1836
David Blaikie960ea3f2014-06-08 16:18:35 +00001837 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1838 SMLoc E, MCContext &Ctx) {
1839 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001840 Op->SysCRImm.Val = Val;
1841 Op->StartLoc = S;
1842 Op->EndLoc = E;
1843 return Op;
1844 }
1845
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001846 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1847 StringRef Str,
1848 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001849 MCContext &Ctx) {
1850 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001851 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001852 Op->Barrier.Data = Str.data();
1853 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001854 Op->StartLoc = S;
1855 Op->EndLoc = S;
1856 return Op;
1857 }
1858
Oliver Stannarda34e4702015-12-01 10:48:51 +00001859 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1860 StringRef Str,
1861 SMLoc S,
1862 MCContext &Ctx) {
1863 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1864 Op->PSBHint.Val = Val;
1865 Op->PSBHint.Data = Str.data();
1866 Op->PSBHint.Length = Str.size();
1867 Op->StartLoc = S;
1868 Op->EndLoc = S;
1869 return Op;
1870 }
1871
David Blaikie960ea3f2014-06-08 16:18:35 +00001872 static std::unique_ptr<AArch64Operand>
1873 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1874 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1875 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001876 Op->ShiftExtend.Type = ShOp;
1877 Op->ShiftExtend.Amount = Val;
1878 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1879 Op->StartLoc = S;
1880 Op->EndLoc = E;
1881 return Op;
1882 }
1883};
1884
1885} // end anonymous namespace.
1886
1887void AArch64Operand::print(raw_ostream &OS) const {
1888 switch (Kind) {
1889 case k_FPImm:
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001890 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
1891 if (!getFPImmIsExact())
1892 OS << " (inexact)";
1893 OS << ">";
Tim Northover3b0846e2014-05-24 12:50:23 +00001894 break;
1895 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001896 StringRef Name = getBarrierName();
1897 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001898 OS << "<barrier " << Name << ">";
1899 else
1900 OS << "<barrier invalid #" << getBarrier() << ">";
1901 break;
1902 }
1903 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001904 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001905 break;
1906 case k_ShiftedImm: {
1907 unsigned Shift = getShiftedImmShift();
1908 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001909 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001910 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1911 break;
1912 }
1913 case k_CondCode:
1914 OS << "<condcode " << getCondCode() << ">";
1915 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001916 case k_VectorList: {
1917 OS << "<vectorlist ";
1918 unsigned Reg = getVectorListStart();
1919 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1920 OS << Reg + i << " ";
1921 OS << ">";
1922 break;
1923 }
1924 case k_VectorIndex:
1925 OS << "<vectorindex " << getVectorIndex() << ">";
1926 break;
1927 case k_SysReg:
1928 OS << "<sysreg: " << getSysReg() << '>';
1929 break;
1930 case k_Token:
1931 OS << "'" << getToken() << "'";
1932 break;
1933 case k_SysCR:
1934 OS << "c" << getSysCR();
1935 break;
1936 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001937 StringRef Name = getPrefetchName();
1938 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001939 OS << "<prfop " << Name << ">";
1940 else
1941 OS << "<prfop invalid #" << getPrefetch() << ">";
1942 break;
1943 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001944 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001945 OS << getPSBHintName();
1946 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00001947 case k_Register:
1948 OS << "<register " << getReg() << ">";
1949 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
1950 break;
1951 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001952 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001953 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1954 << getShiftExtendAmount();
1955 if (!hasShiftExtendAmount())
1956 OS << "<imp>";
1957 OS << '>';
1958 break;
1959 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001960}
1961
1962/// @name Auto-generated Match Functions
1963/// {
1964
1965static unsigned MatchRegisterName(StringRef Name);
1966
1967/// }
1968
Florian Hahnc4422242017-11-07 13:07:50 +00001969static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001970 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001971 .Case("v0", AArch64::Q0)
1972 .Case("v1", AArch64::Q1)
1973 .Case("v2", AArch64::Q2)
1974 .Case("v3", AArch64::Q3)
1975 .Case("v4", AArch64::Q4)
1976 .Case("v5", AArch64::Q5)
1977 .Case("v6", AArch64::Q6)
1978 .Case("v7", AArch64::Q7)
1979 .Case("v8", AArch64::Q8)
1980 .Case("v9", AArch64::Q9)
1981 .Case("v10", AArch64::Q10)
1982 .Case("v11", AArch64::Q11)
1983 .Case("v12", AArch64::Q12)
1984 .Case("v13", AArch64::Q13)
1985 .Case("v14", AArch64::Q14)
1986 .Case("v15", AArch64::Q15)
1987 .Case("v16", AArch64::Q16)
1988 .Case("v17", AArch64::Q17)
1989 .Case("v18", AArch64::Q18)
1990 .Case("v19", AArch64::Q19)
1991 .Case("v20", AArch64::Q20)
1992 .Case("v21", AArch64::Q21)
1993 .Case("v22", AArch64::Q22)
1994 .Case("v23", AArch64::Q23)
1995 .Case("v24", AArch64::Q24)
1996 .Case("v25", AArch64::Q25)
1997 .Case("v26", AArch64::Q26)
1998 .Case("v27", AArch64::Q27)
1999 .Case("v28", AArch64::Q28)
2000 .Case("v29", AArch64::Q29)
2001 .Case("v30", AArch64::Q30)
2002 .Case("v31", AArch64::Q31)
2003 .Default(0);
2004}
2005
Sander de Smalen73937b72018-04-11 07:36:10 +00002006/// Returns an optional pair of (#elements, element-width) if Suffix
2007/// is a valid vector kind. Where the number of elements in a vector
2008/// or the vector width is implicit or explicitly unknown (but still a
2009/// valid suffix kind), 0 is used.
2010static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2011 RegKind VectorKind) {
2012 std::pair<int, int> Res = {-1, -1};
2013
2014 switch (VectorKind) {
2015 case RegKind::NeonVector:
2016 Res =
2017 StringSwitch<std::pair<int, int>>(Suffix.lower())
2018 .Case("", {0, 0})
2019 .Case(".1d", {1, 64})
2020 .Case(".1q", {1, 128})
2021 // '.2h' needed for fp16 scalar pairwise reductions
2022 .Case(".2h", {2, 16})
2023 .Case(".2s", {2, 32})
2024 .Case(".2d", {2, 64})
2025 // '.4b' is another special case for the ARMv8.2a dot product
2026 // operand
2027 .Case(".4b", {4, 8})
2028 .Case(".4h", {4, 16})
2029 .Case(".4s", {4, 32})
2030 .Case(".8b", {8, 8})
2031 .Case(".8h", {8, 16})
2032 .Case(".16b", {16, 8})
2033 // Accept the width neutral ones, too, for verbose syntax. If those
2034 // aren't used in the right places, the token operand won't match so
2035 // all will work out.
2036 .Case(".b", {0, 8})
2037 .Case(".h", {0, 16})
2038 .Case(".s", {0, 32})
2039 .Case(".d", {0, 64})
2040 .Default({-1, -1});
2041 break;
2042 case RegKind::SVEPredicateVector:
2043 case RegKind::SVEDataVector:
2044 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2045 .Case("", {0, 0})
2046 .Case(".b", {0, 8})
2047 .Case(".h", {0, 16})
2048 .Case(".s", {0, 32})
2049 .Case(".d", {0, 64})
2050 .Case(".q", {0, 128})
2051 .Default({-1, -1});
2052 break;
2053 default:
2054 llvm_unreachable("Unsupported RegKind");
2055 }
2056
2057 if (Res == std::make_pair(-1, -1))
2058 return Optional<std::pair<int, int>>();
2059
2060 return Optional<std::pair<int, int>>(Res);
2061}
2062
2063static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2064 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002065}
2066
Florian Hahn91f11e52017-11-07 16:45:48 +00002067static unsigned matchSVEDataVectorRegName(StringRef Name) {
2068 return StringSwitch<unsigned>(Name.lower())
2069 .Case("z0", AArch64::Z0)
2070 .Case("z1", AArch64::Z1)
2071 .Case("z2", AArch64::Z2)
2072 .Case("z3", AArch64::Z3)
2073 .Case("z4", AArch64::Z4)
2074 .Case("z5", AArch64::Z5)
2075 .Case("z6", AArch64::Z6)
2076 .Case("z7", AArch64::Z7)
2077 .Case("z8", AArch64::Z8)
2078 .Case("z9", AArch64::Z9)
2079 .Case("z10", AArch64::Z10)
2080 .Case("z11", AArch64::Z11)
2081 .Case("z12", AArch64::Z12)
2082 .Case("z13", AArch64::Z13)
2083 .Case("z14", AArch64::Z14)
2084 .Case("z15", AArch64::Z15)
2085 .Case("z16", AArch64::Z16)
2086 .Case("z17", AArch64::Z17)
2087 .Case("z18", AArch64::Z18)
2088 .Case("z19", AArch64::Z19)
2089 .Case("z20", AArch64::Z20)
2090 .Case("z21", AArch64::Z21)
2091 .Case("z22", AArch64::Z22)
2092 .Case("z23", AArch64::Z23)
2093 .Case("z24", AArch64::Z24)
2094 .Case("z25", AArch64::Z25)
2095 .Case("z26", AArch64::Z26)
2096 .Case("z27", AArch64::Z27)
2097 .Case("z28", AArch64::Z28)
2098 .Case("z29", AArch64::Z29)
2099 .Case("z30", AArch64::Z30)
2100 .Case("z31", AArch64::Z31)
2101 .Default(0);
2102}
2103
Sander de Smalencd6be962017-12-20 11:02:42 +00002104static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2105 return StringSwitch<unsigned>(Name.lower())
2106 .Case("p0", AArch64::P0)
2107 .Case("p1", AArch64::P1)
2108 .Case("p2", AArch64::P2)
2109 .Case("p3", AArch64::P3)
2110 .Case("p4", AArch64::P4)
2111 .Case("p5", AArch64::P5)
2112 .Case("p6", AArch64::P6)
2113 .Case("p7", AArch64::P7)
2114 .Case("p8", AArch64::P8)
2115 .Case("p9", AArch64::P9)
2116 .Case("p10", AArch64::P10)
2117 .Case("p11", AArch64::P11)
2118 .Case("p12", AArch64::P12)
2119 .Case("p13", AArch64::P13)
2120 .Case("p14", AArch64::P14)
2121 .Case("p15", AArch64::P15)
2122 .Default(0);
2123}
2124
Tim Northover3b0846e2014-05-24 12:50:23 +00002125bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2126 SMLoc &EndLoc) {
2127 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002128 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002129 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002130 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002131}
2132
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002133// Matches a register name or register alias previously defined by '.req'
2134unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002135 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002136 unsigned RegNum = 0;
2137 if ((RegNum = matchSVEDataVectorRegName(Name)))
2138 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2139
Sander de Smalencd6be962017-12-20 11:02:42 +00002140 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2141 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2142
Sander de Smalenc067c302017-12-20 09:45:45 +00002143 if ((RegNum = MatchNeonVectorRegName(Name)))
2144 return Kind == RegKind::NeonVector ? RegNum : 0;
2145
2146 // The parsed register must be of RegKind Scalar
2147 if ((RegNum = MatchRegisterName(Name)))
2148 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002149
Florian Hahnc4422242017-11-07 13:07:50 +00002150 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002151 // Handle a few common aliases of registers.
2152 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2153 .Case("fp", AArch64::FP)
2154 .Case("lr", AArch64::LR)
2155 .Case("x31", AArch64::XZR)
2156 .Case("w31", AArch64::WZR)
2157 .Default(0))
2158 return Kind == RegKind::Scalar ? RegNum : 0;
2159
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002160 // Check for aliases registered via .req. Canonicalize to lower case.
2161 // That's more consistent since register names are case insensitive, and
2162 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2163 auto Entry = RegisterReqs.find(Name.lower());
2164 if (Entry == RegisterReqs.end())
2165 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002166
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002167 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002168 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002169 RegNum = Entry->getValue().second;
2170 }
2171 return RegNum;
2172}
2173
Sander de Smalen50d87022018-04-19 07:35:08 +00002174/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002175/// Identifier when called, and if it is a register name the token is eaten and
2176/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002177OperandMatchResultTy
2178AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002179 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002180 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002181 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002182 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002183
2184 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002185 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2186 if (Reg == 0)
2187 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002188
Sander de Smalen50d87022018-04-19 07:35:08 +00002189 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002190 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002191 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002192}
2193
Tim Northover3b0846e2014-05-24 12:50:23 +00002194/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002195OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002196AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002197 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002198 SMLoc S = getLoc();
2199
2200 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2201 Error(S, "Expected cN operand where 0 <= N <= 15");
2202 return MatchOperand_ParseFail;
2203 }
2204
2205 StringRef Tok = Parser.getTok().getIdentifier();
2206 if (Tok[0] != 'c' && Tok[0] != 'C') {
2207 Error(S, "Expected cN operand where 0 <= N <= 15");
2208 return MatchOperand_ParseFail;
2209 }
2210
2211 uint32_t CRNum;
2212 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2213 if (BadNum || CRNum > 15) {
2214 Error(S, "Expected cN operand where 0 <= N <= 15");
2215 return MatchOperand_ParseFail;
2216 }
2217
2218 Parser.Lex(); // Eat identifier token.
2219 Operands.push_back(
2220 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2221 return MatchOperand_Success;
2222}
2223
2224/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002225template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002226OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002227AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002228 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002229 SMLoc S = getLoc();
2230 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002231
2232 auto LookupByName = [](StringRef N) {
2233 if (IsSVEPrefetch) {
2234 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2235 return Optional<unsigned>(Res->Encoding);
2236 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2237 return Optional<unsigned>(Res->Encoding);
2238 return Optional<unsigned>();
2239 };
2240
2241 auto LookupByEncoding = [](unsigned E) {
2242 if (IsSVEPrefetch) {
2243 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2244 return Optional<StringRef>(Res->Name);
2245 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2246 return Optional<StringRef>(Res->Name);
2247 return Optional<StringRef>();
2248 };
2249 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2250
Tim Northover3b0846e2014-05-24 12:50:23 +00002251 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002252 // Eat optional hash.
2253 if (parseOptionalToken(AsmToken::Hash) ||
2254 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002255 const MCExpr *ImmVal;
2256 if (getParser().parseExpression(ImmVal))
2257 return MatchOperand_ParseFail;
2258
2259 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2260 if (!MCE) {
2261 TokError("immediate value expected for prefetch operand");
2262 return MatchOperand_ParseFail;
2263 }
2264 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002265 if (prfop > MaxVal) {
2266 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2267 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002268 return MatchOperand_ParseFail;
2269 }
2270
Sander de Smalen93380372018-05-14 11:54:41 +00002271 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002272 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002273 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002274 return MatchOperand_Success;
2275 }
2276
2277 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002278 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002279 return MatchOperand_ParseFail;
2280 }
2281
Sander de Smalen93380372018-05-14 11:54:41 +00002282 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002283 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002284 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002285 return MatchOperand_ParseFail;
2286 }
2287
2288 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002289 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002290 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002291 return MatchOperand_Success;
2292}
2293
Oliver Stannarda34e4702015-12-01 10:48:51 +00002294/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002295OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002296AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2297 MCAsmParser &Parser = getParser();
2298 SMLoc S = getLoc();
2299 const AsmToken &Tok = Parser.getTok();
2300 if (Tok.isNot(AsmToken::Identifier)) {
2301 TokError("invalid operand for instruction");
2302 return MatchOperand_ParseFail;
2303 }
2304
Tim Northovere6ae6762016-07-05 21:23:04 +00002305 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2306 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002307 TokError("invalid operand for instruction");
2308 return MatchOperand_ParseFail;
2309 }
2310
2311 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002312 Operands.push_back(AArch64Operand::CreatePSBHint(
2313 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002314 return MatchOperand_Success;
2315}
2316
Tim Northover3b0846e2014-05-24 12:50:23 +00002317/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2318/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002319OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002320AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002321 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002322 SMLoc S = getLoc();
2323 const MCExpr *Expr;
2324
2325 if (Parser.getTok().is(AsmToken::Hash)) {
2326 Parser.Lex(); // Eat hash token.
2327 }
2328
2329 if (parseSymbolicImmVal(Expr))
2330 return MatchOperand_ParseFail;
2331
2332 AArch64MCExpr::VariantKind ELFRefKind;
2333 MCSymbolRefExpr::VariantKind DarwinRefKind;
2334 int64_t Addend;
2335 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2336 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2337 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2338 // No modifier was specified at all; this is the syntax for an ELF basic
2339 // ADRP relocation (unfortunately).
2340 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002341 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002342 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2343 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2344 Addend != 0) {
2345 Error(S, "gotpage label reference not allowed an addend");
2346 return MatchOperand_ParseFail;
2347 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2348 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2349 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2350 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2351 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2352 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2353 // The operand must be an @page or @gotpage qualified symbolref.
2354 Error(S, "page or gotpage label reference expected");
2355 return MatchOperand_ParseFail;
2356 }
2357 }
2358
2359 // We have either a label reference possibly with addend or an immediate. The
2360 // addend is a raw value here. The linker will adjust it to only reference the
2361 // page.
2362 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2363 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2364
2365 return MatchOperand_Success;
2366}
2367
2368/// tryParseAdrLabel - Parse and validate a source label for the ADR
2369/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002370OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002371AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2372 SMLoc S = getLoc();
2373 const MCExpr *Expr;
2374
Nirav Davee833c6c2016-11-08 18:31:04 +00002375 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002376 if (getParser().parseExpression(Expr))
2377 return MatchOperand_ParseFail;
2378
2379 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2380 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2381
2382 return MatchOperand_Success;
2383}
2384
2385/// tryParseFPImm - A floating point immediate expression operand.
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002386template<bool AddFPZeroAsLiteral>
Alex Bradbury58eba092016-11-01 16:32:05 +00002387OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002388AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002389 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002390 SMLoc S = getLoc();
2391
Nirav Davee833c6c2016-11-08 18:31:04 +00002392 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002393
2394 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002395 bool isNegative = parseOptionalToken(AsmToken::Minus);
2396
Tim Northover3b0846e2014-05-24 12:50:23 +00002397 const AsmToken &Tok = Parser.getTok();
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002398 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2399 if (!Hash)
2400 return MatchOperand_NoMatch;
2401 TokError("invalid floating point immediate");
2402 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002403 }
2404
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002405 // Parse hexadecimal representation.
2406 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2407 if (Tok.getIntVal() > 255 || isNegative) {
2408 TokError("encoded floating point value out of range");
2409 return MatchOperand_ParseFail;
2410 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002411
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002412 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2413 Operands.push_back(
2414 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2415 } else {
2416 // Parse FP representation.
2417 APFloat RealVal(APFloat::IEEEdouble());
2418 auto Status =
2419 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2420 if (isNegative)
2421 RealVal.changeSign();
2422
2423 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2424 Operands.push_back(
2425 AArch64Operand::CreateToken("#0", false, S, getContext()));
2426 Operands.push_back(
2427 AArch64Operand::CreateToken(".0", false, S, getContext()));
2428 } else
2429 Operands.push_back(AArch64Operand::CreateFPImm(
2430 RealVal, Status == APFloat::opOK, S, getContext()));
2431 }
2432
2433 Parser.Lex(); // Eat the token.
2434
2435 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002436}
2437
Sander de Smalen62770792018-05-25 09:47:52 +00002438/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2439/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002440OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002441AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002442 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002443 SMLoc S = getLoc();
2444
2445 if (Parser.getTok().is(AsmToken::Hash))
2446 Parser.Lex(); // Eat '#'
2447 else if (Parser.getTok().isNot(AsmToken::Integer))
2448 // Operand should start from # or should be integer, emit error otherwise.
2449 return MatchOperand_NoMatch;
2450
2451 const MCExpr *Imm;
2452 if (parseSymbolicImmVal(Imm))
2453 return MatchOperand_ParseFail;
2454 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002455 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002456 Operands.push_back(
2457 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002458 return MatchOperand_Success;
2459 }
2460
2461 // Eat ','
2462 Parser.Lex();
2463
2464 // The optional operand must be "lsl #N" where N is non-negative.
2465 if (!Parser.getTok().is(AsmToken::Identifier) ||
2466 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2467 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2468 return MatchOperand_ParseFail;
2469 }
2470
2471 // Eat 'lsl'
2472 Parser.Lex();
2473
Nirav Davee833c6c2016-11-08 18:31:04 +00002474 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002475
2476 if (Parser.getTok().isNot(AsmToken::Integer)) {
2477 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2478 return MatchOperand_ParseFail;
2479 }
2480
2481 int64_t ShiftAmount = Parser.getTok().getIntVal();
2482
2483 if (ShiftAmount < 0) {
2484 Error(Parser.getTok().getLoc(), "positive shift amount required");
2485 return MatchOperand_ParseFail;
2486 }
2487 Parser.Lex(); // Eat the number
2488
Sander de Smalen62770792018-05-25 09:47:52 +00002489 // Just in case the optional lsl #0 is used for immediates other than zero.
2490 if (ShiftAmount == 0 && Imm != 0) {
2491 SMLoc E = Parser.getTok().getLoc();
2492 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2493 return MatchOperand_Success;
2494 }
2495
Tim Northover3b0846e2014-05-24 12:50:23 +00002496 SMLoc E = Parser.getTok().getLoc();
2497 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2498 S, E, getContext()));
2499 return MatchOperand_Success;
2500}
2501
2502/// parseCondCodeString - Parse a Condition Code string.
2503AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2504 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2505 .Case("eq", AArch64CC::EQ)
2506 .Case("ne", AArch64CC::NE)
2507 .Case("cs", AArch64CC::HS)
2508 .Case("hs", AArch64CC::HS)
2509 .Case("cc", AArch64CC::LO)
2510 .Case("lo", AArch64CC::LO)
2511 .Case("mi", AArch64CC::MI)
2512 .Case("pl", AArch64CC::PL)
2513 .Case("vs", AArch64CC::VS)
2514 .Case("vc", AArch64CC::VC)
2515 .Case("hi", AArch64CC::HI)
2516 .Case("ls", AArch64CC::LS)
2517 .Case("ge", AArch64CC::GE)
2518 .Case("lt", AArch64CC::LT)
2519 .Case("gt", AArch64CC::GT)
2520 .Case("le", AArch64CC::LE)
2521 .Case("al", AArch64CC::AL)
2522 .Case("nv", AArch64CC::NV)
2523 .Default(AArch64CC::Invalid);
2524 return CC;
2525}
2526
2527/// parseCondCode - Parse a Condition Code operand.
2528bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2529 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002530 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002531 SMLoc S = getLoc();
2532 const AsmToken &Tok = Parser.getTok();
2533 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2534
2535 StringRef Cond = Tok.getString();
2536 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2537 if (CC == AArch64CC::Invalid)
2538 return TokError("invalid condition code");
2539 Parser.Lex(); // Eat identifier token.
2540
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002541 if (invertCondCode) {
2542 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2543 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002544 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002545 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002546
2547 Operands.push_back(
2548 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2549 return false;
2550}
2551
2552/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2553/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002554OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002555AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002556 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002557 const AsmToken &Tok = Parser.getTok();
2558 std::string LowerID = Tok.getString().lower();
2559 AArch64_AM::ShiftExtendType ShOp =
2560 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2561 .Case("lsl", AArch64_AM::LSL)
2562 .Case("lsr", AArch64_AM::LSR)
2563 .Case("asr", AArch64_AM::ASR)
2564 .Case("ror", AArch64_AM::ROR)
2565 .Case("msl", AArch64_AM::MSL)
2566 .Case("uxtb", AArch64_AM::UXTB)
2567 .Case("uxth", AArch64_AM::UXTH)
2568 .Case("uxtw", AArch64_AM::UXTW)
2569 .Case("uxtx", AArch64_AM::UXTX)
2570 .Case("sxtb", AArch64_AM::SXTB)
2571 .Case("sxth", AArch64_AM::SXTH)
2572 .Case("sxtw", AArch64_AM::SXTW)
2573 .Case("sxtx", AArch64_AM::SXTX)
2574 .Default(AArch64_AM::InvalidShiftExtend);
2575
2576 if (ShOp == AArch64_AM::InvalidShiftExtend)
2577 return MatchOperand_NoMatch;
2578
2579 SMLoc S = Tok.getLoc();
2580 Parser.Lex();
2581
Nirav Davee833c6c2016-11-08 18:31:04 +00002582 bool Hash = parseOptionalToken(AsmToken::Hash);
2583
Tim Northover3b0846e2014-05-24 12:50:23 +00002584 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2585 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2586 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2587 ShOp == AArch64_AM::MSL) {
2588 // We expect a number here.
2589 TokError("expected #imm after shift specifier");
2590 return MatchOperand_ParseFail;
2591 }
2592
Chad Rosier2ff37b82016-12-27 16:58:09 +00002593 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002594 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2595 Operands.push_back(
2596 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2597 return MatchOperand_Success;
2598 }
2599
Chad Rosier2ff37b82016-12-27 16:58:09 +00002600 // Make sure we do actually have a number, identifier or a parenthesized
2601 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002602 SMLoc E = Parser.getTok().getLoc();
2603 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002604 !Parser.getTok().is(AsmToken::LParen) &&
2605 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002606 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002607 return MatchOperand_ParseFail;
2608 }
2609
2610 const MCExpr *ImmVal;
2611 if (getParser().parseExpression(ImmVal))
2612 return MatchOperand_ParseFail;
2613
2614 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2615 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002616 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002617 return MatchOperand_ParseFail;
2618 }
2619
Jim Grosbach57fd2622014-09-23 22:16:02 +00002620 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002621 Operands.push_back(AArch64Operand::CreateShiftExtend(
2622 ShOp, MCE->getValue(), true, S, E, getContext()));
2623 return MatchOperand_Success;
2624}
2625
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002626static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2627 if (FBS[AArch64::HasV8_1aOps])
2628 Str += "ARMv8.1a";
2629 else if (FBS[AArch64::HasV8_2aOps])
2630 Str += "ARMv8.2a";
2631 else
2632 Str += "(unknown)";
2633}
2634
2635void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2636 SMLoc S) {
2637 const uint16_t Op2 = Encoding & 7;
2638 const uint16_t Cm = (Encoding & 0x78) >> 3;
2639 const uint16_t Cn = (Encoding & 0x780) >> 7;
2640 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2641
2642 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2643
2644 Operands.push_back(
2645 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2646 Operands.push_back(
2647 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2648 Operands.push_back(
2649 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2650 Expr = MCConstantExpr::create(Op2, getContext());
2651 Operands.push_back(
2652 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2653}
2654
Tim Northover3b0846e2014-05-24 12:50:23 +00002655/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2656/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2657bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2658 OperandVector &Operands) {
2659 if (Name.find('.') != StringRef::npos)
2660 return TokError("invalid operand");
2661
2662 Mnemonic = Name;
2663 Operands.push_back(
2664 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2665
Rafael Espindola961d4692014-11-11 05:18:41 +00002666 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002667 const AsmToken &Tok = Parser.getTok();
2668 StringRef Op = Tok.getString();
2669 SMLoc S = Tok.getLoc();
2670
Tim Northover3b0846e2014-05-24 12:50:23 +00002671 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002672 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2673 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002674 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002675 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2676 std::string Str("IC " + std::string(IC->Name) + " requires ");
2677 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2678 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002679 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002680 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002681 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002682 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2683 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002684 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002685 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2686 std::string Str("DC " + std::string(DC->Name) + " requires ");
2687 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2688 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002689 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002690 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002691 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002692 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2693 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002694 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002695 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2696 std::string Str("AT " + std::string(AT->Name) + " requires ");
2697 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2698 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002699 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002700 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002701 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002702 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2703 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002704 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002705 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2706 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2707 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2708 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002709 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002710 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002711 }
2712
Tim Northover3b0846e2014-05-24 12:50:23 +00002713 Parser.Lex(); // Eat operand.
2714
2715 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2716 bool HasRegister = false;
2717
2718 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002719 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002720 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2721 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002722 HasRegister = true;
2723 }
2724
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002725 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002726 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002727 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002728 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002729
Nirav Davee833c6c2016-11-08 18:31:04 +00002730 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2731 return true;
2732
Tim Northover3b0846e2014-05-24 12:50:23 +00002733 return false;
2734}
2735
Alex Bradbury58eba092016-11-01 16:32:05 +00002736OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002737AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002738 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002739 const AsmToken &Tok = Parser.getTok();
2740
2741 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002742 if (parseOptionalToken(AsmToken::Hash) ||
2743 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002744 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002745 const MCExpr *ImmVal;
2746 SMLoc ExprLoc = getLoc();
2747 if (getParser().parseExpression(ImmVal))
2748 return MatchOperand_ParseFail;
2749 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2750 if (!MCE) {
2751 Error(ExprLoc, "immediate value expected for barrier operand");
2752 return MatchOperand_ParseFail;
2753 }
2754 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2755 Error(ExprLoc, "barrier operand out of range");
2756 return MatchOperand_ParseFail;
2757 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002758 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2759 Operands.push_back(AArch64Operand::CreateBarrier(
2760 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002761 return MatchOperand_Success;
2762 }
2763
2764 if (Tok.isNot(AsmToken::Identifier)) {
2765 TokError("invalid operand for instruction");
2766 return MatchOperand_ParseFail;
2767 }
2768
Tim Northover3b0846e2014-05-24 12:50:23 +00002769 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002770 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2771 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002772 TokError("'sy' or #imm operand expected");
2773 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002774 } else if (!DB) {
2775 TokError("invalid barrier option name");
2776 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002777 }
2778
Tim Northovere6ae6762016-07-05 21:23:04 +00002779 Operands.push_back(AArch64Operand::CreateBarrier(
2780 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002781 Parser.Lex(); // Consume the option
2782
2783 return MatchOperand_Success;
2784}
2785
Alex Bradbury58eba092016-11-01 16:32:05 +00002786OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002787AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002788 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002789 const AsmToken &Tok = Parser.getTok();
2790
2791 if (Tok.isNot(AsmToken::Identifier))
2792 return MatchOperand_NoMatch;
2793
Tim Northovere6ae6762016-07-05 21:23:04 +00002794 int MRSReg, MSRReg;
2795 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2796 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2797 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2798 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2799 } else
2800 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002801
Tim Northovere6ae6762016-07-05 21:23:04 +00002802 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2803 unsigned PStateImm = -1;
2804 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2805 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002806
Tim Northovere6ae6762016-07-05 21:23:04 +00002807 Operands.push_back(
2808 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2809 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002810 Parser.Lex(); // Eat identifier
2811
2812 return MatchOperand_Success;
2813}
2814
Florian Hahnc4422242017-11-07 13:07:50 +00002815/// tryParseNeonVectorRegister - Parse a vector register operand.
2816bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002817 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002818 if (Parser.getTok().isNot(AsmToken::Identifier))
2819 return true;
2820
2821 SMLoc S = getLoc();
2822 // Check for a vector register specifier first.
2823 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002824 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002825 OperandMatchResultTy Res =
2826 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2827 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002828 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002829
2830 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2831 if (!KindRes)
2832 return true;
2833
2834 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002835 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002836 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2837 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002838
Tim Northover3b0846e2014-05-24 12:50:23 +00002839 // If there was an explicit qualifier, that goes on as a literal text
2840 // operand.
2841 if (!Kind.empty())
2842 Operands.push_back(
2843 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2844
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002845 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2846}
2847
2848OperandMatchResultTy
2849AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002850 SMLoc SIdx = getLoc();
2851 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002852 const MCExpr *ImmVal;
2853 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002854 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002855 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2856 if (!MCE) {
2857 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002858 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002859 }
2860
2861 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002862
Nirav Davee833c6c2016-11-08 18:31:04 +00002863 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002864 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002865
2866 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2867 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002868 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002869 }
2870
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002871 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002872}
2873
Sander de Smalen73937b72018-04-11 07:36:10 +00002874// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002875// optional kind specifier. If it is a register specifier, eat the token
2876// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002877OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002878AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002879 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002880 MCAsmParser &Parser = getParser();
2881 const AsmToken &Tok = Parser.getTok();
2882
Florian Hahn91f11e52017-11-07 16:45:48 +00002883 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002884 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002885
2886 StringRef Name = Tok.getString();
2887 // If there is a kind specifier, it's separated from the register name by
2888 // a '.'.
2889 size_t Start = 0, Next = Name.find('.');
2890 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002891 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002892
2893 if (RegNum) {
2894 if (Next != StringRef::npos) {
2895 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002896 if (!isValidVectorKind(Kind, MatchKind)) {
2897 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002898 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002899 }
2900 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002901 Parser.Lex(); // Eat the register token.
2902
2903 Reg = RegNum;
2904 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002905 }
2906
Sander de Smalen8e607342017-11-15 15:44:43 +00002907 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002908}
2909
Sander de Smalencd6be962017-12-20 11:02:42 +00002910/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2911OperandMatchResultTy
2912AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2913 // Check for a SVE predicate register specifier first.
2914 const SMLoc S = getLoc();
2915 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002916 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002917 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002918 if (Res != MatchOperand_Success)
2919 return Res;
2920
Sander de Smalen73937b72018-04-11 07:36:10 +00002921 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2922 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002923 return MatchOperand_NoMatch;
2924
Sander de Smalen73937b72018-04-11 07:36:10 +00002925 unsigned ElementWidth = KindRes->second;
2926 Operands.push_back(AArch64Operand::CreateVectorReg(
2927 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2928 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002929
Sander de Smalen7868e742018-01-09 11:17:06 +00002930 // Not all predicates are followed by a '/m' or '/z'.
2931 MCAsmParser &Parser = getParser();
2932 if (Parser.getTok().isNot(AsmToken::Slash))
2933 return MatchOperand_Success;
2934
2935 // But when they do they shouldn't have an element type suffix.
2936 if (!Kind.empty()) {
2937 Error(S, "not expecting size suffix");
2938 return MatchOperand_ParseFail;
2939 }
2940
2941 // Add a literal slash as operand
2942 Operands.push_back(
2943 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2944
2945 Parser.Lex(); // Eat the slash.
2946
2947 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002948 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002949 if (Pred != "z" && Pred != "m") {
2950 Error(getLoc(), "expecting 'm' or 'z' predication");
2951 return MatchOperand_ParseFail;
2952 }
2953
2954 // Add zero/merge token.
2955 const char *ZM = Pred == "z" ? "z" : "m";
2956 Operands.push_back(
2957 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2958
2959 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002960 return MatchOperand_Success;
2961}
2962
Sander de Smalen50d87022018-04-19 07:35:08 +00002963/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002964bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002965 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002966 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002967 return false;
2968
Sander de Smalen149916d2018-04-20 07:24:20 +00002969 // Otherwise try for a scalar register.
2970 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
2971 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002972
Sander de Smalen149916d2018-04-20 07:24:20 +00002973 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002974}
2975
2976bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002977 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002978 bool HasELFModifier = false;
2979 AArch64MCExpr::VariantKind RefKind;
2980
Nirav Davee833c6c2016-11-08 18:31:04 +00002981 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002982 HasELFModifier = true;
2983
Nirav Davee833c6c2016-11-08 18:31:04 +00002984 if (Parser.getTok().isNot(AsmToken::Identifier))
2985 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002986
2987 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2988 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2989 .Case("lo12", AArch64MCExpr::VK_LO12)
2990 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2991 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2992 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2993 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2994 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2995 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2996 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2997 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2998 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2999 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
3000 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
3001 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
3002 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3003 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3004 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3005 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3006 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3007 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3008 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3009 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3010 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3011 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3012 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3013 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3014 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3015 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3016 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3017 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3018 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3019 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3020 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3021 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3022 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3023 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003024 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3025 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00003026 .Default(AArch64MCExpr::VK_INVALID);
3027
Nirav Davee833c6c2016-11-08 18:31:04 +00003028 if (RefKind == AArch64MCExpr::VK_INVALID)
3029 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003030
3031 Parser.Lex(); // Eat identifier
3032
Nirav Davee833c6c2016-11-08 18:31:04 +00003033 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003034 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003035 }
3036
3037 if (getParser().parseExpression(ImmVal))
3038 return true;
3039
3040 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003041 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003042
3043 return false;
3044}
3045
Sander de Smalen650234b2018-04-12 11:40:52 +00003046template <RegKind VectorKind>
3047OperandMatchResultTy
3048AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3049 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003050 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003051 if (!Parser.getTok().is(AsmToken::LCurly))
3052 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003053
3054 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003055 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003056 bool NoMatchIsError) {
3057 auto RegTok = Parser.getTok();
3058 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3059 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003060 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003061 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003062 llvm_unreachable("Expected a valid vector kind");
3063 }
3064
Sander de Smalen650234b2018-04-12 11:40:52 +00003065 if (RegTok.isNot(AsmToken::Identifier) ||
3066 ParseRes == MatchOperand_ParseFail ||
3067 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3068 Error(Loc, "vector register expected");
3069 return MatchOperand_ParseFail;
3070 }
3071
3072 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003073 };
3074
Tim Northover3b0846e2014-05-24 12:50:23 +00003075 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003076 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003077 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003078
Tim Northover3b0846e2014-05-24 12:50:23 +00003079 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003080 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003081 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3082
3083 // Put back the original left bracket if there was no match, so that
3084 // different types of list-operands can be matched (e.g. SVE, Neon).
3085 if (ParseRes == MatchOperand_NoMatch)
3086 Parser.getLexer().UnLex(LCurly);
3087
3088 if (ParseRes != MatchOperand_Success)
3089 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003090
Tim Northover3b0846e2014-05-24 12:50:23 +00003091 int64_t PrevReg = FirstReg;
3092 unsigned Count = 1;
3093
Nirav Davee833c6c2016-11-08 18:31:04 +00003094 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003095 SMLoc Loc = getLoc();
3096 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003097
Sander de Smalen50d87022018-04-19 07:35:08 +00003098 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003099 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3100 if (ParseRes != MatchOperand_Success)
3101 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003102
Tim Northover3b0846e2014-05-24 12:50:23 +00003103 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003104 if (Kind != NextKind) {
3105 Error(Loc, "mismatched register size suffix");
3106 return MatchOperand_ParseFail;
3107 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003108
3109 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3110
3111 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003112 Error(Loc, "invalid number of vectors");
3113 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003114 }
3115
3116 Count += Space;
3117 }
3118 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003119 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003120 SMLoc Loc = getLoc();
3121 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003122 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003123 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3124 if (ParseRes != MatchOperand_Success)
3125 return ParseRes;
3126
Tim Northover3b0846e2014-05-24 12:50:23 +00003127 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003128 if (Kind != NextKind) {
3129 Error(Loc, "mismatched register size suffix");
3130 return MatchOperand_ParseFail;
3131 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003132
3133 // Registers must be incremental (with wraparound at 31)
3134 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003135 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3136 Error(Loc, "registers must be sequential");
3137 return MatchOperand_ParseFail;
3138 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003139
3140 PrevReg = Reg;
3141 ++Count;
3142 }
3143 }
3144
Nirav Davee833c6c2016-11-08 18:31:04 +00003145 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003146 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003147
Sander de Smalen650234b2018-04-12 11:40:52 +00003148 if (Count > 4) {
3149 Error(S, "invalid number of vectors");
3150 return MatchOperand_ParseFail;
3151 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003152
3153 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003154 unsigned ElementWidth = 0;
3155 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003156 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003157 std::tie(NumElements, ElementWidth) = *VK;
3158 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003159
3160 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003161 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3162 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003163
Sander de Smalen650234b2018-04-12 11:40:52 +00003164 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003165}
3166
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003167/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3168bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003169 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3170 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003171 return true;
3172
3173 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3174}
3175
Alex Bradbury58eba092016-11-01 16:32:05 +00003176OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003177AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003178 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003179
Sander de Smalen50d87022018-04-19 07:35:08 +00003180 unsigned RegNum;
3181 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3182 if (Res != MatchOperand_Success)
3183 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003184
Nirav Davee833c6c2016-11-08 18:31:04 +00003185 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003186 Operands.push_back(AArch64Operand::CreateReg(
3187 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003188 return MatchOperand_Success;
3189 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003190
Nirav Davee833c6c2016-11-08 18:31:04 +00003191 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003192
Sander de Smalen50d87022018-04-19 07:35:08 +00003193 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003194 Error(getLoc(), "index must be absent or #0");
3195 return MatchOperand_ParseFail;
3196 }
3197
3198 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003199 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003200 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3201 Error(getLoc(), "index must be absent or #0");
3202 return MatchOperand_ParseFail;
3203 }
3204
Sander de Smalen50d87022018-04-19 07:35:08 +00003205 Operands.push_back(AArch64Operand::CreateReg(
3206 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003207 return MatchOperand_Success;
3208}
3209
Sander de Smalen0325e302018-07-02 07:34:52 +00003210template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
Sander de Smalen149916d2018-04-20 07:24:20 +00003211OperandMatchResultTy
3212AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3213 SMLoc StartLoc = getLoc();
3214
3215 unsigned RegNum;
3216 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3217 if (Res != MatchOperand_Success)
3218 return Res;
3219
3220 // No shift/extend is the default.
3221 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3222 Operands.push_back(AArch64Operand::CreateReg(
Sander de Smalen0325e302018-07-02 07:34:52 +00003223 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
Sander de Smalen149916d2018-04-20 07:24:20 +00003224 return MatchOperand_Success;
3225 }
3226
3227 // Eat the comma
3228 getParser().Lex();
3229
3230 // Match the shift
3231 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3232 Res = tryParseOptionalShiftExtend(ExtOpnd);
3233 if (Res != MatchOperand_Success)
3234 return Res;
3235
3236 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
Sander de Smalen0325e302018-07-02 07:34:52 +00003237 Operands.push_back(AArch64Operand::CreateReg(
3238 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3239 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3240 Ext->hasShiftExtendAmount()));
Sander de Smalen149916d2018-04-20 07:24:20 +00003241
3242 return MatchOperand_Success;
3243}
3244
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003245bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
Sander de Smalen5c625982018-04-13 12:56:14 +00003246 MCAsmParser &Parser = getParser();
3247
3248 // Some SVE instructions have a decoration after the immediate, i.e.
3249 // "mul vl". We parse them here and add tokens, which must be present in the
3250 // asm string in the tablegen instruction.
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003251 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3252 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
Sander de Smalen5c625982018-04-13 12:56:14 +00003253 if (!Parser.getTok().getString().equals_lower("mul") ||
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003254 !(NextIsVL || NextIsHash))
Sander de Smalen5c625982018-04-13 12:56:14 +00003255 return true;
3256
Sander de Smalen5c625982018-04-13 12:56:14 +00003257 Operands.push_back(
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003258 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
Sander de Smalen5c625982018-04-13 12:56:14 +00003259 Parser.Lex(); // Eat the "mul"
3260
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003261 if (NextIsVL) {
3262 Operands.push_back(
3263 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3264 Parser.Lex(); // Eat the "vl"
3265 return false;
3266 }
Sander de Smalen5c625982018-04-13 12:56:14 +00003267
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003268 if (NextIsHash) {
3269 Parser.Lex(); // Eat the #
3270 SMLoc S = getLoc();
3271
3272 // Parse immediate operand.
3273 const MCExpr *ImmVal;
3274 if (!Parser.parseExpression(ImmVal))
3275 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3276 Operands.push_back(AArch64Operand::CreateImm(
3277 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3278 getContext()));
3279 return MatchOperand_Success;
3280 }
3281 }
3282
3283 return Error(getLoc(), "expected 'vl' or '#<imm>'");
Sander de Smalen5c625982018-04-13 12:56:14 +00003284}
3285
Tim Northover3b0846e2014-05-24 12:50:23 +00003286/// parseOperand - Parse a arm instruction operand. For now this parses the
3287/// operand regardless of the mnemonic.
3288bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3289 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003290 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003291
3292 OperandMatchResultTy ResTy =
3293 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3294
Tim Northover3b0846e2014-05-24 12:50:23 +00003295 // Check if the current operand has a custom associated parser, if so, try to
3296 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003297 if (ResTy == MatchOperand_Success)
3298 return false;
3299 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3300 // there was a match, but an error occurred, in which case, just return that
3301 // the operand parsing failed.
3302 if (ResTy == MatchOperand_ParseFail)
3303 return true;
3304
3305 // Nothing custom, so do general case parsing.
3306 SMLoc S, E;
3307 switch (getLexer().getKind()) {
3308 default: {
3309 SMLoc S = getLoc();
3310 const MCExpr *Expr;
3311 if (parseSymbolicImmVal(Expr))
3312 return Error(S, "invalid operand");
3313
3314 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3315 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3316 return false;
3317 }
3318 case AsmToken::LBrac: {
3319 SMLoc Loc = Parser.getTok().getLoc();
3320 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3321 getContext()));
3322 Parser.Lex(); // Eat '['
3323
3324 // There's no comma after a '[', so we can parse the next operand
3325 // immediately.
3326 return parseOperand(Operands, false, false);
3327 }
3328 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003329 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003330 case AsmToken::Identifier: {
3331 // If we're expecting a Condition Code operand, then just parse that.
3332 if (isCondCode)
3333 return parseCondCode(Operands, invertCondCode);
3334
3335 // If it's a register name, parse it.
3336 if (!parseRegister(Operands))
3337 return false;
3338
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003339 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3340 // by SVE instructions.
3341 if (!parseOptionalMulOperand(Operands))
Sander de Smalen5c625982018-04-13 12:56:14 +00003342 return false;
3343
Tim Northover3b0846e2014-05-24 12:50:23 +00003344 // This could be an optional "shift" or "extend" operand.
3345 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3346 // We can only continue if no tokens were eaten.
3347 if (GotShift != MatchOperand_NoMatch)
3348 return GotShift;
3349
3350 // This was not a register so parse other operands that start with an
3351 // identifier (like labels) as expressions and create them as immediates.
3352 const MCExpr *IdVal;
3353 S = getLoc();
3354 if (getParser().parseExpression(IdVal))
3355 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003356 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3357 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3358 return false;
3359 }
3360 case AsmToken::Integer:
3361 case AsmToken::Real:
3362 case AsmToken::Hash: {
3363 // #42 -> immediate.
3364 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003365
3366 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003367
3368 // Parse a negative sign
3369 bool isNegative = false;
3370 if (Parser.getTok().is(AsmToken::Minus)) {
3371 isNegative = true;
3372 // We need to consume this token only when we have a Real, otherwise
3373 // we let parseSymbolicImmVal take care of it
3374 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3375 Parser.Lex();
3376 }
3377
3378 // The only Real that should come through here is a literal #0.0 for
3379 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3380 // so convert the value.
3381 const AsmToken &Tok = Parser.getTok();
3382 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003383 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003384 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3385 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3386 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
Sander de Smalen8fcc3f52018-07-03 09:07:23 +00003387 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
Tim Northover3b0846e2014-05-24 12:50:23 +00003388 return TokError("unexpected floating point literal");
3389 else if (IntVal != 0 || isNegative)
3390 return TokError("expected floating-point constant #0.0");
3391 Parser.Lex(); // Eat the token.
3392
3393 Operands.push_back(
3394 AArch64Operand::CreateToken("#0", false, S, getContext()));
3395 Operands.push_back(
3396 AArch64Operand::CreateToken(".0", false, S, getContext()));
3397 return false;
3398 }
3399
3400 const MCExpr *ImmVal;
3401 if (parseSymbolicImmVal(ImmVal))
3402 return true;
3403
3404 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3405 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3406 return false;
3407 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003408 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003409 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003410 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003411 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003412 Parser.Lex(); // Eat '='
3413 const MCExpr *SubExprVal;
3414 if (getParser().parseExpression(SubExprVal))
3415 return true;
3416
David Peixottoae5ba762014-07-18 16:05:14 +00003417 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003418 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003419 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003420
3421 bool IsXReg =
3422 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3423 Operands[1]->getReg());
3424
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003425 MCContext& Ctx = getContext();
3426 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3427 // 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 +00003428 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003429 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3430 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3431 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3432 ShiftAmt += 16;
3433 Imm >>= 16;
3434 }
3435 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3436 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3437 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003438 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003439 if (ShiftAmt)
3440 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3441 ShiftAmt, true, S, E, Ctx));
3442 return false;
3443 }
David Peixottoae5ba762014-07-18 16:05:14 +00003444 APInt Simm = APInt(64, Imm << ShiftAmt);
3445 // check if the immediate is an unsigned or signed 32-bit int for W regs
3446 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3447 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003448 }
3449 // 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 +00003450 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003451 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003452 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3453 return false;
3454 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003455 }
3456}
3457
Sander de Smalen0325e302018-07-02 07:34:52 +00003458bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3459 const MCParsedAsmOperand &Op2) const {
3460 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3461 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3462 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3463 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3464 return MCTargetAsmParser::regsEqual(Op1, Op2);
3465
3466 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3467 "Testing equality of non-scalar registers not supported");
3468
3469 // Check if a registers match their sub/super register classes.
3470 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3471 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3472 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3473 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3474 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3475 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3476 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3477 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3478
3479 return false;
3480}
3481
Tim Northover3b0846e2014-05-24 12:50:23 +00003482/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3483/// operands.
3484bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3485 StringRef Name, SMLoc NameLoc,
3486 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003487 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003488 Name = StringSwitch<StringRef>(Name.lower())
3489 .Case("beq", "b.eq")
3490 .Case("bne", "b.ne")
3491 .Case("bhs", "b.hs")
3492 .Case("bcs", "b.cs")
3493 .Case("blo", "b.lo")
3494 .Case("bcc", "b.cc")
3495 .Case("bmi", "b.mi")
3496 .Case("bpl", "b.pl")
3497 .Case("bvs", "b.vs")
3498 .Case("bvc", "b.vc")
3499 .Case("bhi", "b.hi")
3500 .Case("bls", "b.ls")
3501 .Case("bge", "b.ge")
3502 .Case("blt", "b.lt")
3503 .Case("bgt", "b.gt")
3504 .Case("ble", "b.le")
3505 .Case("bal", "b.al")
3506 .Case("bnv", "b.nv")
3507 .Default(Name);
3508
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003509 // First check for the AArch64-specific .req directive.
3510 if (Parser.getTok().is(AsmToken::Identifier) &&
3511 Parser.getTok().getIdentifier() == ".req") {
3512 parseDirectiveReq(Name, NameLoc);
3513 // We always return 'error' for this, as we're done with this
3514 // statement and don't need to match the 'instruction."
3515 return true;
3516 }
3517
Tim Northover3b0846e2014-05-24 12:50:23 +00003518 // Create the leading tokens for the mnemonic, split by '.' characters.
3519 size_t Start = 0, Next = Name.find('.');
3520 StringRef Head = Name.slice(Start, Next);
3521
3522 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003523 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3524 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003525
3526 Operands.push_back(
3527 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3528 Mnemonic = Head;
3529
3530 // Handle condition codes for a branch mnemonic
3531 if (Head == "b" && Next != StringRef::npos) {
3532 Start = Next;
3533 Next = Name.find('.', Start + 1);
3534 Head = Name.slice(Start + 1, Next);
3535
3536 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3537 (Head.data() - Name.data()));
3538 AArch64CC::CondCode CC = parseCondCodeString(Head);
3539 if (CC == AArch64CC::Invalid)
3540 return Error(SuffixLoc, "invalid condition code");
3541 Operands.push_back(
3542 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3543 Operands.push_back(
3544 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3545 }
3546
3547 // Add the remaining tokens in the mnemonic.
3548 while (Next != StringRef::npos) {
3549 Start = Next;
3550 Next = Name.find('.', Start + 1);
3551 Head = Name.slice(Start, Next);
3552 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3553 (Head.data() - Name.data()) + 1);
3554 Operands.push_back(
3555 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3556 }
3557
3558 // Conditional compare instructions have a Condition Code operand, which needs
3559 // to be parsed and an immediate operand created.
3560 bool condCodeFourthOperand =
3561 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3562 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3563 Head == "csinc" || Head == "csinv" || Head == "csneg");
3564
3565 // These instructions are aliases to some of the conditional select
3566 // instructions. However, the condition code is inverted in the aliased
3567 // instruction.
3568 //
3569 // FIXME: Is this the correct way to handle these? Or should the parser
3570 // generate the aliased instructions directly?
3571 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3572 bool condCodeThirdOperand =
3573 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3574
3575 // Read the remaining operands.
3576 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3577 // Read the first operand.
3578 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003579 return true;
3580 }
3581
3582 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003583 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003584 // Parse and remember the operand.
3585 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3586 (N == 3 && condCodeThirdOperand) ||
3587 (N == 2 && condCodeSecondOperand),
3588 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003589 return true;
3590 }
3591
3592 // After successfully parsing some operands there are two special cases to
3593 // consider (i.e. notional operands not separated by commas). Both are due
3594 // to memory specifiers:
3595 // + An RBrac will end an address for load/store/prefetch
3596 // + An '!' will indicate a pre-indexed operation.
3597 //
3598 // It's someone else's responsibility to make sure these tokens are sane
3599 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003600
Nirav Davee833c6c2016-11-08 18:31:04 +00003601 SMLoc RLoc = Parser.getTok().getLoc();
3602 if (parseOptionalToken(AsmToken::RBrac))
3603 Operands.push_back(
3604 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3605 SMLoc ELoc = Parser.getTok().getLoc();
3606 if (parseOptionalToken(AsmToken::Exclaim))
3607 Operands.push_back(
3608 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003609
3610 ++N;
3611 }
3612 }
3613
Nirav Davee833c6c2016-11-08 18:31:04 +00003614 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3615 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003616
Tim Northover3b0846e2014-05-24 12:50:23 +00003617 return false;
3618}
3619
3620// FIXME: This entire function is a giant hack to provide us with decent
3621// operand range validation/diagnostics until TableGen/MC can be extended
3622// to support autogeneration of this kind of validation.
3623bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3624 SmallVectorImpl<SMLoc> &Loc) {
3625 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3626 // Check for indexed addressing modes w/ the base register being the
3627 // same as a destination/source register or pair load where
3628 // the Rt == Rt2. All of those are undefined behaviour.
3629 switch (Inst.getOpcode()) {
3630 case AArch64::LDPSWpre:
3631 case AArch64::LDPWpost:
3632 case AArch64::LDPWpre:
3633 case AArch64::LDPXpost:
3634 case AArch64::LDPXpre: {
3635 unsigned Rt = Inst.getOperand(1).getReg();
3636 unsigned Rt2 = Inst.getOperand(2).getReg();
3637 unsigned Rn = Inst.getOperand(3).getReg();
3638 if (RI->isSubRegisterEq(Rn, Rt))
3639 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3640 "is also a destination");
3641 if (RI->isSubRegisterEq(Rn, Rt2))
3642 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3643 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003644 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003645 }
3646 case AArch64::LDPDi:
3647 case AArch64::LDPQi:
3648 case AArch64::LDPSi:
3649 case AArch64::LDPSWi:
3650 case AArch64::LDPWi:
3651 case AArch64::LDPXi: {
3652 unsigned Rt = Inst.getOperand(0).getReg();
3653 unsigned Rt2 = Inst.getOperand(1).getReg();
3654 if (Rt == Rt2)
3655 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3656 break;
3657 }
3658 case AArch64::LDPDpost:
3659 case AArch64::LDPDpre:
3660 case AArch64::LDPQpost:
3661 case AArch64::LDPQpre:
3662 case AArch64::LDPSpost:
3663 case AArch64::LDPSpre:
3664 case AArch64::LDPSWpost: {
3665 unsigned Rt = Inst.getOperand(1).getReg();
3666 unsigned Rt2 = Inst.getOperand(2).getReg();
3667 if (Rt == Rt2)
3668 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3669 break;
3670 }
3671 case AArch64::STPDpost:
3672 case AArch64::STPDpre:
3673 case AArch64::STPQpost:
3674 case AArch64::STPQpre:
3675 case AArch64::STPSpost:
3676 case AArch64::STPSpre:
3677 case AArch64::STPWpost:
3678 case AArch64::STPWpre:
3679 case AArch64::STPXpost:
3680 case AArch64::STPXpre: {
3681 unsigned Rt = Inst.getOperand(1).getReg();
3682 unsigned Rt2 = Inst.getOperand(2).getReg();
3683 unsigned Rn = Inst.getOperand(3).getReg();
3684 if (RI->isSubRegisterEq(Rn, Rt))
3685 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3686 "is also a source");
3687 if (RI->isSubRegisterEq(Rn, Rt2))
3688 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3689 "is also a source");
3690 break;
3691 }
3692 case AArch64::LDRBBpre:
3693 case AArch64::LDRBpre:
3694 case AArch64::LDRHHpre:
3695 case AArch64::LDRHpre:
3696 case AArch64::LDRSBWpre:
3697 case AArch64::LDRSBXpre:
3698 case AArch64::LDRSHWpre:
3699 case AArch64::LDRSHXpre:
3700 case AArch64::LDRSWpre:
3701 case AArch64::LDRWpre:
3702 case AArch64::LDRXpre:
3703 case AArch64::LDRBBpost:
3704 case AArch64::LDRBpost:
3705 case AArch64::LDRHHpost:
3706 case AArch64::LDRHpost:
3707 case AArch64::LDRSBWpost:
3708 case AArch64::LDRSBXpost:
3709 case AArch64::LDRSHWpost:
3710 case AArch64::LDRSHXpost:
3711 case AArch64::LDRSWpost:
3712 case AArch64::LDRWpost:
3713 case AArch64::LDRXpost: {
3714 unsigned Rt = Inst.getOperand(1).getReg();
3715 unsigned Rn = Inst.getOperand(2).getReg();
3716 if (RI->isSubRegisterEq(Rn, Rt))
3717 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3718 "is also a source");
3719 break;
3720 }
3721 case AArch64::STRBBpost:
3722 case AArch64::STRBpost:
3723 case AArch64::STRHHpost:
3724 case AArch64::STRHpost:
3725 case AArch64::STRWpost:
3726 case AArch64::STRXpost:
3727 case AArch64::STRBBpre:
3728 case AArch64::STRBpre:
3729 case AArch64::STRHHpre:
3730 case AArch64::STRHpre:
3731 case AArch64::STRWpre:
3732 case AArch64::STRXpre: {
3733 unsigned Rt = Inst.getOperand(1).getReg();
3734 unsigned Rn = Inst.getOperand(2).getReg();
3735 if (RI->isSubRegisterEq(Rn, Rt))
3736 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3737 "is also a source");
3738 break;
3739 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003740 case AArch64::STXRB:
3741 case AArch64::STXRH:
3742 case AArch64::STXRW:
3743 case AArch64::STXRX:
3744 case AArch64::STLXRB:
3745 case AArch64::STLXRH:
3746 case AArch64::STLXRW:
3747 case AArch64::STLXRX: {
3748 unsigned Rs = Inst.getOperand(0).getReg();
3749 unsigned Rt = Inst.getOperand(1).getReg();
3750 unsigned Rn = Inst.getOperand(2).getReg();
3751 if (RI->isSubRegisterEq(Rt, Rs) ||
3752 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3753 return Error(Loc[0],
3754 "unpredictable STXR instruction, status is also a source");
3755 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003756 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003757 case AArch64::STXPW:
3758 case AArch64::STXPX:
3759 case AArch64::STLXPW:
3760 case AArch64::STLXPX: {
3761 unsigned Rs = Inst.getOperand(0).getReg();
3762 unsigned Rt1 = Inst.getOperand(1).getReg();
3763 unsigned Rt2 = Inst.getOperand(2).getReg();
3764 unsigned Rn = Inst.getOperand(3).getReg();
3765 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3766 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3767 return Error(Loc[0],
3768 "unpredictable STXP instruction, status is also a source");
3769 break;
3770 }
3771 }
3772
Tim Northover3b0846e2014-05-24 12:50:23 +00003773
3774 // Now check immediate ranges. Separate from the above as there is overlap
3775 // in the instructions being checked and this keeps the nested conditionals
3776 // to a minimum.
3777 switch (Inst.getOpcode()) {
3778 case AArch64::ADDSWri:
3779 case AArch64::ADDSXri:
3780 case AArch64::ADDWri:
3781 case AArch64::ADDXri:
3782 case AArch64::SUBSWri:
3783 case AArch64::SUBSXri:
3784 case AArch64::SUBWri:
3785 case AArch64::SUBXri: {
3786 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3787 // some slight duplication here.
3788 if (Inst.getOperand(2).isExpr()) {
3789 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3790 AArch64MCExpr::VariantKind ELFRefKind;
3791 MCSymbolRefExpr::VariantKind DarwinRefKind;
3792 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003793 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3794
3795 // Only allow these with ADDXri.
3796 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3797 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3798 Inst.getOpcode() == AArch64::ADDXri)
3799 return false;
3800
3801 // Only allow these with ADDXri/ADDWri
3802 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3803 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3804 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3805 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3806 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3807 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3808 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003809 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3810 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3811 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003812 (Inst.getOpcode() == AArch64::ADDXri ||
3813 Inst.getOpcode() == AArch64::ADDWri))
3814 return false;
3815
3816 // Don't allow symbol refs in the immediate field otherwise
3817 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3818 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3819 // 'cmp w0, 'borked')
3820 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003821 }
Diana Picusc93518d2016-10-11 09:17:47 +00003822 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003823 }
3824 return false;
3825 }
3826 default:
3827 return false;
3828 }
3829}
3830
Craig Topper05515562017-10-26 06:46:41 +00003831static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3832 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003833
3834bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
Sander de Smalen0325e302018-07-02 07:34:52 +00003835 uint64_t ErrorInfo,
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003836 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003837 switch (ErrCode) {
Sander de Smalen0325e302018-07-02 07:34:52 +00003838 case Match_InvalidTiedOperand: {
3839 RegConstraintEqualityTy EqTy =
3840 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
3841 .getRegEqualityTy();
3842 switch (EqTy) {
3843 case RegConstraintEqualityTy::EqualsSubReg:
3844 return Error(Loc, "operand must be 64-bit form of destination register");
3845 case RegConstraintEqualityTy::EqualsSuperReg:
3846 return Error(Loc, "operand must be 32-bit form of destination register");
3847 case RegConstraintEqualityTy::EqualsReg:
3848 return Error(Loc, "operand must match destination register");
3849 }
3850 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003851 case Match_MissingFeature:
3852 return Error(Loc,
3853 "instruction requires a CPU feature not currently enabled");
3854 case Match_InvalidOperand:
3855 return Error(Loc, "invalid operand for instruction");
3856 case Match_InvalidSuffix:
3857 return Error(Loc, "invalid type suffix for instruction");
3858 case Match_InvalidCondCode:
3859 return Error(Loc, "expected AArch64 condition code");
3860 case Match_AddSubRegExtendSmall:
3861 return Error(Loc,
3862 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3863 case Match_AddSubRegExtendLarge:
3864 return Error(Loc,
3865 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3866 case Match_AddSubSecondSource:
3867 return Error(Loc,
3868 "expected compatible register, symbol or integer in range [0, 4095]");
3869 case Match_LogicalSecondSource:
3870 return Error(Loc, "expected compatible register or logical immediate");
3871 case Match_InvalidMovImm32Shift:
3872 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3873 case Match_InvalidMovImm64Shift:
3874 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3875 case Match_AddSubRegShift32:
3876 return Error(Loc,
3877 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3878 case Match_AddSubRegShift64:
3879 return Error(Loc,
3880 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3881 case Match_InvalidFPImm:
3882 return Error(Loc,
3883 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003884 case Match_InvalidMemoryIndexedSImm6:
3885 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003886 case Match_InvalidMemoryIndexedSImm5:
3887 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003888 case Match_InvalidMemoryIndexed1SImm4:
3889 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003890 case Match_InvalidMemoryIndexed2SImm4:
3891 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003892 case Match_InvalidMemoryIndexed3SImm4:
3893 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003894 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00003895 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00003896 case Match_InvalidMemoryIndexed16SImm4:
3897 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00003898 case Match_InvalidMemoryIndexed1SImm6:
3899 return Error(Loc, "index must be an integer in range [-32, 31].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003900 case Match_InvalidMemoryIndexedSImm9:
3901 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00003902 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00003903 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003904 case Match_InvalidMemoryIndexed4SImm7:
3905 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3906 case Match_InvalidMemoryIndexed8SImm7:
3907 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3908 case Match_InvalidMemoryIndexed16SImm7:
3909 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00003910 case Match_InvalidMemoryIndexed8UImm5:
3911 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
3912 case Match_InvalidMemoryIndexed4UImm5:
3913 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
3914 case Match_InvalidMemoryIndexed2UImm5:
3915 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00003916 case Match_InvalidMemoryIndexed8UImm6:
3917 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
3918 case Match_InvalidMemoryIndexed4UImm6:
3919 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
3920 case Match_InvalidMemoryIndexed2UImm6:
3921 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
3922 case Match_InvalidMemoryIndexed1UImm6:
3923 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003924 case Match_InvalidMemoryWExtend8:
3925 return Error(Loc,
3926 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3927 case Match_InvalidMemoryWExtend16:
3928 return Error(Loc,
3929 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3930 case Match_InvalidMemoryWExtend32:
3931 return Error(Loc,
3932 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3933 case Match_InvalidMemoryWExtend64:
3934 return Error(Loc,
3935 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3936 case Match_InvalidMemoryWExtend128:
3937 return Error(Loc,
3938 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3939 case Match_InvalidMemoryXExtend8:
3940 return Error(Loc,
3941 "expected 'lsl' or 'sxtx' with optional shift of #0");
3942 case Match_InvalidMemoryXExtend16:
3943 return Error(Loc,
3944 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3945 case Match_InvalidMemoryXExtend32:
3946 return Error(Loc,
3947 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3948 case Match_InvalidMemoryXExtend64:
3949 return Error(Loc,
3950 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3951 case Match_InvalidMemoryXExtend128:
3952 return Error(Loc,
3953 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3954 case Match_InvalidMemoryIndexed1:
3955 return Error(Loc, "index must be an integer in range [0, 4095].");
3956 case Match_InvalidMemoryIndexed2:
3957 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3958 case Match_InvalidMemoryIndexed4:
3959 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3960 case Match_InvalidMemoryIndexed8:
3961 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3962 case Match_InvalidMemoryIndexed16:
3963 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003964 case Match_InvalidImm0_1:
3965 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003966 case Match_InvalidImm0_7:
3967 return Error(Loc, "immediate must be an integer in range [0, 7].");
3968 case Match_InvalidImm0_15:
3969 return Error(Loc, "immediate must be an integer in range [0, 15].");
3970 case Match_InvalidImm0_31:
3971 return Error(Loc, "immediate must be an integer in range [0, 31].");
3972 case Match_InvalidImm0_63:
3973 return Error(Loc, "immediate must be an integer in range [0, 63].");
3974 case Match_InvalidImm0_127:
3975 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003976 case Match_InvalidImm0_255:
3977 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003978 case Match_InvalidImm0_65535:
3979 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3980 case Match_InvalidImm1_8:
3981 return Error(Loc, "immediate must be an integer in range [1, 8].");
3982 case Match_InvalidImm1_16:
3983 return Error(Loc, "immediate must be an integer in range [1, 16].");
3984 case Match_InvalidImm1_32:
3985 return Error(Loc, "immediate must be an integer in range [1, 32].");
3986 case Match_InvalidImm1_64:
3987 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00003988 case Match_InvalidSVEAddSubImm8:
3989 return Error(Loc, "immediate must be an integer in range [0, 255]"
3990 " with a shift amount of 0");
3991 case Match_InvalidSVEAddSubImm16:
3992 case Match_InvalidSVEAddSubImm32:
3993 case Match_InvalidSVEAddSubImm64:
3994 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
3995 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00003996 case Match_InvalidSVECpyImm8:
3997 return Error(Loc, "immediate must be an integer in range [-128, 255]"
3998 " with a shift amount of 0");
3999 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00004000 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4001 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004002 case Match_InvalidSVECpyImm32:
4003 case Match_InvalidSVECpyImm64:
4004 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4005 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004006 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004007 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004008 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00004009 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004010 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00004011 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004012 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004013 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004014 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004015 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004016 case Match_InvalidSVEIndexRange0_63:
4017 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4018 case Match_InvalidSVEIndexRange0_31:
4019 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4020 case Match_InvalidSVEIndexRange0_15:
4021 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4022 case Match_InvalidSVEIndexRange0_7:
4023 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4024 case Match_InvalidSVEIndexRange0_3:
4025 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004026 case Match_InvalidLabel:
4027 return Error(Loc, "expected label or encodable integer pc offset");
4028 case Match_MRS:
4029 return Error(Loc, "expected readable system register");
4030 case Match_MSR:
4031 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00004032 case Match_InvalidComplexRotationEven:
4033 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4034 case Match_InvalidComplexRotationOdd:
4035 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004036 case Match_MnemonicFail: {
4037 std::string Suggestion = AArch64MnemonicSpellCheck(
4038 ((AArch64Operand &)*Operands[0]).getToken(),
4039 ComputeAvailableFeatures(STI->getFeatureBits()));
4040 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4041 }
Sander de Smalen367694b2018-04-20 08:54:49 +00004042 case Match_InvalidGPR64shifted8:
4043 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4044 case Match_InvalidGPR64shifted16:
4045 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4046 case Match_InvalidGPR64shifted32:
4047 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4048 case Match_InvalidGPR64shifted64:
4049 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4050 case Match_InvalidGPR64NoXZRshifted8:
4051 return Error(Loc, "register must be x0..x30 without shift");
4052 case Match_InvalidGPR64NoXZRshifted16:
4053 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4054 case Match_InvalidGPR64NoXZRshifted32:
4055 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4056 case Match_InvalidGPR64NoXZRshifted64:
4057 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004058 case Match_InvalidZPR32UXTW8:
4059 case Match_InvalidZPR32SXTW8:
4060 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4061 case Match_InvalidZPR32UXTW16:
4062 case Match_InvalidZPR32SXTW16:
4063 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4064 case Match_InvalidZPR32UXTW32:
4065 case Match_InvalidZPR32SXTW32:
4066 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4067 case Match_InvalidZPR32UXTW64:
4068 case Match_InvalidZPR32SXTW64:
4069 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4070 case Match_InvalidZPR64UXTW8:
4071 case Match_InvalidZPR64SXTW8:
4072 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4073 case Match_InvalidZPR64UXTW16:
4074 case Match_InvalidZPR64SXTW16:
4075 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4076 case Match_InvalidZPR64UXTW32:
4077 case Match_InvalidZPR64SXTW32:
4078 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4079 case Match_InvalidZPR64UXTW64:
4080 case Match_InvalidZPR64SXTW64:
4081 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
4082 case Match_InvalidZPR64LSL8:
4083 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4084 case Match_InvalidZPR64LSL16:
4085 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4086 case Match_InvalidZPR64LSL32:
4087 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4088 case Match_InvalidZPR64LSL64:
4089 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00004090 case Match_InvalidZPR0:
4091 return Error(Loc, "expected register without element width sufix");
4092 case Match_InvalidZPR8:
4093 case Match_InvalidZPR16:
4094 case Match_InvalidZPR32:
4095 case Match_InvalidZPR64:
4096 case Match_InvalidZPR128:
4097 return Error(Loc, "invalid element width");
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004098 case Match_InvalidZPR_3b8:
4099 return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b");
4100 case Match_InvalidZPR_3b16:
4101 return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h");
4102 case Match_InvalidZPR_3b32:
4103 return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s");
4104 case Match_InvalidZPR_4b16:
4105 return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h");
4106 case Match_InvalidZPR_4b32:
4107 return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s");
4108 case Match_InvalidZPR_4b64:
4109 return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004110 case Match_InvalidSVEPattern:
4111 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004112 case Match_InvalidSVEPredicateAnyReg:
4113 case Match_InvalidSVEPredicateBReg:
4114 case Match_InvalidSVEPredicateHReg:
4115 case Match_InvalidSVEPredicateSReg:
4116 case Match_InvalidSVEPredicateDReg:
4117 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004118 case Match_InvalidSVEPredicate3bAnyReg:
4119 case Match_InvalidSVEPredicate3bBReg:
4120 case Match_InvalidSVEPredicate3bHReg:
4121 case Match_InvalidSVEPredicate3bSReg:
4122 case Match_InvalidSVEPredicate3bDReg:
4123 return Error(Loc, "restricted predicate has range [0, 7].");
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004124 case Match_InvalidSVEExactFPImmOperandHalfOne:
4125 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4126 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4127 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4128 case Match_InvalidSVEExactFPImmOperandZeroOne:
4129 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004130 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004131 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004132 }
4133}
4134
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004135static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004136
4137bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4138 OperandVector &Operands,
4139 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004140 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004141 bool MatchingInlineAsm) {
4142 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004143 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4144 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004145
David Blaikie960ea3f2014-06-08 16:18:35 +00004146 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004147 unsigned NumOperands = Operands.size();
4148
4149 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004150 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4151 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004152 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004153 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004154 if (Op3CE) {
4155 uint64_t Op3Val = Op3CE->getValue();
4156 uint64_t NewOp3Val = 0;
4157 uint64_t NewOp4Val = 0;
4158 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004159 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004160 NewOp3Val = (32 - Op3Val) & 0x1f;
4161 NewOp4Val = 31 - Op3Val;
4162 } else {
4163 NewOp3Val = (64 - Op3Val) & 0x3f;
4164 NewOp4Val = 63 - Op3Val;
4165 }
4166
Jim Grosbach13760bd2015-05-30 01:25:56 +00004167 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4168 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004169
4170 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004171 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004172 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004173 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4174 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4175 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004176 }
4177 }
Tim Northover03b99f62015-04-30 18:28:58 +00004178 } else if (NumOperands == 4 && Tok == "bfc") {
4179 // FIXME: Horrible hack to handle BFC->BFM alias.
4180 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4181 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4182 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4183
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004184 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004185 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4186 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4187
4188 if (LSBCE && WidthCE) {
4189 uint64_t LSB = LSBCE->getValue();
4190 uint64_t Width = WidthCE->getValue();
4191
4192 uint64_t RegWidth = 0;
4193 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4194 Op1.getReg()))
4195 RegWidth = 64;
4196 else
4197 RegWidth = 32;
4198
4199 if (LSB >= RegWidth)
4200 return Error(LSBOp.getStartLoc(),
4201 "expected integer in range [0, 31]");
4202 if (Width < 1 || Width > RegWidth)
4203 return Error(WidthOp.getStartLoc(),
4204 "expected integer in range [1, 32]");
4205
4206 uint64_t ImmR = 0;
4207 if (RegWidth == 32)
4208 ImmR = (32 - LSB) & 0x1f;
4209 else
4210 ImmR = (64 - LSB) & 0x3f;
4211
4212 uint64_t ImmS = Width - 1;
4213
4214 if (ImmR != 0 && ImmS >= ImmR)
4215 return Error(WidthOp.getStartLoc(),
4216 "requested insert overflows register");
4217
Jim Grosbach13760bd2015-05-30 01:25:56 +00004218 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4219 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004220 Operands[0] = AArch64Operand::CreateToken(
4221 "bfm", false, Op.getStartLoc(), getContext());
4222 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004223 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4224 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004225 Operands[3] = AArch64Operand::CreateImm(
4226 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4227 Operands.emplace_back(
4228 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4229 WidthOp.getEndLoc(), getContext()));
4230 }
4231 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004232 } else if (NumOperands == 5) {
4233 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4234 // UBFIZ -> UBFM aliases.
4235 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004236 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4237 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4238 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004239
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004240 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004241 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4242 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004243
4244 if (Op3CE && Op4CE) {
4245 uint64_t Op3Val = Op3CE->getValue();
4246 uint64_t Op4Val = Op4CE->getValue();
4247
4248 uint64_t RegWidth = 0;
4249 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004250 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004251 RegWidth = 64;
4252 else
4253 RegWidth = 32;
4254
4255 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004256 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004257 "expected integer in range [0, 31]");
4258 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004259 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004260 "expected integer in range [1, 32]");
4261
4262 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004263 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004264 NewOp3Val = (32 - Op3Val) & 0x1f;
4265 else
4266 NewOp3Val = (64 - Op3Val) & 0x3f;
4267
4268 uint64_t NewOp4Val = Op4Val - 1;
4269
4270 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004271 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004272 "requested insert overflows register");
4273
4274 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004275 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004276 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004277 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004278 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004279 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004280 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004281 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004282 if (Tok == "bfi")
4283 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004284 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004285 else if (Tok == "sbfiz")
4286 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004287 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004288 else if (Tok == "ubfiz")
4289 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004290 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004291 else
4292 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004293 }
4294 }
4295
4296 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4297 // UBFX -> UBFM aliases.
4298 } else if (NumOperands == 5 &&
4299 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004300 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4301 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4302 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004303
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004304 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004305 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4306 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004307
4308 if (Op3CE && Op4CE) {
4309 uint64_t Op3Val = Op3CE->getValue();
4310 uint64_t Op4Val = Op4CE->getValue();
4311
4312 uint64_t RegWidth = 0;
4313 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004314 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004315 RegWidth = 64;
4316 else
4317 RegWidth = 32;
4318
4319 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004320 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004321 "expected integer in range [0, 31]");
4322 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004323 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004324 "expected integer in range [1, 32]");
4325
4326 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4327
4328 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004329 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004330 "requested extract overflows register");
4331
4332 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004333 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004334 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004335 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004336 if (Tok == "bfxil")
4337 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004338 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004339 else if (Tok == "sbfx")
4340 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004341 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004342 else if (Tok == "ubfx")
4343 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004344 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004345 else
4346 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004347 }
4348 }
4349 }
4350 }
Tim Northover9097a072017-12-18 10:36:00 +00004351
4352 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4353 // instruction for FP registers correctly in some rare circumstances. Convert
4354 // it to a safe instruction and warn (because silently changing someone's
4355 // assembly is rude).
4356 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4357 NumOperands == 4 && Tok == "movi") {
4358 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4359 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4360 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4361 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4362 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4363 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4364 if (Suffix.lower() == ".2d" &&
4365 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4366 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4367 " correctly on this CPU, converting to equivalent movi.16b");
4368 // Switch the suffix to .16b.
4369 unsigned Idx = Op1.isToken() ? 1 : 2;
4370 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4371 getContext());
4372 }
4373 }
4374 }
4375
Tim Northover3b0846e2014-05-24 12:50:23 +00004376 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4377 // InstAlias can't quite handle this since the reg classes aren't
4378 // subclasses.
4379 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4380 // The source register can be Wn here, but the matcher expects a
4381 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004382 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004383 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004384 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004385 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4386 Op.getStartLoc(), Op.getEndLoc(),
4387 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004388 }
4389 }
4390 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4391 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004392 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004393 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004394 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004395 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004396 // The source register can be Wn here, but the matcher expects a
4397 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004398 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004399 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004400 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004401 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4402 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004403 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004404 }
4405 }
4406 }
4407 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4408 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004409 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004410 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004411 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004412 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004413 // The source register can be Wn here, but the matcher expects a
4414 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004415 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004416 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004417 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004418 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4419 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004420 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004421 }
4422 }
4423 }
4424
Tim Northover3b0846e2014-05-24 12:50:23 +00004425 MCInst Inst;
4426 // First try to match against the secondary set of tables containing the
4427 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4428 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004429 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004430
4431 // If that fails, try against the alternate table containing long-form NEON:
4432 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004433 if (MatchResult != Match_Success) {
4434 // But first, save the short-form match result: we can use it in case the
4435 // long-form match also fails.
4436 auto ShortFormNEONErrorInfo = ErrorInfo;
4437 auto ShortFormNEONMatchResult = MatchResult;
4438
Tim Northover3b0846e2014-05-24 12:50:23 +00004439 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004440 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004441
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004442 // Now, both matches failed, and the long-form match failed on the mnemonic
4443 // suffix token operand. The short-form match failure is probably more
4444 // relevant: use it instead.
4445 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004446 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004447 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4448 MatchResult = ShortFormNEONMatchResult;
4449 ErrorInfo = ShortFormNEONErrorInfo;
4450 }
4451 }
4452
Tim Northover3b0846e2014-05-24 12:50:23 +00004453 switch (MatchResult) {
4454 case Match_Success: {
4455 // Perform range checking and other semantic validations
4456 SmallVector<SMLoc, 8> OperandLocs;
4457 NumOperands = Operands.size();
4458 for (unsigned i = 1; i < NumOperands; ++i)
4459 OperandLocs.push_back(Operands[i]->getStartLoc());
4460 if (validateInstruction(Inst, OperandLocs))
4461 return true;
4462
4463 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004464 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004465 return false;
4466 }
4467 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004468 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004469 // Special case the error message for the very common case where only
4470 // a single subtarget feature is missing (neon, e.g.).
4471 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004472 uint64_t Mask = 1;
4473 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4474 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004475 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004476 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004477 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004478 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004479 }
4480 return Error(IDLoc, Msg);
4481 }
4482 case Match_MnemonicFail:
Sander de Smalen0325e302018-07-02 07:34:52 +00004483 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004484 case Match_InvalidOperand: {
4485 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004486
Tim Northover26bb14e2014-08-18 11:49:42 +00004487 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004488 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004489 return Error(IDLoc, "too few operands for instruction",
4490 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004491
David Blaikie960ea3f2014-06-08 16:18:35 +00004492 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004493 if (ErrorLoc == SMLoc())
4494 ErrorLoc = IDLoc;
4495 }
4496 // If the match failed on a suffix token operand, tweak the diagnostic
4497 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004498 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4499 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004500 MatchResult = Match_InvalidSuffix;
4501
Sander de Smalen0325e302018-07-02 07:34:52 +00004502 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004503 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004504 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004505 case Match_InvalidMemoryIndexed1:
4506 case Match_InvalidMemoryIndexed2:
4507 case Match_InvalidMemoryIndexed4:
4508 case Match_InvalidMemoryIndexed8:
4509 case Match_InvalidMemoryIndexed16:
4510 case Match_InvalidCondCode:
4511 case Match_AddSubRegExtendSmall:
4512 case Match_AddSubRegExtendLarge:
4513 case Match_AddSubSecondSource:
4514 case Match_LogicalSecondSource:
4515 case Match_AddSubRegShift32:
4516 case Match_AddSubRegShift64:
4517 case Match_InvalidMovImm32Shift:
4518 case Match_InvalidMovImm64Shift:
4519 case Match_InvalidFPImm:
4520 case Match_InvalidMemoryWExtend8:
4521 case Match_InvalidMemoryWExtend16:
4522 case Match_InvalidMemoryWExtend32:
4523 case Match_InvalidMemoryWExtend64:
4524 case Match_InvalidMemoryWExtend128:
4525 case Match_InvalidMemoryXExtend8:
4526 case Match_InvalidMemoryXExtend16:
4527 case Match_InvalidMemoryXExtend32:
4528 case Match_InvalidMemoryXExtend64:
4529 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004530 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004531 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004532 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004533 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004534 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004535 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004536 case Match_InvalidMemoryIndexed4SImm7:
4537 case Match_InvalidMemoryIndexed8SImm7:
4538 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004539 case Match_InvalidMemoryIndexed8UImm5:
4540 case Match_InvalidMemoryIndexed4UImm5:
4541 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004542 case Match_InvalidMemoryIndexed1UImm6:
4543 case Match_InvalidMemoryIndexed2UImm6:
4544 case Match_InvalidMemoryIndexed4UImm6:
4545 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004546 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004547 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004548 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004549 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004550 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004551 case Match_InvalidImm0_7:
4552 case Match_InvalidImm0_15:
4553 case Match_InvalidImm0_31:
4554 case Match_InvalidImm0_63:
4555 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004556 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004557 case Match_InvalidImm0_65535:
4558 case Match_InvalidImm1_8:
4559 case Match_InvalidImm1_16:
4560 case Match_InvalidImm1_32:
4561 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004562 case Match_InvalidSVEAddSubImm8:
4563 case Match_InvalidSVEAddSubImm16:
4564 case Match_InvalidSVEAddSubImm32:
4565 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004566 case Match_InvalidSVECpyImm8:
4567 case Match_InvalidSVECpyImm16:
4568 case Match_InvalidSVECpyImm32:
4569 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004570 case Match_InvalidIndexRange1_1:
4571 case Match_InvalidIndexRange0_15:
4572 case Match_InvalidIndexRange0_7:
4573 case Match_InvalidIndexRange0_3:
4574 case Match_InvalidIndexRange0_1:
4575 case Match_InvalidSVEIndexRange0_63:
4576 case Match_InvalidSVEIndexRange0_31:
4577 case Match_InvalidSVEIndexRange0_15:
4578 case Match_InvalidSVEIndexRange0_7:
4579 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004580 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004581 case Match_InvalidComplexRotationEven:
4582 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004583 case Match_InvalidGPR64shifted8:
4584 case Match_InvalidGPR64shifted16:
4585 case Match_InvalidGPR64shifted32:
4586 case Match_InvalidGPR64shifted64:
4587 case Match_InvalidGPR64NoXZRshifted8:
4588 case Match_InvalidGPR64NoXZRshifted16:
4589 case Match_InvalidGPR64NoXZRshifted32:
4590 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004591 case Match_InvalidZPR32UXTW8:
4592 case Match_InvalidZPR32UXTW16:
4593 case Match_InvalidZPR32UXTW32:
4594 case Match_InvalidZPR32UXTW64:
4595 case Match_InvalidZPR32SXTW8:
4596 case Match_InvalidZPR32SXTW16:
4597 case Match_InvalidZPR32SXTW32:
4598 case Match_InvalidZPR32SXTW64:
4599 case Match_InvalidZPR64UXTW8:
4600 case Match_InvalidZPR64SXTW8:
4601 case Match_InvalidZPR64UXTW16:
4602 case Match_InvalidZPR64SXTW16:
4603 case Match_InvalidZPR64UXTW32:
4604 case Match_InvalidZPR64SXTW32:
4605 case Match_InvalidZPR64UXTW64:
4606 case Match_InvalidZPR64SXTW64:
4607 case Match_InvalidZPR64LSL8:
4608 case Match_InvalidZPR64LSL16:
4609 case Match_InvalidZPR64LSL32:
4610 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004611 case Match_InvalidZPR0:
4612 case Match_InvalidZPR8:
4613 case Match_InvalidZPR16:
4614 case Match_InvalidZPR32:
4615 case Match_InvalidZPR64:
4616 case Match_InvalidZPR128:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004617 case Match_InvalidZPR_3b8:
4618 case Match_InvalidZPR_3b16:
4619 case Match_InvalidZPR_3b32:
4620 case Match_InvalidZPR_4b16:
4621 case Match_InvalidZPR_4b32:
4622 case Match_InvalidZPR_4b64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004623 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004624 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004625 case Match_InvalidSVEPredicateBReg:
4626 case Match_InvalidSVEPredicateHReg:
4627 case Match_InvalidSVEPredicateSReg:
4628 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004629 case Match_InvalidSVEPredicate3bAnyReg:
4630 case Match_InvalidSVEPredicate3bBReg:
4631 case Match_InvalidSVEPredicate3bHReg:
4632 case Match_InvalidSVEPredicate3bSReg:
4633 case Match_InvalidSVEPredicate3bDReg:
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004634 case Match_InvalidSVEExactFPImmOperandHalfOne:
4635 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4636 case Match_InvalidSVEExactFPImmOperandZeroOne:
Tim Northover3b0846e2014-05-24 12:50:23 +00004637 case Match_MSR:
4638 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004639 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004640 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004641 // Any time we get here, there's nothing fancy to do. Just get the
4642 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004643 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004644 if (ErrorLoc == SMLoc())
4645 ErrorLoc = IDLoc;
Sander de Smalen0325e302018-07-02 07:34:52 +00004646 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004647 }
4648 }
4649
4650 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004651}
4652
4653/// ParseDirective parses the arm specific directives
4654bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004655 const MCObjectFileInfo::Environment Format =
4656 getContext().getObjectFileInfo()->getObjectFileType();
4657 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4658 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004659
Tim Northover3b0846e2014-05-24 12:50:23 +00004660 StringRef IDVal = DirectiveID.getIdentifier();
4661 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004662 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004663 parseDirectiveArch(Loc);
4664 else if (IDVal == ".cpu")
4665 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00004666 else if (IDVal == ".tlsdesccall")
4667 parseDirectiveTLSDescCall(Loc);
4668 else if (IDVal == ".ltorg" || IDVal == ".pool")
4669 parseDirectiveLtorg(Loc);
4670 else if (IDVal == ".unreq")
4671 parseDirectiveUnreq(Loc);
4672 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004673 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004674 parseDirectiveInst(Loc);
4675 else
4676 return true;
4677 } else if (IDVal == MCLOHDirectiveName())
4678 parseDirectiveLOH(IDVal, Loc);
4679 else
4680 return true;
4681 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004682}
4683
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004684static const struct {
4685 const char *Name;
4686 const FeatureBitset Features;
4687} ExtensionMap[] = {
4688 { "crc", {AArch64::FeatureCRC} },
4689 { "crypto", {AArch64::FeatureCrypto} },
4690 { "fp", {AArch64::FeatureFPARMv8} },
4691 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004692 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004693 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004694
4695 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004696 { "pan", {} },
4697 { "lor", {} },
4698 { "rdma", {} },
4699 { "profile", {} },
4700};
4701
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004702/// parseDirectiveArch
4703/// ::= .arch token
4704bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4705 SMLoc ArchLoc = getLoc();
4706
4707 StringRef Arch, ExtensionString;
4708 std::tie(Arch, ExtensionString) =
4709 getParser().parseStringToEndOfStatement().trim().split('+');
4710
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004711 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4712 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004713 return Error(ArchLoc, "unknown arch name");
4714
4715 if (parseToken(AsmToken::EndOfStatement))
4716 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004717
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004718 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004719 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004720 AArch64::getArchFeatures(ID, AArch64Features);
4721 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4722 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004723
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004724 MCSubtargetInfo &STI = copySTI();
4725 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4726 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4727
4728 SmallVector<StringRef, 4> RequestedExtensions;
4729 if (!ExtensionString.empty())
4730 ExtensionString.split(RequestedExtensions, '+');
4731
4732 FeatureBitset Features = STI.getFeatureBits();
4733 for (auto Name : RequestedExtensions) {
4734 bool EnableFeature = true;
4735
4736 if (Name.startswith_lower("no")) {
4737 EnableFeature = false;
4738 Name = Name.substr(2);
4739 }
4740
4741 for (const auto &Extension : ExtensionMap) {
4742 if (Extension.Name != Name)
4743 continue;
4744
4745 if (Extension.Features.none())
4746 report_fatal_error("unsupported architectural extension: " + Name);
4747
4748 FeatureBitset ToggleFeatures = EnableFeature
4749 ? (~Features & Extension.Features)
4750 : ( Features & Extension.Features);
4751 uint64_t Features =
4752 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4753 setAvailableFeatures(Features);
4754 break;
4755 }
4756 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004757 return false;
4758}
4759
Tim Northover8b96c7e2017-05-15 19:42:15 +00004760static SMLoc incrementLoc(SMLoc L, int Offset) {
4761 return SMLoc::getFromPointer(L.getPointer() + Offset);
4762}
4763
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004764/// parseDirectiveCPU
4765/// ::= .cpu id
4766bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004767 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004768
4769 StringRef CPU, ExtensionString;
4770 std::tie(CPU, ExtensionString) =
4771 getParser().parseStringToEndOfStatement().trim().split('+');
4772
Nirav Davee833c6c2016-11-08 18:31:04 +00004773 if (parseToken(AsmToken::EndOfStatement))
4774 return true;
4775
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004776 SmallVector<StringRef, 4> RequestedExtensions;
4777 if (!ExtensionString.empty())
4778 ExtensionString.split(RequestedExtensions, '+');
4779
4780 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4781 // once that is tablegen'ed
4782 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004783 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004784 return false;
4785 }
4786
4787 MCSubtargetInfo &STI = copySTI();
4788 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004789 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004790
4791 FeatureBitset Features = STI.getFeatureBits();
4792 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004793 // Advance source location past '+'.
4794 CurLoc = incrementLoc(CurLoc, 1);
4795
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004796 bool EnableFeature = true;
4797
4798 if (Name.startswith_lower("no")) {
4799 EnableFeature = false;
4800 Name = Name.substr(2);
4801 }
4802
Tim Northover8b96c7e2017-05-15 19:42:15 +00004803 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004804 for (const auto &Extension : ExtensionMap) {
4805 if (Extension.Name != Name)
4806 continue;
4807
4808 if (Extension.Features.none())
4809 report_fatal_error("unsupported architectural extension: " + Name);
4810
4811 FeatureBitset ToggleFeatures = EnableFeature
4812 ? (~Features & Extension.Features)
4813 : ( Features & Extension.Features);
4814 uint64_t Features =
4815 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4816 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004817 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004818
4819 break;
4820 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004821
4822 if (!FoundExtension)
4823 Error(CurLoc, "unsupported architectural extension");
4824
4825 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004826 }
4827 return false;
4828}
4829
Chad Rosierdcd2a302014-10-22 20:35:57 +00004830/// parseDirectiveInst
4831/// ::= .inst opcode [, ...]
4832bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004833 if (getLexer().is(AsmToken::EndOfStatement))
4834 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004835
Nirav Davee833c6c2016-11-08 18:31:04 +00004836 auto parseOp = [&]() -> bool {
4837 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004838 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004839 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4840 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004841 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004842 if (check(!Value, L, "expected constant expression"))
4843 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004844 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004845 return false;
4846 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004847
Nirav Davee833c6c2016-11-08 18:31:04 +00004848 if (parseMany(parseOp))
4849 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004850 return false;
4851}
4852
Tim Northover3b0846e2014-05-24 12:50:23 +00004853// parseDirectiveTLSDescCall:
4854// ::= .tlsdesccall symbol
4855bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4856 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004857 if (check(getParser().parseIdentifier(Name), L,
4858 "expected symbol after directive") ||
4859 parseToken(AsmToken::EndOfStatement))
4860 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004861
Jim Grosbach6f482002015-05-18 18:43:14 +00004862 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004863 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4864 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004865
4866 MCInst Inst;
4867 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004868 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004869
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004870 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004871 return false;
4872}
4873
4874/// ::= .loh <lohName | lohId> label1, ..., labelN
4875/// The number of arguments depends on the loh identifier.
4876bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004877 MCLOHType Kind;
4878 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4879 if (getParser().getTok().isNot(AsmToken::Integer))
4880 return TokError("expected an identifier or a number in directive");
4881 // We successfully get a numeric value for the identifier.
4882 // Check if it is valid.
4883 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004884 if (Id <= -1U && !isValidMCLOHType(Id))
4885 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004886 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004887 } else {
4888 StringRef Name = getTok().getIdentifier();
4889 // We successfully parse an identifier.
4890 // Check if it is a recognized one.
4891 int Id = MCLOHNameToId(Name);
4892
4893 if (Id == -1)
4894 return TokError("invalid identifier in directive");
4895 Kind = (MCLOHType)Id;
4896 }
4897 // Consume the identifier.
4898 Lex();
4899 // Get the number of arguments of this LOH.
4900 int NbArgs = MCLOHIdToNbArgs(Kind);
4901
4902 assert(NbArgs != -1 && "Invalid number of arguments");
4903
4904 SmallVector<MCSymbol *, 3> Args;
4905 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4906 StringRef Name;
4907 if (getParser().parseIdentifier(Name))
4908 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004909 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004910
4911 if (Idx + 1 == NbArgs)
4912 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004913 if (parseToken(AsmToken::Comma,
4914 "unexpected token in '" + Twine(IDVal) + "' directive"))
4915 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004916 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004917 if (parseToken(AsmToken::EndOfStatement,
4918 "unexpected token in '" + Twine(IDVal) + "' directive"))
4919 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004920
4921 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4922 return false;
4923}
4924
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004925/// parseDirectiveLtorg
4926/// ::= .ltorg | .pool
4927bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004928 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4929 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004930 getTargetStreamer().emitCurrentConstantPool();
4931 return false;
4932}
4933
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004934/// parseDirectiveReq
4935/// ::= name .req registername
4936bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004937 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004938 Parser.Lex(); // Eat the '.req' token.
4939 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004940 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004941 unsigned RegNum;
4942 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004943
Sander de Smalen50d87022018-04-19 07:35:08 +00004944 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004945 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004946 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004947 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004948
Sander de Smalen50d87022018-04-19 07:35:08 +00004949 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004950 return true;
4951
Sander de Smalen50d87022018-04-19 07:35:08 +00004952 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004953 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004954 }
4955
Sander de Smalen50d87022018-04-19 07:35:08 +00004956 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004957 StringRef Kind;
4958 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004959 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004960 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004961
Sander de Smalen50d87022018-04-19 07:35:08 +00004962 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004963 return true;
4964
Sander de Smalen50d87022018-04-19 07:35:08 +00004965 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004966 return Error(SRegLoc,
4967 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004968 }
4969
Sander de Smalen50d87022018-04-19 07:35:08 +00004970 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00004971 StringRef Kind;
4972 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004973 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004974
Sander de Smalen50d87022018-04-19 07:35:08 +00004975 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00004976 return true;
4977
Sander de Smalen50d87022018-04-19 07:35:08 +00004978 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00004979 return Error(SRegLoc,
4980 "sve predicate register without type specifier expected");
4981 }
4982
Sander de Smalen50d87022018-04-19 07:35:08 +00004983 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00004984 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004985
4986 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004987 if (parseToken(AsmToken::EndOfStatement,
4988 "unexpected input in .req directive"))
4989 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004990
Sander de Smalen8e607342017-11-15 15:44:43 +00004991 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004992 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004993 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4994
Nirav Dave2364748a2016-09-16 18:30:20 +00004995 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004996}
4997
4998/// parseDirectiveUneq
4999/// ::= .unreq registername
5000bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005001 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00005002 if (getTok().isNot(AsmToken::Identifier))
5003 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005004 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
5005 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00005006 if (parseToken(AsmToken::EndOfStatement))
5007 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005008 return false;
5009}
5010
Tim Northover3b0846e2014-05-24 12:50:23 +00005011bool
5012AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
5013 AArch64MCExpr::VariantKind &ELFRefKind,
5014 MCSymbolRefExpr::VariantKind &DarwinRefKind,
5015 int64_t &Addend) {
5016 ELFRefKind = AArch64MCExpr::VK_INVALID;
5017 DarwinRefKind = MCSymbolRefExpr::VK_None;
5018 Addend = 0;
5019
5020 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5021 ELFRefKind = AE->getKind();
5022 Expr = AE->getSubExpr();
5023 }
5024
5025 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5026 if (SE) {
5027 // It's a simple symbol reference with no addend.
5028 DarwinRefKind = SE->getKind();
5029 return true;
5030 }
5031
5032 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
5033 if (!BE)
5034 return false;
5035
5036 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
5037 if (!SE)
5038 return false;
5039 DarwinRefKind = SE->getKind();
5040
5041 if (BE->getOpcode() != MCBinaryExpr::Add &&
5042 BE->getOpcode() != MCBinaryExpr::Sub)
5043 return false;
5044
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00005045 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00005046 // on here than we can deal with.
5047 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
5048 if (!AddendExpr)
5049 return false;
5050
5051 Addend = AddendExpr->getValue();
5052 if (BE->getOpcode() == MCBinaryExpr::Sub)
5053 Addend = -Addend;
5054
5055 // It's some symbol reference + a constant addend, but really
5056 // shouldn't use both Darwin and ELF syntax.
5057 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5058 DarwinRefKind == MCSymbolRefExpr::VK_None;
5059}
5060
5061/// Force static initialization.
5062extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00005063 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5064 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5065 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00005066}
5067
5068#define GET_REGISTER_MATCHER
5069#define GET_SUBTARGET_FEATURE_NAME
5070#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00005071#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00005072#include "AArch64GenAsmMatcher.inc"
5073
5074// Define this matcher function after the auto-generated include so we
5075// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00005076unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00005077 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005078 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00005079 // If the kind is a token for a literal immediate, check if our asm
5080 // operand matches. This is for InstAliases which have a fixed-value
5081 // immediate in the syntax.
5082 int64_t ExpectedVal;
5083 switch (Kind) {
5084 default:
5085 return Match_InvalidOperand;
5086 case MCK__35_0:
5087 ExpectedVal = 0;
5088 break;
5089 case MCK__35_1:
5090 ExpectedVal = 1;
5091 break;
5092 case MCK__35_12:
5093 ExpectedVal = 12;
5094 break;
5095 case MCK__35_16:
5096 ExpectedVal = 16;
5097 break;
5098 case MCK__35_2:
5099 ExpectedVal = 2;
5100 break;
5101 case MCK__35_24:
5102 ExpectedVal = 24;
5103 break;
5104 case MCK__35_3:
5105 ExpectedVal = 3;
5106 break;
5107 case MCK__35_32:
5108 ExpectedVal = 32;
5109 break;
5110 case MCK__35_4:
5111 ExpectedVal = 4;
5112 break;
5113 case MCK__35_48:
5114 ExpectedVal = 48;
5115 break;
5116 case MCK__35_6:
5117 ExpectedVal = 6;
5118 break;
5119 case MCK__35_64:
5120 ExpectedVal = 64;
5121 break;
5122 case MCK__35_8:
5123 ExpectedVal = 8;
5124 break;
5125 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005126 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005127 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005128 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005129 if (!CE)
5130 return Match_InvalidOperand;
5131 if (CE->getValue() == ExpectedVal)
5132 return Match_Success;
5133 return Match_InvalidOperand;
5134}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005135
Alex Bradbury58eba092016-11-01 16:32:05 +00005136OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005137AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5138
5139 SMLoc S = getLoc();
5140
5141 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5142 Error(S, "expected register");
5143 return MatchOperand_ParseFail;
5144 }
5145
Sander de Smalen50d87022018-04-19 07:35:08 +00005146 unsigned FirstReg;
5147 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5148 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005149 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005150
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005151 const MCRegisterClass &WRegClass =
5152 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5153 const MCRegisterClass &XRegClass =
5154 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5155
5156 bool isXReg = XRegClass.contains(FirstReg),
5157 isWReg = WRegClass.contains(FirstReg);
5158 if (!isXReg && !isWReg) {
5159 Error(S, "expected first even register of a "
5160 "consecutive same-size even/odd register pair");
5161 return MatchOperand_ParseFail;
5162 }
5163
5164 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5165 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5166
5167 if (FirstEncoding & 0x1) {
5168 Error(S, "expected first even register of a "
5169 "consecutive same-size even/odd register pair");
5170 return MatchOperand_ParseFail;
5171 }
5172
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005173 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005174 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005175 return MatchOperand_ParseFail;
5176 }
5177 // Eat the comma
5178 getParser().Lex();
5179
5180 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005181 unsigned SecondReg;
5182 Res = tryParseScalarRegister(SecondReg);
5183 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005184 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005185
Eugene Zelenko049b0172017-01-06 00:30:53 +00005186 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005187 (isXReg && !XRegClass.contains(SecondReg)) ||
5188 (isWReg && !WRegClass.contains(SecondReg))) {
5189 Error(E,"expected second odd register of a "
5190 "consecutive same-size even/odd register pair");
5191 return MatchOperand_ParseFail;
5192 }
Joel Jones504bf332016-10-24 13:37:13 +00005193
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005194 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005195 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005196 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5197 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5198 } else {
5199 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5200 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5201 }
5202
Florian Hahnc4422242017-11-07 13:07:50 +00005203 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5204 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005205
5206 return MatchOperand_Success;
5207}
Florian Hahn91f11e52017-11-07 16:45:48 +00005208
Sander de Smaleneb896b12018-04-25 09:26:47 +00005209template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005210OperandMatchResultTy
5211AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005212 const SMLoc S = getLoc();
5213 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005214 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005215 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005216
Sander de Smalen8e607342017-11-15 15:44:43 +00005217 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005218 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005219
5220 if (Res != MatchOperand_Success)
5221 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005222
5223 if (ParseSuffix && Kind.empty())
5224 return MatchOperand_NoMatch;
5225
Sander de Smalen73937b72018-04-11 07:36:10 +00005226 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5227 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005228 return MatchOperand_NoMatch;
5229
Sander de Smalen73937b72018-04-11 07:36:10 +00005230 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005231
5232 // No shift/extend is the default.
5233 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5234 Operands.push_back(AArch64Operand::CreateVectorReg(
5235 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5236
Sander de Smalenc33d6682018-06-04 06:40:55 +00005237 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5238 if (Res == MatchOperand_ParseFail)
5239 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005240 return MatchOperand_Success;
5241 }
5242
5243 // Eat the comma
5244 getParser().Lex();
5245
5246 // Match the shift
5247 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5248 Res = tryParseOptionalShiftExtend(ExtOpnd);
5249 if (Res != MatchOperand_Success)
5250 return Res;
5251
5252 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005253 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005254 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5255 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5256 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005257
5258 return MatchOperand_Success;
5259}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005260
5261OperandMatchResultTy
5262AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5263 MCAsmParser &Parser = getParser();
5264
5265 SMLoc SS = getLoc();
5266 const AsmToken &TokE = Parser.getTok();
5267 bool IsHash = TokE.is(AsmToken::Hash);
5268
5269 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5270 return MatchOperand_NoMatch;
5271
5272 int64_t Pattern;
5273 if (IsHash) {
5274 Parser.Lex(); // Eat hash
5275
5276 // Parse the immediate operand.
5277 const MCExpr *ImmVal;
5278 SS = getLoc();
5279 if (Parser.parseExpression(ImmVal))
5280 return MatchOperand_ParseFail;
5281
5282 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5283 if (!MCE)
5284 return MatchOperand_ParseFail;
5285
5286 Pattern = MCE->getValue();
5287 } else {
5288 // Parse the pattern
5289 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5290 if (!Pat)
5291 return MatchOperand_NoMatch;
5292
5293 Parser.Lex();
5294 Pattern = Pat->Encoding;
5295 assert(Pattern >= 0 && Pattern < 32);
5296 }
5297
5298 Operands.push_back(
5299 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5300 SS, getLoc(), getContext()));
5301
5302 return MatchOperand_Success;
5303}