blob: 3e24299ec98b2c034c69a3d847ad3caf6608b5ce [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/AArch64AddressingModes.h"
11#include "MCTargetDesc/AArch64MCExpr.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000012#include "MCTargetDesc/AArch64MCTargetDesc.h"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000013#include "MCTargetDesc/AArch64TargetStreamer.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000014#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000015#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000016#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000017#include "llvm/ADT/ArrayRef.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000018#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "llvm/ADT/SmallVector.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000020#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000021#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000023#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000025#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000028#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000029#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000030#include "llvm/MC/MCParser/MCAsmLexer.h"
31#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000032#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000033#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000034#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000035#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSubtargetInfo.h"
38#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000039#include "llvm/MC/MCTargetOptions.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000043#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000044#include "llvm/Support/MathExtras.h"
45#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000046#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000047#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000049#include <cassert>
50#include <cctype>
51#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000052#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000053#include <string>
54#include <tuple>
55#include <utility>
56#include <vector>
57
Tim Northover3b0846e2014-05-24 12:50:23 +000058using namespace llvm;
59
60namespace {
61
Sander de Smalencd6be962017-12-20 11:02:42 +000062enum class RegKind {
63 Scalar,
64 NeonVector,
65 SVEDataVector,
66 SVEPredicateVector
67};
Florian Hahnc4422242017-11-07 13:07:50 +000068
Sander de Smalen0325e302018-07-02 07:34:52 +000069enum RegConstraintEqualityTy {
70 EqualsReg,
71 EqualsSuperReg,
72 EqualsSubReg
73};
74
Tim Northover3b0846e2014-05-24 12:50:23 +000075class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000076private:
77 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000078
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000079 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000080 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000081
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000082 AArch64TargetStreamer &getTargetStreamer() {
83 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
84 return static_cast<AArch64TargetStreamer &>(TS);
85 }
86
Rafael Espindola961d4692014-11-11 05:18:41 +000087 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000088
89 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +000090 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +000091 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
92 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +000093 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +000094 bool parseRegister(OperandVector &Operands);
95 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
Sander de Smalenc88f9a12018-04-11 14:10:37 +000096 bool parseNeonVectorList(OperandVector &Operands);
Sander de Smalen18ac8f92018-06-15 15:47:44 +000097 bool parseOptionalMulOperand(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000098 bool parseOperand(OperandVector &Operands, bool isCondCode,
99 bool invertCondCode);
100
Sander de Smalen0325e302018-07-02 07:34:52 +0000101 bool showMatchError(SMLoc Loc, unsigned ErrCode, uint64_t ErrorInfo,
102 OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000103
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +0000104 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +0000105 bool parseDirectiveCPU(SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +0000106 bool parseDirectiveInst(SMLoc L);
107
Tim Northover3b0846e2014-05-24 12:50:23 +0000108 bool parseDirectiveTLSDescCall(SMLoc L);
109
110 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000111 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000112
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000113 bool parseDirectiveReq(StringRef Name, SMLoc L);
114 bool parseDirectiveUnreq(SMLoc L);
115
Tim Northover3b0846e2014-05-24 12:50:23 +0000116 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
117 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
118 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000119 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000120 bool MatchingInlineAsm) override;
121/// @name Auto-generated Match Functions
122/// {
123
124#define GET_ASSEMBLER_HEADER
125#include "AArch64GenAsmMatcher.inc"
126
127 /// }
128
Sander de Smalen50d87022018-04-19 07:35:08 +0000129 OperandMatchResultTy tryParseScalarRegister(unsigned &Reg);
130 OperandMatchResultTy tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +0000131 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000132 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
133 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
134 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
135 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
136 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
Sander de Smalen93380372018-05-14 11:54:41 +0000137 template <bool IsSVEPrefetch = false>
Tim Northover3b0846e2014-05-24 12:50:23 +0000138 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000139 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000140 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
141 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000142 template<bool AddFPZeroAsLiteral>
Tim Northover3b0846e2014-05-24 12:50:23 +0000143 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
Sander de Smalen62770792018-05-25 09:47:52 +0000144 OperandMatchResultTy tryParseImmWithOptionalShift(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000145 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000146 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000147 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000148 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Sander de Smalen0325e302018-07-02 07:34:52 +0000149 template <bool ParseShiftExtend,
150 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg>
Sander de Smalen149916d2018-04-20 07:24:20 +0000151 OperandMatchResultTy tryParseGPROperand(OperandVector &Operands);
Sander de Smaleneb896b12018-04-25 09:26:47 +0000152 template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +0000153 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000154 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000155 template <RegKind VectorKind>
156 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
157 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000158 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000159
160public:
161 enum AArch64MatchResultTy {
162 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
163#define GET_OPERAND_DIAGNOSTIC_TYPES
164#include "AArch64GenAsmMatcher.inc"
165 };
Joel Jones504bf332016-10-24 13:37:13 +0000166 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000167
Akira Hatanakab11ef082015-11-14 06:35:56 +0000168 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000169 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000170 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000171 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000172 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000173 MCStreamer &S = getParser().getStreamer();
174 if (S.getTargetStreamer() == nullptr)
175 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000176
Alex Bradbury0a59f182018-05-23 11:17:20 +0000177 // Alias .hword/.word/xword to the target-independent .2byte/.4byte/.8byte
178 // directives as they have the same form and semantics:
179 /// ::= (.hword | .word | .xword ) [ expression (, expression)* ]
180 Parser.addAliasForDirective(".hword", ".2byte");
181 Parser.addAliasForDirective(".word", ".4byte");
182 Parser.addAliasForDirective(".xword", ".8byte");
183
Tim Northover3b0846e2014-05-24 12:50:23 +0000184 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000185 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000186 }
187
Sander de Smalen0325e302018-07-02 07:34:52 +0000188 bool regsEqual(const MCParsedAsmOperand &Op1,
189 const MCParsedAsmOperand &Op2) const override;
Tim Northover3b0846e2014-05-24 12:50:23 +0000190 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
191 SMLoc NameLoc, OperandVector &Operands) override;
192 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
193 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000194 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000195 unsigned Kind) override;
196
197 static bool classifySymbolRef(const MCExpr *Expr,
198 AArch64MCExpr::VariantKind &ELFRefKind,
199 MCSymbolRefExpr::VariantKind &DarwinRefKind,
200 int64_t &Addend);
201};
Tim Northover3b0846e2014-05-24 12:50:23 +0000202
203/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
204/// instruction.
205class AArch64Operand : public MCParsedAsmOperand {
206private:
207 enum KindTy {
208 k_Immediate,
209 k_ShiftedImm,
210 k_CondCode,
211 k_Register,
212 k_VectorList,
213 k_VectorIndex,
214 k_Token,
215 k_SysReg,
216 k_SysCR,
217 k_Prefetch,
218 k_ShiftExtend,
219 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000220 k_Barrier,
221 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000222 } Kind;
223
224 SMLoc StartLoc, EndLoc;
225
226 struct TokOp {
227 const char *Data;
228 unsigned Length;
229 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
230 };
231
Sander de Smalen149916d2018-04-20 07:24:20 +0000232 // Separate shift/extend operand.
233 struct ShiftExtendOp {
234 AArch64_AM::ShiftExtendType Type;
235 unsigned Amount;
236 bool HasExplicitAmount;
237 };
238
Tim Northover3b0846e2014-05-24 12:50:23 +0000239 struct RegOp {
240 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000241 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000242 int ElementWidth;
Sander de Smalen149916d2018-04-20 07:24:20 +0000243
Sander de Smalen0325e302018-07-02 07:34:52 +0000244 // The register may be allowed as a different register class,
245 // e.g. for GPR64as32 or GPR32as64.
246 RegConstraintEqualityTy EqualityTy;
247
Sander de Smalen149916d2018-04-20 07:24:20 +0000248 // In some cases the shift/extend needs to be explicitly parsed together
249 // with the register, rather than as a separate operand. This is needed
250 // for addressing modes where the instruction as a whole dictates the
251 // scaling/extend, rather than specific bits in the instruction.
252 // By parsing them as a single operand, we avoid the need to pass an
253 // extra operand in all CodeGen patterns (because all operands need to
254 // have an associated value), and we avoid the need to update TableGen to
255 // accept operands that have no associated bits in the instruction.
256 //
257 // An added benefit of parsing them together is that the assembler
258 // can give a sensible diagnostic if the scaling is not correct.
259 //
260 // The default is 'lsl #0' (HasExplicitAmount = false) if no
261 // ShiftExtend is specified.
262 ShiftExtendOp ShiftExtend;
Tim Northover3b0846e2014-05-24 12:50:23 +0000263 };
264
265 struct VectorListOp {
266 unsigned RegNum;
267 unsigned Count;
268 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000269 unsigned ElementWidth;
270 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000271 };
272
273 struct VectorIndexOp {
274 unsigned Val;
275 };
276
277 struct ImmOp {
278 const MCExpr *Val;
279 };
280
281 struct ShiftedImmOp {
282 const MCExpr *Val;
283 unsigned ShiftAmount;
284 };
285
286 struct CondCodeOp {
287 AArch64CC::CondCode Code;
288 };
289
290 struct FPImmOp {
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000291 uint64_t Val; // APFloat value bitcasted to uint64_t.
292 bool IsExact; // describes whether parsed value was exact.
Tim Northover3b0846e2014-05-24 12:50:23 +0000293 };
294
295 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000296 const char *Data;
297 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000298 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000299 };
300
301 struct SysRegOp {
302 const char *Data;
303 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000304 uint32_t MRSReg;
305 uint32_t MSRReg;
306 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000307 };
308
309 struct SysCRImmOp {
310 unsigned Val;
311 };
312
313 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000314 const char *Data;
315 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000316 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000317 };
318
Oliver Stannarda34e4702015-12-01 10:48:51 +0000319 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000320 const char *Data;
321 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000322 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000323 };
324
Tim Northover3b0846e2014-05-24 12:50:23 +0000325 struct ExtendOp {
326 unsigned Val;
327 };
328
329 union {
330 struct TokOp Tok;
331 struct RegOp Reg;
332 struct VectorListOp VectorList;
333 struct VectorIndexOp VectorIndex;
334 struct ImmOp Imm;
335 struct ShiftedImmOp ShiftedImm;
336 struct CondCodeOp CondCode;
337 struct FPImmOp FPImm;
338 struct BarrierOp Barrier;
339 struct SysRegOp SysReg;
340 struct SysCRImmOp SysCRImm;
341 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000342 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000343 struct ShiftExtendOp ShiftExtend;
344 };
345
346 // Keep the MCContext around as the MCExprs may need manipulated during
347 // the add<>Operands() calls.
348 MCContext &Ctx;
349
David Blaikie960ea3f2014-06-08 16:18:35 +0000350public:
David Blaikie9f380a32015-03-16 18:06:57 +0000351 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000352
Tim Northover3b0846e2014-05-24 12:50:23 +0000353 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
354 Kind = o.Kind;
355 StartLoc = o.StartLoc;
356 EndLoc = o.EndLoc;
357 switch (Kind) {
358 case k_Token:
359 Tok = o.Tok;
360 break;
361 case k_Immediate:
362 Imm = o.Imm;
363 break;
364 case k_ShiftedImm:
365 ShiftedImm = o.ShiftedImm;
366 break;
367 case k_CondCode:
368 CondCode = o.CondCode;
369 break;
370 case k_FPImm:
371 FPImm = o.FPImm;
372 break;
373 case k_Barrier:
374 Barrier = o.Barrier;
375 break;
376 case k_Register:
377 Reg = o.Reg;
378 break;
379 case k_VectorList:
380 VectorList = o.VectorList;
381 break;
382 case k_VectorIndex:
383 VectorIndex = o.VectorIndex;
384 break;
385 case k_SysReg:
386 SysReg = o.SysReg;
387 break;
388 case k_SysCR:
389 SysCRImm = o.SysCRImm;
390 break;
391 case k_Prefetch:
392 Prefetch = o.Prefetch;
393 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000394 case k_PSBHint:
395 PSBHint = o.PSBHint;
396 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000397 case k_ShiftExtend:
398 ShiftExtend = o.ShiftExtend;
399 break;
400 }
401 }
402
403 /// getStartLoc - Get the location of the first token of this operand.
404 SMLoc getStartLoc() const override { return StartLoc; }
405 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000406 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000407
408 StringRef getToken() const {
409 assert(Kind == k_Token && "Invalid access!");
410 return StringRef(Tok.Data, Tok.Length);
411 }
412
413 bool isTokenSuffix() const {
414 assert(Kind == k_Token && "Invalid access!");
415 return Tok.IsSuffix;
416 }
417
418 const MCExpr *getImm() const {
419 assert(Kind == k_Immediate && "Invalid access!");
420 return Imm.Val;
421 }
422
423 const MCExpr *getShiftedImmVal() const {
424 assert(Kind == k_ShiftedImm && "Invalid access!");
425 return ShiftedImm.Val;
426 }
427
428 unsigned getShiftedImmShift() const {
429 assert(Kind == k_ShiftedImm && "Invalid access!");
430 return ShiftedImm.ShiftAmount;
431 }
432
433 AArch64CC::CondCode getCondCode() const {
434 assert(Kind == k_CondCode && "Invalid access!");
435 return CondCode.Code;
436 }
437
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000438 APFloat getFPImm() const {
439 assert (Kind == k_FPImm && "Invalid access!");
440 return APFloat(APFloat::IEEEdouble(), APInt(64, FPImm.Val, true));
441 }
442
443 bool getFPImmIsExact() const {
444 assert (Kind == k_FPImm && "Invalid access!");
445 return FPImm.IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +0000446 }
447
448 unsigned getBarrier() const {
449 assert(Kind == k_Barrier && "Invalid access!");
450 return Barrier.Val;
451 }
452
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000453 StringRef getBarrierName() const {
454 assert(Kind == k_Barrier && "Invalid access!");
455 return StringRef(Barrier.Data, Barrier.Length);
456 }
457
Tim Northover3b0846e2014-05-24 12:50:23 +0000458 unsigned getReg() const override {
459 assert(Kind == k_Register && "Invalid access!");
460 return Reg.RegNum;
461 }
462
Sander de Smalen0325e302018-07-02 07:34:52 +0000463 RegConstraintEqualityTy getRegEqualityTy() const {
464 assert(Kind == k_Register && "Invalid access!");
465 return Reg.EqualityTy;
466 }
467
Tim Northover3b0846e2014-05-24 12:50:23 +0000468 unsigned getVectorListStart() const {
469 assert(Kind == k_VectorList && "Invalid access!");
470 return VectorList.RegNum;
471 }
472
473 unsigned getVectorListCount() const {
474 assert(Kind == k_VectorList && "Invalid access!");
475 return VectorList.Count;
476 }
477
478 unsigned getVectorIndex() const {
479 assert(Kind == k_VectorIndex && "Invalid access!");
480 return VectorIndex.Val;
481 }
482
483 StringRef getSysReg() const {
484 assert(Kind == k_SysReg && "Invalid access!");
485 return StringRef(SysReg.Data, SysReg.Length);
486 }
487
Tim Northover3b0846e2014-05-24 12:50:23 +0000488 unsigned getSysCR() const {
489 assert(Kind == k_SysCR && "Invalid access!");
490 return SysCRImm.Val;
491 }
492
493 unsigned getPrefetch() const {
494 assert(Kind == k_Prefetch && "Invalid access!");
495 return Prefetch.Val;
496 }
497
Oliver Stannarda34e4702015-12-01 10:48:51 +0000498 unsigned getPSBHint() const {
499 assert(Kind == k_PSBHint && "Invalid access!");
500 return PSBHint.Val;
501 }
502
503 StringRef getPSBHintName() const {
504 assert(Kind == k_PSBHint && "Invalid access!");
505 return StringRef(PSBHint.Data, PSBHint.Length);
506 }
507
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000508 StringRef getPrefetchName() const {
509 assert(Kind == k_Prefetch && "Invalid access!");
510 return StringRef(Prefetch.Data, Prefetch.Length);
511 }
512
Tim Northover3b0846e2014-05-24 12:50:23 +0000513 AArch64_AM::ShiftExtendType getShiftExtendType() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000514 if (Kind == k_ShiftExtend)
515 return ShiftExtend.Type;
516 if (Kind == k_Register)
517 return Reg.ShiftExtend.Type;
518 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000519 }
520
521 unsigned getShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000522 if (Kind == k_ShiftExtend)
523 return ShiftExtend.Amount;
524 if (Kind == k_Register)
525 return Reg.ShiftExtend.Amount;
526 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000527 }
528
529 bool hasShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000530 if (Kind == k_ShiftExtend)
531 return ShiftExtend.HasExplicitAmount;
532 if (Kind == k_Register)
533 return Reg.ShiftExtend.HasExplicitAmount;
534 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000535 }
536
537 bool isImm() const override { return Kind == k_Immediate; }
538 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000539
540 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
541
Sander de Smalen50ded902018-04-29 17:33:38 +0000542 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
543 return isImmScaled<Bits, Scale>(true);
544 }
545
546 template <int Bits, int Scale> DiagnosticPredicate isUImmScaled() const {
547 return isImmScaled<Bits, Scale>(false);
548 }
549
Sander de Smalenfe17a782018-04-26 12:54:42 +0000550 template <int Bits, int Scale>
Sander de Smalen50ded902018-04-29 17:33:38 +0000551 DiagnosticPredicate isImmScaled(bool Signed) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000552 if (!isImm())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000553 return DiagnosticPredicateTy::NoMatch;
554
Tim Northover3b0846e2014-05-24 12:50:23 +0000555 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
556 if (!MCE)
Sander de Smalenfe17a782018-04-26 12:54:42 +0000557 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000558
Sander de Smalen50ded902018-04-29 17:33:38 +0000559 int64_t MinVal, MaxVal;
560 if (Signed) {
561 int64_t Shift = Bits - 1;
562 MinVal = (int64_t(1) << Shift) * -Scale;
563 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
564 } else {
565 MinVal = 0;
566 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
567 }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000568
Tim Northover3b0846e2014-05-24 12:50:23 +0000569 int64_t Val = MCE->getValue();
Sander de Smalenfe17a782018-04-26 12:54:42 +0000570 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
571 return DiagnosticPredicateTy::Match;
572
573 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +0000574 }
575
Sander de Smalen0325e302018-07-02 07:34:52 +0000576 DiagnosticPredicate isSVEPattern() const {
Sander de Smalen245e0e62018-01-22 10:46:00 +0000577 if (!isImm())
Sander de Smalen0325e302018-07-02 07:34:52 +0000578 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000579 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
580 if (!MCE)
Sander de Smalen0325e302018-07-02 07:34:52 +0000581 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000582 int64_t Val = MCE->getValue();
Sander de Smalen0325e302018-07-02 07:34:52 +0000583 if (Val >= 0 && Val < 32)
584 return DiagnosticPredicateTy::Match;
585 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000586 }
587
Tim Northover3b0846e2014-05-24 12:50:23 +0000588 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
589 AArch64MCExpr::VariantKind ELFRefKind;
590 MCSymbolRefExpr::VariantKind DarwinRefKind;
591 int64_t Addend;
592 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
593 Addend)) {
594 // If we don't understand the expression, assume the best and
595 // let the fixup and relocation code deal with it.
596 return true;
597 }
598
599 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
600 ELFRefKind == AArch64MCExpr::VK_LO12 ||
601 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
602 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
603 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
604 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
605 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
606 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000607 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
608 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
609 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000610 // Note that we don't range-check the addend. It's adjusted modulo page
611 // size when converted, so there is no "out of range" condition when using
612 // @pageoff.
613 return Addend >= 0 && (Addend % Scale) == 0;
614 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
615 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
616 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
617 return Addend == 0;
618 }
619
620 return false;
621 }
622
623 template <int Scale> bool isUImm12Offset() const {
624 if (!isImm())
625 return false;
626
627 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
628 if (!MCE)
629 return isSymbolicUImm12Offset(getImm(), Scale);
630
631 int64_t Val = MCE->getValue();
632 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
633 }
634
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000635 template <int N, int M>
636 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000637 if (!isImm())
638 return false;
639 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
640 if (!MCE)
641 return false;
642 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000643 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000644 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000645
Sander de Smalena1c259c2018-01-29 13:05:38 +0000646 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
647 // a logical immediate can always be represented when inverted.
648 template <typename T>
649 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000650 if (!isImm())
651 return false;
652 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
653 if (!MCE)
654 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000655
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000656 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000657 int64_t SVal = typename std::make_signed<T>::type(Val);
658 int64_t UVal = typename std::make_unsigned<T>::type(Val);
659 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000660 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000661
Sander de Smalena1c259c2018-01-29 13:05:38 +0000662 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000663 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000664
Tim Northover3b0846e2014-05-24 12:50:23 +0000665 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000666
Sander de Smalen62770792018-05-25 09:47:52 +0000667 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
668 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
669 /// immediate that can be shifted by 'Shift'.
670 template <unsigned Width>
671 Optional<std::pair<int64_t, unsigned> > getShiftedVal() const {
672 if (isShiftedImm() && Width == getShiftedImmShift())
673 if (auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
674 return std::make_pair(CE->getValue(), Width);
675
676 if (isImm())
677 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
678 int64_t Val = CE->getValue();
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000679 if ((Val != 0) && (uint64_t(Val >> Width) << Width) == uint64_t(Val))
Sander de Smalen62770792018-05-25 09:47:52 +0000680 return std::make_pair(Val >> Width, Width);
681 else
682 return std::make_pair(Val, 0u);
683 }
684
685 return {};
686 }
687
Tim Northover3b0846e2014-05-24 12:50:23 +0000688 bool isAddSubImm() const {
689 if (!isShiftedImm() && !isImm())
690 return false;
691
692 const MCExpr *Expr;
693
694 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
695 if (isShiftedImm()) {
696 unsigned Shift = ShiftedImm.ShiftAmount;
697 Expr = ShiftedImm.Val;
698 if (Shift != 0 && Shift != 12)
699 return false;
700 } else {
701 Expr = getImm();
702 }
703
704 AArch64MCExpr::VariantKind ELFRefKind;
705 MCSymbolRefExpr::VariantKind DarwinRefKind;
706 int64_t Addend;
707 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
708 DarwinRefKind, Addend)) {
709 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
710 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
711 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
712 || ELFRefKind == AArch64MCExpr::VK_LO12
713 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
714 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
715 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
716 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
717 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
718 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000719 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
720 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
721 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000722 }
723
Sander de Smalen98686c62018-05-29 10:39:49 +0000724 // If it's a constant, it should be a real immediate in range.
Sander de Smalen62770792018-05-25 09:47:52 +0000725 if (auto ShiftedVal = getShiftedVal<12>())
726 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
Diana Picusc93518d2016-10-11 09:17:47 +0000727
728 // If it's an expression, we hope for the best and let the fixup/relocation
729 // code deal with it.
730 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000731 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000732
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000733 bool isAddSubImmNeg() const {
734 if (!isShiftedImm() && !isImm())
735 return false;
736
Sander de Smalen98686c62018-05-29 10:39:49 +0000737 // Otherwise it should be a real negative immediate in range.
738 if (auto ShiftedVal = getShiftedVal<12>())
739 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000740
Sander de Smalen98686c62018-05-29 10:39:49 +0000741 return false;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000742 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000743
Sander de Smalen62770792018-05-25 09:47:52 +0000744 // Signed value in the range -128 to +127. For element widths of
745 // 16 bits or higher it may also be a signed multiple of 256 in the
746 // range -32768 to +32512.
747 // For element-width of 8 bits a range of -128 to 255 is accepted,
748 // since a copy of a byte can be either signed/unsigned.
749 template <typename T>
750 DiagnosticPredicate isSVECpyImm() const {
751 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
752 return DiagnosticPredicateTy::NoMatch;
753
754 bool IsByte =
755 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
756 if (auto ShiftedImm = getShiftedVal<8>())
757 if (!(IsByte && ShiftedImm->second) &&
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000758 AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
759 << ShiftedImm->second))
Sander de Smalen62770792018-05-25 09:47:52 +0000760 return DiagnosticPredicateTy::Match;
761
762 return DiagnosticPredicateTy::NearMatch;
763 }
764
Sander de Smalen98686c62018-05-29 10:39:49 +0000765 // Unsigned value in the range 0 to 255. For element widths of
766 // 16 bits or higher it may also be a signed multiple of 256 in the
767 // range 0 to 65280.
768 template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
769 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
770 return DiagnosticPredicateTy::NoMatch;
771
772 bool IsByte =
773 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
774 if (auto ShiftedImm = getShiftedVal<8>())
775 if (!(IsByte && ShiftedImm->second) &&
776 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
777 << ShiftedImm->second))
778 return DiagnosticPredicateTy::Match;
779
780 return DiagnosticPredicateTy::NearMatch;
781 }
782
Sander de Smalen97ca6b92018-06-01 07:25:46 +0000783 template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
784 if (isLogicalImm<T>() && !isSVECpyImm<T>())
785 return DiagnosticPredicateTy::Match;
786 return DiagnosticPredicateTy::NoMatch;
787 }
788
Tim Northover3b0846e2014-05-24 12:50:23 +0000789 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000790
Tim Northover3b0846e2014-05-24 12:50:23 +0000791 bool isSIMDImmType10() const {
792 if (!isImm())
793 return false;
794 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
795 if (!MCE)
796 return false;
797 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
798 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000799
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000800 template<int N>
801 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000802 if (!isImm())
803 return false;
804 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
805 if (!MCE)
806 return true;
807 int64_t Val = MCE->getValue();
808 if (Val & 0x3)
809 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000810 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
811 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000812 }
813
814 bool
815 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
816 if (!isImm())
817 return false;
818
819 AArch64MCExpr::VariantKind ELFRefKind;
820 MCSymbolRefExpr::VariantKind DarwinRefKind;
821 int64_t Addend;
822 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
823 DarwinRefKind, Addend)) {
824 return false;
825 }
826 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
827 return false;
828
829 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
830 if (ELFRefKind == AllowedModifiers[i])
831 return Addend == 0;
832 }
833
834 return false;
835 }
836
837 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000838 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000839 }
840
841 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000842 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
843 AArch64MCExpr::VK_TPREL_G2,
844 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000845 }
846
847 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000848 return isMovWSymbol({
849 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000850 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
851 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000852 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000853 }
854
855 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000856 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
857 AArch64MCExpr::VK_TPREL_G0,
858 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000859 }
860
861 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000862 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000863 }
864
865 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000866 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000867 }
868
869 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000870 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
871 AArch64MCExpr::VK_TPREL_G1_NC,
872 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000873 }
874
875 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000876 return isMovWSymbol(
877 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
878 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000879 }
880
881 template<int RegWidth, int Shift>
882 bool isMOVZMovAlias() const {
883 if (!isImm()) return false;
884
885 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
886 if (!CE) return false;
887 uint64_t Value = CE->getValue();
888
Tim Northoverdaa1c012016-06-16 01:42:25 +0000889 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000890 }
891
892 template<int RegWidth, int Shift>
893 bool isMOVNMovAlias() const {
894 if (!isImm()) return false;
895
896 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
897 if (!CE) return false;
898 uint64_t Value = CE->getValue();
899
Tim Northoverdaa1c012016-06-16 01:42:25 +0000900 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000901 }
902
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000903 bool isFPImm() const {
904 return Kind == k_FPImm &&
905 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt()) != -1;
906 }
907
Tim Northover3b0846e2014-05-24 12:50:23 +0000908 bool isBarrier() const { return Kind == k_Barrier; }
909 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000910
Tim Northover3b0846e2014-05-24 12:50:23 +0000911 bool isMRSSystemRegister() const {
912 if (!isSysReg()) return false;
913
Tim Northover7cd58932015-01-22 17:23:04 +0000914 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000915 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000916
Tim Northover3b0846e2014-05-24 12:50:23 +0000917 bool isMSRSystemRegister() const {
918 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000919 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000920 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000921
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000922 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000923 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000924 return (SysReg.PStateField == AArch64PState::PAN ||
Sjoerd Meijer173b7f02018-07-03 12:09:20 +0000925 SysReg.PStateField == AArch64PState::DIT ||
Oliver Stannard911ea202015-11-26 15:32:30 +0000926 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000927 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000928
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000929 bool isSystemPStateFieldWithImm0_15() const {
930 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000931 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000932 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000933
Florian Hahnc4422242017-11-07 13:07:50 +0000934 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000935 return Kind == k_Register;
936 }
937
938 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000939 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
940 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000941
Florian Hahnc4422242017-11-07 13:07:50 +0000942 bool isNeonVectorReg() const {
943 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
944 }
945
946 bool isNeonVectorRegLo() const {
947 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000948 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
949 Reg.RegNum);
950 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000951
Sander de Smalencd6be962017-12-20 11:02:42 +0000952 template <unsigned Class> bool isSVEVectorReg() const {
953 RegKind RK;
954 switch (Class) {
955 case AArch64::ZPRRegClassID:
Sander de Smalen8cd1f532018-07-03 15:31:04 +0000956 case AArch64::ZPR_3bRegClassID:
957 case AArch64::ZPR_4bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000958 RK = RegKind::SVEDataVector;
959 break;
960 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000961 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000962 RK = RegKind::SVEPredicateVector;
963 break;
964 default:
965 llvm_unreachable("Unsupport register class");
966 }
967
968 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000969 AArch64MCRegisterClasses[Class].contains(getReg());
970 }
971
Sander de Smalenfd54a782018-06-04 07:07:35 +0000972 template <unsigned Class> bool isFPRasZPR() const {
973 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
974 AArch64MCRegisterClasses[Class].contains(getReg());
975 }
976
Sander de Smalencd6be962017-12-20 11:02:42 +0000977 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +0000978 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
979 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
980 return DiagnosticPredicateTy::NoMatch;
981
982 if (isSVEVectorReg<Class>() &&
983 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
984 return DiagnosticPredicateTy::Match;
985
986 return DiagnosticPredicateTy::NearMatch;
987 }
988
989 template <int ElementWidth, unsigned Class>
990 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
991 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
992 return DiagnosticPredicateTy::NoMatch;
993
994 if (isSVEVectorReg<Class>() &&
995 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
996 return DiagnosticPredicateTy::Match;
997
998 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +0000999 }
1000
Sander de Smaleneb896b12018-04-25 09:26:47 +00001001 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +00001002 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
1003 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +00001004 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
1005 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
1006 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001007 return DiagnosticPredicateTy::NoMatch;
1008
Sander de Smalen5861c262018-04-30 07:24:38 +00001009 // Give a more specific diagnostic when the user has explicitly typed in
1010 // a shift-amount that does not match what is expected, but for which
1011 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
1012 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
1013 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
1014 ShiftExtendTy == AArch64_AM::SXTW) &&
1015 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
1016 return DiagnosticPredicateTy::NoMatch;
1017
1018 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001019 return DiagnosticPredicateTy::Match;
1020
1021 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +00001022 }
1023
Tim Northover3b0846e2014-05-24 12:50:23 +00001024 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001025 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001026 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
1027 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001028
Sander de Smalen0325e302018-07-02 07:34:52 +00001029 bool isGPR64as32() const {
1030 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1031 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(Reg.RegNum);
1032 }
1033
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001034 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001035 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001036 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
1037 Reg.RegNum);
1038 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001039
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001040 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001041 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001042 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1043 Reg.RegNum);
1044 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001045
Sam Parker5f934642017-08-31 09:27:04 +00001046 template<int64_t Angle, int64_t Remainder>
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001047 DiagnosticPredicate isComplexRotation() const {
1048 if (!isImm()) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001049
1050 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001051 if (!CE) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001052 uint64_t Value = CE->getValue();
1053
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001054 if (Value % Angle == Remainder && Value <= 270)
1055 return DiagnosticPredicateTy::Match;
1056 return DiagnosticPredicateTy::NearMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001057 }
1058
Sander de Smalen149916d2018-04-20 07:24:20 +00001059 template <unsigned RegClassID> bool isGPR64() const {
1060 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1061 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1062 }
1063
1064 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001065 DiagnosticPredicate isGPR64WithShiftExtend() const {
1066 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1067 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001068
Sander de Smalenfe17a782018-04-26 12:54:42 +00001069 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1070 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1071 return DiagnosticPredicateTy::Match;
1072 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001073 }
1074
Tim Northover3b0846e2014-05-24 12:50:23 +00001075 /// Is this a vector list with the type implicit (presumably attached to the
1076 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001077 template <RegKind VectorKind, unsigned NumRegs>
1078 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001079 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001080 VectorList.NumElements == 0 &&
1081 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001082 }
1083
Sander de Smalen650234b2018-04-12 11:40:52 +00001084 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1085 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001086 bool isTypedVectorList() const {
1087 if (Kind != k_VectorList)
1088 return false;
1089 if (VectorList.Count != NumRegs)
1090 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001091 if (VectorList.RegisterKind != VectorKind)
1092 return false;
1093 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001094 return false;
1095 return VectorList.NumElements == NumElements;
1096 }
1097
Sander de Smalenc33d6682018-06-04 06:40:55 +00001098 template <int Min, int Max>
1099 DiagnosticPredicate isVectorIndex() const {
1100 if (Kind != k_VectorIndex)
1101 return DiagnosticPredicateTy::NoMatch;
1102 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1103 return DiagnosticPredicateTy::Match;
1104 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001105 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001106
Tim Northover3b0846e2014-05-24 12:50:23 +00001107 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001108
Tim Northover3b0846e2014-05-24 12:50:23 +00001109 bool isTokenEqual(StringRef Str) const {
1110 return Kind == k_Token && getToken() == Str;
1111 }
1112 bool isSysCR() const { return Kind == k_SysCR; }
1113 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001114 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001115 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1116 bool isShifter() const {
1117 if (!isShiftExtend())
1118 return false;
1119
1120 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1121 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1122 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1123 ST == AArch64_AM::MSL);
1124 }
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001125
1126 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1127 if (Kind != k_FPImm)
1128 return DiagnosticPredicateTy::NoMatch;
1129
1130 if (getFPImmIsExact()) {
1131 // Lookup the immediate from table of supported immediates.
1132 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1133 assert(Desc && "Unknown enum value");
1134
1135 // Calculate its FP value.
1136 APFloat RealVal(APFloat::IEEEdouble());
1137 if (RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero) !=
1138 APFloat::opOK)
1139 llvm_unreachable("FP immediate is not exact");
1140
1141 if (getFPImm().bitwiseIsEqual(RealVal))
1142 return DiagnosticPredicateTy::Match;
1143 }
1144
1145 return DiagnosticPredicateTy::NearMatch;
1146 }
1147
1148 template <unsigned ImmA, unsigned ImmB>
1149 DiagnosticPredicate isExactFPImm() const {
1150 DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1151 if ((Res = isExactFPImm<ImmA>()))
1152 return DiagnosticPredicateTy::Match;
1153 if ((Res = isExactFPImm<ImmB>()))
1154 return DiagnosticPredicateTy::Match;
1155 return Res;
1156 }
1157
Tim Northover3b0846e2014-05-24 12:50:23 +00001158 bool isExtend() const {
1159 if (!isShiftExtend())
1160 return false;
1161
1162 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1163 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1164 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1165 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1166 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1167 ET == AArch64_AM::LSL) &&
1168 getShiftExtendAmount() <= 4;
1169 }
1170
1171 bool isExtend64() const {
1172 if (!isExtend())
1173 return false;
1174 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1175 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1176 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1177 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001178
Tim Northover3b0846e2014-05-24 12:50:23 +00001179 bool isExtendLSL64() const {
1180 if (!isExtend())
1181 return false;
1182 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1183 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1184 ET == AArch64_AM::LSL) &&
1185 getShiftExtendAmount() <= 4;
1186 }
1187
1188 template<int Width> bool isMemXExtend() const {
1189 if (!isExtend())
1190 return false;
1191 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1192 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1193 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1194 getShiftExtendAmount() == 0);
1195 }
1196
1197 template<int Width> bool isMemWExtend() const {
1198 if (!isExtend())
1199 return false;
1200 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1201 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1202 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1203 getShiftExtendAmount() == 0);
1204 }
1205
1206 template <unsigned width>
1207 bool isArithmeticShifter() const {
1208 if (!isShifter())
1209 return false;
1210
1211 // An arithmetic shifter is LSL, LSR, or ASR.
1212 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1213 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1214 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1215 }
1216
1217 template <unsigned width>
1218 bool isLogicalShifter() const {
1219 if (!isShifter())
1220 return false;
1221
1222 // A logical shifter is LSL, LSR, ASR or ROR.
1223 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1224 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1225 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1226 getShiftExtendAmount() < width;
1227 }
1228
1229 bool isMovImm32Shifter() const {
1230 if (!isShifter())
1231 return false;
1232
1233 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1234 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1235 if (ST != AArch64_AM::LSL)
1236 return false;
1237 uint64_t Val = getShiftExtendAmount();
1238 return (Val == 0 || Val == 16);
1239 }
1240
1241 bool isMovImm64Shifter() const {
1242 if (!isShifter())
1243 return false;
1244
1245 // A MOVi shifter is LSL of 0 or 16.
1246 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1247 if (ST != AArch64_AM::LSL)
1248 return false;
1249 uint64_t Val = getShiftExtendAmount();
1250 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1251 }
1252
1253 bool isLogicalVecShifter() const {
1254 if (!isShifter())
1255 return false;
1256
1257 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1258 unsigned Shift = getShiftExtendAmount();
1259 return getShiftExtendType() == AArch64_AM::LSL &&
1260 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1261 }
1262
1263 bool isLogicalVecHalfWordShifter() const {
1264 if (!isLogicalVecShifter())
1265 return false;
1266
1267 // A logical vector shifter is a left shift by 0 or 8.
1268 unsigned Shift = getShiftExtendAmount();
1269 return getShiftExtendType() == AArch64_AM::LSL &&
1270 (Shift == 0 || Shift == 8);
1271 }
1272
1273 bool isMoveVecShifter() const {
1274 if (!isShiftExtend())
1275 return false;
1276
1277 // A logical vector shifter is a left shift by 8 or 16.
1278 unsigned Shift = getShiftExtendAmount();
1279 return getShiftExtendType() == AArch64_AM::MSL &&
1280 (Shift == 8 || Shift == 16);
1281 }
1282
1283 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1284 // to LDUR/STUR when the offset is not legal for the former but is for
1285 // the latter. As such, in addition to checking for being a legal unscaled
1286 // address, also check that it is not a legal scaled address. This avoids
1287 // ambiguity in the matcher.
1288 template<int Width>
1289 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001290 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001291 }
1292
1293 bool isAdrpLabel() const {
1294 // Validation was handled during parsing, so we just sanity check that
1295 // something didn't go haywire.
1296 if (!isImm())
1297 return false;
1298
1299 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1300 int64_t Val = CE->getValue();
1301 int64_t Min = - (4096 * (1LL << (21 - 1)));
1302 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1303 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1304 }
1305
1306 return true;
1307 }
1308
1309 bool isAdrLabel() const {
1310 // Validation was handled during parsing, so we just sanity check that
1311 // something didn't go haywire.
1312 if (!isImm())
1313 return false;
1314
1315 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1316 int64_t Val = CE->getValue();
1317 int64_t Min = - (1LL << (21 - 1));
1318 int64_t Max = ((1LL << (21 - 1)) - 1);
1319 return Val >= Min && Val <= Max;
1320 }
1321
1322 return true;
1323 }
1324
1325 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1326 // Add as immediates when possible. Null MCExpr = 0.
1327 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001328 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001329 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001330 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001331 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001332 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001333 }
1334
1335 void addRegOperands(MCInst &Inst, unsigned N) const {
1336 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001337 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001338 }
1339
1340 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1341 assert(N == 1 && "Invalid number of operands!");
1342 assert(
1343 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1344
1345 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1346 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1347 RI->getEncodingValue(getReg()));
1348
Jim Grosbache9119e42015-05-13 18:37:00 +00001349 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001350 }
1351
Sander de Smalen0325e302018-07-02 07:34:52 +00001352 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1353 assert(N == 1 && "Invalid number of operands!");
1354 assert(
1355 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(getReg()));
1356
1357 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1358 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID).getRegister(
1359 RI->getEncodingValue(getReg()));
1360
1361 Inst.addOperand(MCOperand::createReg(Reg));
1362 }
1363
Sander de Smalenfd54a782018-06-04 07:07:35 +00001364 template <int Width>
1365 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1366 unsigned Base;
1367 switch (Width) {
1368 case 8: Base = AArch64::B0; break;
1369 case 16: Base = AArch64::H0; break;
1370 case 32: Base = AArch64::S0; break;
1371 case 64: Base = AArch64::D0; break;
1372 case 128: Base = AArch64::Q0; break;
1373 default:
1374 llvm_unreachable("Unsupported width");
1375 }
1376 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1377 }
1378
Tim Northover3b0846e2014-05-24 12:50:23 +00001379 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1380 assert(N == 1 && "Invalid number of operands!");
1381 assert(
1382 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001383 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001384 }
1385
1386 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1387 assert(N == 1 && "Invalid number of operands!");
1388 assert(
1389 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001390 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001391 }
1392
1393 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1394 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001395 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001396 }
1397
Sander de Smalen525e3222018-04-12 13:19:32 +00001398 enum VecListIndexType {
1399 VecListIdx_DReg = 0,
1400 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001401 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001402 };
1403
1404 template <VecListIndexType RegTy, unsigned NumRegs>
1405 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001406 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001407 static const unsigned FirstRegs[][5] = {
1408 /* DReg */ { AArch64::Q0,
1409 AArch64::D0, AArch64::D0_D1,
1410 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1411 /* QReg */ { AArch64::Q0,
1412 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001413 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1414 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001415 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001416 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001417 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001418
Sander de Smalen7a210db2018-04-16 10:46:18 +00001419 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1420 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001421
Sander de Smalen525e3222018-04-12 13:19:32 +00001422 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1423 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1424 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001425 }
1426
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001427 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001428 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001429 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001430 }
1431
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001432 template <unsigned ImmIs0, unsigned ImmIs1>
1433 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1434 assert(N == 1 && "Invalid number of operands!");
1435 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1436 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1437 }
1438
Tim Northover3b0846e2014-05-24 12:50:23 +00001439 void addImmOperands(MCInst &Inst, unsigned N) const {
1440 assert(N == 1 && "Invalid number of operands!");
1441 // If this is a pageoff symrefexpr with an addend, adjust the addend
1442 // to be only the page-offset portion. Otherwise, just add the expr
1443 // as-is.
1444 addExpr(Inst, getImm());
1445 }
1446
Sander de Smalen62770792018-05-25 09:47:52 +00001447 template <int Shift>
1448 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001449 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001450 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1451 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1452 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1453 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001454 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001455 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001456 } else {
1457 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001458 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001459 }
1460 }
1461
Sander de Smalen62770792018-05-25 09:47:52 +00001462 template <int Shift>
1463 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001464 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001465 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1466 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1467 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1468 } else
1469 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001470 }
1471
Tim Northover3b0846e2014-05-24 12:50:23 +00001472 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1473 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001474 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001475 }
1476
1477 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1478 assert(N == 1 && "Invalid number of operands!");
1479 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1480 if (!MCE)
1481 addExpr(Inst, getImm());
1482 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001483 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001484 }
1485
1486 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1487 addImmOperands(Inst, N);
1488 }
1489
1490 template<int Scale>
1491 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1492 assert(N == 1 && "Invalid number of operands!");
1493 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1494
1495 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001496 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001497 return;
1498 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001499 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001500 }
1501
Sander de Smalen5c625982018-04-13 12:56:14 +00001502 template <int Scale>
1503 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1504 assert(N == 1 && "Invalid number of operands!");
1505 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1506 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1507 }
1508
Sander de Smalena1c259c2018-01-29 13:05:38 +00001509 template <typename T>
1510 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001511 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001512 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001513 typename std::make_unsigned<T>::type Val = MCE->getValue();
1514 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001515 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001516 }
1517
Sander de Smalena1c259c2018-01-29 13:05:38 +00001518 template <typename T>
1519 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001520 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001521 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001522 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1523 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001524 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001525 }
1526
Tim Northover3b0846e2014-05-24 12:50:23 +00001527 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1528 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001529 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001530 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001531 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001532 }
1533
1534 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1535 // Branch operands don't encode the low bits, so shift them off
1536 // here. If it's a label, however, just put it on directly as there's
1537 // not enough information now to do anything.
1538 assert(N == 1 && "Invalid number of operands!");
1539 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1540 if (!MCE) {
1541 addExpr(Inst, getImm());
1542 return;
1543 }
1544 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001545 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001546 }
1547
1548 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1549 // Branch operands don't encode the low bits, so shift them off
1550 // here. If it's a label, however, just put it on directly as there's
1551 // not enough information now to do anything.
1552 assert(N == 1 && "Invalid number of operands!");
1553 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1554 if (!MCE) {
1555 addExpr(Inst, getImm());
1556 return;
1557 }
1558 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001559 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001560 }
1561
1562 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1563 // Branch operands don't encode the low bits, so shift them off
1564 // here. If it's a label, however, just put it on directly as there's
1565 // not enough information now to do anything.
1566 assert(N == 1 && "Invalid number of operands!");
1567 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1568 if (!MCE) {
1569 addExpr(Inst, getImm());
1570 return;
1571 }
1572 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001573 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001574 }
1575
1576 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1577 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001578 Inst.addOperand(MCOperand::createImm(
1579 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
Tim Northover3b0846e2014-05-24 12:50:23 +00001580 }
1581
1582 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1583 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001584 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001585 }
1586
1587 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1588 assert(N == 1 && "Invalid number of operands!");
1589
Jim Grosbache9119e42015-05-13 18:37:00 +00001590 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001591 }
1592
1593 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1594 assert(N == 1 && "Invalid number of operands!");
1595
Jim Grosbache9119e42015-05-13 18:37:00 +00001596 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001597 }
1598
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001599 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1600 assert(N == 1 && "Invalid number of operands!");
1601
1602 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1603 }
1604
1605 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001606 assert(N == 1 && "Invalid number of operands!");
1607
Jim Grosbache9119e42015-05-13 18:37:00 +00001608 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001609 }
1610
1611 void addSysCROperands(MCInst &Inst, unsigned N) const {
1612 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001613 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001614 }
1615
1616 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1617 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001618 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001619 }
1620
Oliver Stannarda34e4702015-12-01 10:48:51 +00001621 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1622 assert(N == 1 && "Invalid number of operands!");
1623 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1624 }
1625
Tim Northover3b0846e2014-05-24 12:50:23 +00001626 void addShifterOperands(MCInst &Inst, unsigned N) const {
1627 assert(N == 1 && "Invalid number of operands!");
1628 unsigned Imm =
1629 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001630 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001631 }
1632
1633 void addExtendOperands(MCInst &Inst, unsigned N) const {
1634 assert(N == 1 && "Invalid number of operands!");
1635 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1636 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1637 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001638 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001639 }
1640
1641 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1642 assert(N == 1 && "Invalid number of operands!");
1643 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1644 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1645 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001646 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001647 }
1648
1649 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1650 assert(N == 2 && "Invalid number of operands!");
1651 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1652 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001653 Inst.addOperand(MCOperand::createImm(IsSigned));
1654 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001655 }
1656
1657 // For 8-bit load/store instructions with a register offset, both the
1658 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1659 // they're disambiguated by whether the shift was explicit or implicit rather
1660 // than its size.
1661 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1662 assert(N == 2 && "Invalid number of operands!");
1663 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1664 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001665 Inst.addOperand(MCOperand::createImm(IsSigned));
1666 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001667 }
1668
1669 template<int Shift>
1670 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1671 assert(N == 1 && "Invalid number of operands!");
1672
1673 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1674 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001675 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001676 }
1677
1678 template<int Shift>
1679 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1680 assert(N == 1 && "Invalid number of operands!");
1681
1682 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1683 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001684 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001685 }
1686
Sam Parker5f934642017-08-31 09:27:04 +00001687 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1688 assert(N == 1 && "Invalid number of operands!");
1689 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1690 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1691 }
1692
1693 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1694 assert(N == 1 && "Invalid number of operands!");
1695 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1696 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1697 }
1698
Tim Northover3b0846e2014-05-24 12:50:23 +00001699 void print(raw_ostream &OS) const override;
1700
David Blaikie960ea3f2014-06-08 16:18:35 +00001701 static std::unique_ptr<AArch64Operand>
1702 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1703 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001704 Op->Tok.Data = Str.data();
1705 Op->Tok.Length = Str.size();
1706 Op->Tok.IsSuffix = IsSuffix;
1707 Op->StartLoc = S;
1708 Op->EndLoc = S;
1709 return Op;
1710 }
1711
David Blaikie960ea3f2014-06-08 16:18:35 +00001712 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001713 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
Sander de Smalen0325e302018-07-02 07:34:52 +00001714 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
Sander de Smalen149916d2018-04-20 07:24:20 +00001715 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1716 unsigned ShiftAmount = 0,
1717 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001718 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001719 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001720 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001721 Op->Reg.ElementWidth = 0;
Sander de Smalen0325e302018-07-02 07:34:52 +00001722 Op->Reg.EqualityTy = EqTy;
Sander de Smalen149916d2018-04-20 07:24:20 +00001723 Op->Reg.ShiftExtend.Type = ExtTy;
1724 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1725 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001726 Op->StartLoc = S;
1727 Op->EndLoc = E;
1728 return Op;
1729 }
1730
David Blaikie960ea3f2014-06-08 16:18:35 +00001731 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001732 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001733 SMLoc S, SMLoc E, MCContext &Ctx,
1734 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1735 unsigned ShiftAmount = 0,
1736 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001737 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1738 Kind == RegKind::SVEPredicateVector) &&
1739 "Invalid vector kind");
Sander de Smalen0325e302018-07-02 07:34:52 +00001740 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
Sander de Smalen149916d2018-04-20 07:24:20 +00001741 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001742 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001743 return Op;
1744 }
1745
1746 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001747 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001748 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1749 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001750 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001751 Op->VectorList.RegNum = RegNum;
1752 Op->VectorList.Count = Count;
1753 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001754 Op->VectorList.ElementWidth = ElementWidth;
1755 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001756 Op->StartLoc = S;
1757 Op->EndLoc = E;
1758 return Op;
1759 }
1760
David Blaikie960ea3f2014-06-08 16:18:35 +00001761 static std::unique_ptr<AArch64Operand>
1762 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1763 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001764 Op->VectorIndex.Val = Idx;
1765 Op->StartLoc = S;
1766 Op->EndLoc = E;
1767 return Op;
1768 }
1769
David Blaikie960ea3f2014-06-08 16:18:35 +00001770 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1771 SMLoc E, MCContext &Ctx) {
1772 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001773 Op->Imm.Val = Val;
1774 Op->StartLoc = S;
1775 Op->EndLoc = E;
1776 return Op;
1777 }
1778
David Blaikie960ea3f2014-06-08 16:18:35 +00001779 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1780 unsigned ShiftAmount,
1781 SMLoc S, SMLoc E,
1782 MCContext &Ctx) {
1783 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001784 Op->ShiftedImm .Val = Val;
1785 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1786 Op->StartLoc = S;
1787 Op->EndLoc = E;
1788 return Op;
1789 }
1790
David Blaikie960ea3f2014-06-08 16:18:35 +00001791 static std::unique_ptr<AArch64Operand>
1792 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1793 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001794 Op->CondCode.Code = Code;
1795 Op->StartLoc = S;
1796 Op->EndLoc = E;
1797 return Op;
1798 }
1799
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001800 static std::unique_ptr<AArch64Operand>
1801 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001802 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001803 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
1804 Op->FPImm.IsExact = IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +00001805 Op->StartLoc = S;
1806 Op->EndLoc = S;
1807 return Op;
1808 }
1809
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001810 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1811 StringRef Str,
1812 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001813 MCContext &Ctx) {
1814 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001815 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001816 Op->Barrier.Data = Str.data();
1817 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001818 Op->StartLoc = S;
1819 Op->EndLoc = S;
1820 return Op;
1821 }
1822
Tim Northover7cd58932015-01-22 17:23:04 +00001823 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1824 uint32_t MRSReg,
1825 uint32_t MSRReg,
1826 uint32_t PStateField,
1827 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001828 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001829 Op->SysReg.Data = Str.data();
1830 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001831 Op->SysReg.MRSReg = MRSReg;
1832 Op->SysReg.MSRReg = MSRReg;
1833 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001834 Op->StartLoc = S;
1835 Op->EndLoc = S;
1836 return Op;
1837 }
1838
David Blaikie960ea3f2014-06-08 16:18:35 +00001839 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1840 SMLoc E, MCContext &Ctx) {
1841 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001842 Op->SysCRImm.Val = Val;
1843 Op->StartLoc = S;
1844 Op->EndLoc = E;
1845 return Op;
1846 }
1847
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001848 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1849 StringRef Str,
1850 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001851 MCContext &Ctx) {
1852 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001853 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001854 Op->Barrier.Data = Str.data();
1855 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001856 Op->StartLoc = S;
1857 Op->EndLoc = S;
1858 return Op;
1859 }
1860
Oliver Stannarda34e4702015-12-01 10:48:51 +00001861 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1862 StringRef Str,
1863 SMLoc S,
1864 MCContext &Ctx) {
1865 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1866 Op->PSBHint.Val = Val;
1867 Op->PSBHint.Data = Str.data();
1868 Op->PSBHint.Length = Str.size();
1869 Op->StartLoc = S;
1870 Op->EndLoc = S;
1871 return Op;
1872 }
1873
David Blaikie960ea3f2014-06-08 16:18:35 +00001874 static std::unique_ptr<AArch64Operand>
1875 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1876 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1877 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001878 Op->ShiftExtend.Type = ShOp;
1879 Op->ShiftExtend.Amount = Val;
1880 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1881 Op->StartLoc = S;
1882 Op->EndLoc = E;
1883 return Op;
1884 }
1885};
1886
1887} // end anonymous namespace.
1888
1889void AArch64Operand::print(raw_ostream &OS) const {
1890 switch (Kind) {
1891 case k_FPImm:
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001892 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
1893 if (!getFPImmIsExact())
1894 OS << " (inexact)";
1895 OS << ">";
Tim Northover3b0846e2014-05-24 12:50:23 +00001896 break;
1897 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001898 StringRef Name = getBarrierName();
1899 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001900 OS << "<barrier " << Name << ">";
1901 else
1902 OS << "<barrier invalid #" << getBarrier() << ">";
1903 break;
1904 }
1905 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001906 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001907 break;
1908 case k_ShiftedImm: {
1909 unsigned Shift = getShiftedImmShift();
1910 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001911 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001912 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1913 break;
1914 }
1915 case k_CondCode:
1916 OS << "<condcode " << getCondCode() << ">";
1917 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001918 case k_VectorList: {
1919 OS << "<vectorlist ";
1920 unsigned Reg = getVectorListStart();
1921 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1922 OS << Reg + i << " ";
1923 OS << ">";
1924 break;
1925 }
1926 case k_VectorIndex:
1927 OS << "<vectorindex " << getVectorIndex() << ">";
1928 break;
1929 case k_SysReg:
1930 OS << "<sysreg: " << getSysReg() << '>';
1931 break;
1932 case k_Token:
1933 OS << "'" << getToken() << "'";
1934 break;
1935 case k_SysCR:
1936 OS << "c" << getSysCR();
1937 break;
1938 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001939 StringRef Name = getPrefetchName();
1940 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001941 OS << "<prfop " << Name << ">";
1942 else
1943 OS << "<prfop invalid #" << getPrefetch() << ">";
1944 break;
1945 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001946 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001947 OS << getPSBHintName();
1948 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00001949 case k_Register:
1950 OS << "<register " << getReg() << ">";
1951 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
1952 break;
1953 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001954 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001955 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1956 << getShiftExtendAmount();
1957 if (!hasShiftExtendAmount())
1958 OS << "<imp>";
1959 OS << '>';
1960 break;
1961 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001962}
1963
1964/// @name Auto-generated Match Functions
1965/// {
1966
1967static unsigned MatchRegisterName(StringRef Name);
1968
1969/// }
1970
Florian Hahnc4422242017-11-07 13:07:50 +00001971static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001972 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001973 .Case("v0", AArch64::Q0)
1974 .Case("v1", AArch64::Q1)
1975 .Case("v2", AArch64::Q2)
1976 .Case("v3", AArch64::Q3)
1977 .Case("v4", AArch64::Q4)
1978 .Case("v5", AArch64::Q5)
1979 .Case("v6", AArch64::Q6)
1980 .Case("v7", AArch64::Q7)
1981 .Case("v8", AArch64::Q8)
1982 .Case("v9", AArch64::Q9)
1983 .Case("v10", AArch64::Q10)
1984 .Case("v11", AArch64::Q11)
1985 .Case("v12", AArch64::Q12)
1986 .Case("v13", AArch64::Q13)
1987 .Case("v14", AArch64::Q14)
1988 .Case("v15", AArch64::Q15)
1989 .Case("v16", AArch64::Q16)
1990 .Case("v17", AArch64::Q17)
1991 .Case("v18", AArch64::Q18)
1992 .Case("v19", AArch64::Q19)
1993 .Case("v20", AArch64::Q20)
1994 .Case("v21", AArch64::Q21)
1995 .Case("v22", AArch64::Q22)
1996 .Case("v23", AArch64::Q23)
1997 .Case("v24", AArch64::Q24)
1998 .Case("v25", AArch64::Q25)
1999 .Case("v26", AArch64::Q26)
2000 .Case("v27", AArch64::Q27)
2001 .Case("v28", AArch64::Q28)
2002 .Case("v29", AArch64::Q29)
2003 .Case("v30", AArch64::Q30)
2004 .Case("v31", AArch64::Q31)
2005 .Default(0);
2006}
2007
Sander de Smalen73937b72018-04-11 07:36:10 +00002008/// Returns an optional pair of (#elements, element-width) if Suffix
2009/// is a valid vector kind. Where the number of elements in a vector
2010/// or the vector width is implicit or explicitly unknown (but still a
2011/// valid suffix kind), 0 is used.
2012static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2013 RegKind VectorKind) {
2014 std::pair<int, int> Res = {-1, -1};
2015
2016 switch (VectorKind) {
2017 case RegKind::NeonVector:
2018 Res =
2019 StringSwitch<std::pair<int, int>>(Suffix.lower())
2020 .Case("", {0, 0})
2021 .Case(".1d", {1, 64})
2022 .Case(".1q", {1, 128})
2023 // '.2h' needed for fp16 scalar pairwise reductions
2024 .Case(".2h", {2, 16})
2025 .Case(".2s", {2, 32})
2026 .Case(".2d", {2, 64})
2027 // '.4b' is another special case for the ARMv8.2a dot product
2028 // operand
2029 .Case(".4b", {4, 8})
2030 .Case(".4h", {4, 16})
2031 .Case(".4s", {4, 32})
2032 .Case(".8b", {8, 8})
2033 .Case(".8h", {8, 16})
2034 .Case(".16b", {16, 8})
2035 // Accept the width neutral ones, too, for verbose syntax. If those
2036 // aren't used in the right places, the token operand won't match so
2037 // all will work out.
2038 .Case(".b", {0, 8})
2039 .Case(".h", {0, 16})
2040 .Case(".s", {0, 32})
2041 .Case(".d", {0, 64})
2042 .Default({-1, -1});
2043 break;
2044 case RegKind::SVEPredicateVector:
2045 case RegKind::SVEDataVector:
2046 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2047 .Case("", {0, 0})
2048 .Case(".b", {0, 8})
2049 .Case(".h", {0, 16})
2050 .Case(".s", {0, 32})
2051 .Case(".d", {0, 64})
2052 .Case(".q", {0, 128})
2053 .Default({-1, -1});
2054 break;
2055 default:
2056 llvm_unreachable("Unsupported RegKind");
2057 }
2058
2059 if (Res == std::make_pair(-1, -1))
2060 return Optional<std::pair<int, int>>();
2061
2062 return Optional<std::pair<int, int>>(Res);
2063}
2064
2065static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2066 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002067}
2068
Florian Hahn91f11e52017-11-07 16:45:48 +00002069static unsigned matchSVEDataVectorRegName(StringRef Name) {
2070 return StringSwitch<unsigned>(Name.lower())
2071 .Case("z0", AArch64::Z0)
2072 .Case("z1", AArch64::Z1)
2073 .Case("z2", AArch64::Z2)
2074 .Case("z3", AArch64::Z3)
2075 .Case("z4", AArch64::Z4)
2076 .Case("z5", AArch64::Z5)
2077 .Case("z6", AArch64::Z6)
2078 .Case("z7", AArch64::Z7)
2079 .Case("z8", AArch64::Z8)
2080 .Case("z9", AArch64::Z9)
2081 .Case("z10", AArch64::Z10)
2082 .Case("z11", AArch64::Z11)
2083 .Case("z12", AArch64::Z12)
2084 .Case("z13", AArch64::Z13)
2085 .Case("z14", AArch64::Z14)
2086 .Case("z15", AArch64::Z15)
2087 .Case("z16", AArch64::Z16)
2088 .Case("z17", AArch64::Z17)
2089 .Case("z18", AArch64::Z18)
2090 .Case("z19", AArch64::Z19)
2091 .Case("z20", AArch64::Z20)
2092 .Case("z21", AArch64::Z21)
2093 .Case("z22", AArch64::Z22)
2094 .Case("z23", AArch64::Z23)
2095 .Case("z24", AArch64::Z24)
2096 .Case("z25", AArch64::Z25)
2097 .Case("z26", AArch64::Z26)
2098 .Case("z27", AArch64::Z27)
2099 .Case("z28", AArch64::Z28)
2100 .Case("z29", AArch64::Z29)
2101 .Case("z30", AArch64::Z30)
2102 .Case("z31", AArch64::Z31)
2103 .Default(0);
2104}
2105
Sander de Smalencd6be962017-12-20 11:02:42 +00002106static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2107 return StringSwitch<unsigned>(Name.lower())
2108 .Case("p0", AArch64::P0)
2109 .Case("p1", AArch64::P1)
2110 .Case("p2", AArch64::P2)
2111 .Case("p3", AArch64::P3)
2112 .Case("p4", AArch64::P4)
2113 .Case("p5", AArch64::P5)
2114 .Case("p6", AArch64::P6)
2115 .Case("p7", AArch64::P7)
2116 .Case("p8", AArch64::P8)
2117 .Case("p9", AArch64::P9)
2118 .Case("p10", AArch64::P10)
2119 .Case("p11", AArch64::P11)
2120 .Case("p12", AArch64::P12)
2121 .Case("p13", AArch64::P13)
2122 .Case("p14", AArch64::P14)
2123 .Case("p15", AArch64::P15)
2124 .Default(0);
2125}
2126
Tim Northover3b0846e2014-05-24 12:50:23 +00002127bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2128 SMLoc &EndLoc) {
2129 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002130 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002131 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002132 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002133}
2134
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002135// Matches a register name or register alias previously defined by '.req'
2136unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002137 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002138 unsigned RegNum = 0;
2139 if ((RegNum = matchSVEDataVectorRegName(Name)))
2140 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2141
Sander de Smalencd6be962017-12-20 11:02:42 +00002142 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2143 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2144
Sander de Smalenc067c302017-12-20 09:45:45 +00002145 if ((RegNum = MatchNeonVectorRegName(Name)))
2146 return Kind == RegKind::NeonVector ? RegNum : 0;
2147
2148 // The parsed register must be of RegKind Scalar
2149 if ((RegNum = MatchRegisterName(Name)))
2150 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002151
Florian Hahnc4422242017-11-07 13:07:50 +00002152 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002153 // Handle a few common aliases of registers.
2154 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2155 .Case("fp", AArch64::FP)
2156 .Case("lr", AArch64::LR)
2157 .Case("x31", AArch64::XZR)
2158 .Case("w31", AArch64::WZR)
2159 .Default(0))
2160 return Kind == RegKind::Scalar ? RegNum : 0;
2161
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002162 // Check for aliases registered via .req. Canonicalize to lower case.
2163 // That's more consistent since register names are case insensitive, and
2164 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2165 auto Entry = RegisterReqs.find(Name.lower());
2166 if (Entry == RegisterReqs.end())
2167 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002168
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002169 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002170 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002171 RegNum = Entry->getValue().second;
2172 }
2173 return RegNum;
2174}
2175
Sander de Smalen50d87022018-04-19 07:35:08 +00002176/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002177/// Identifier when called, and if it is a register name the token is eaten and
2178/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002179OperandMatchResultTy
2180AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002181 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002182 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002183 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002184 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002185
2186 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002187 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2188 if (Reg == 0)
2189 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002190
Sander de Smalen50d87022018-04-19 07:35:08 +00002191 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002192 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002193 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002194}
2195
Tim Northover3b0846e2014-05-24 12:50:23 +00002196/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002197OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002198AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002199 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002200 SMLoc S = getLoc();
2201
2202 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2203 Error(S, "Expected cN operand where 0 <= N <= 15");
2204 return MatchOperand_ParseFail;
2205 }
2206
2207 StringRef Tok = Parser.getTok().getIdentifier();
2208 if (Tok[0] != 'c' && Tok[0] != 'C') {
2209 Error(S, "Expected cN operand where 0 <= N <= 15");
2210 return MatchOperand_ParseFail;
2211 }
2212
2213 uint32_t CRNum;
2214 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2215 if (BadNum || CRNum > 15) {
2216 Error(S, "Expected cN operand where 0 <= N <= 15");
2217 return MatchOperand_ParseFail;
2218 }
2219
2220 Parser.Lex(); // Eat identifier token.
2221 Operands.push_back(
2222 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2223 return MatchOperand_Success;
2224}
2225
2226/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002227template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002228OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002229AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002230 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002231 SMLoc S = getLoc();
2232 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002233
2234 auto LookupByName = [](StringRef N) {
2235 if (IsSVEPrefetch) {
2236 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2237 return Optional<unsigned>(Res->Encoding);
2238 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2239 return Optional<unsigned>(Res->Encoding);
2240 return Optional<unsigned>();
2241 };
2242
2243 auto LookupByEncoding = [](unsigned E) {
2244 if (IsSVEPrefetch) {
2245 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2246 return Optional<StringRef>(Res->Name);
2247 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2248 return Optional<StringRef>(Res->Name);
2249 return Optional<StringRef>();
2250 };
2251 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2252
Tim Northover3b0846e2014-05-24 12:50:23 +00002253 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002254 // Eat optional hash.
2255 if (parseOptionalToken(AsmToken::Hash) ||
2256 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002257 const MCExpr *ImmVal;
2258 if (getParser().parseExpression(ImmVal))
2259 return MatchOperand_ParseFail;
2260
2261 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2262 if (!MCE) {
2263 TokError("immediate value expected for prefetch operand");
2264 return MatchOperand_ParseFail;
2265 }
2266 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002267 if (prfop > MaxVal) {
2268 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2269 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002270 return MatchOperand_ParseFail;
2271 }
2272
Sander de Smalen93380372018-05-14 11:54:41 +00002273 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002274 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002275 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002276 return MatchOperand_Success;
2277 }
2278
2279 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002280 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002281 return MatchOperand_ParseFail;
2282 }
2283
Sander de Smalen93380372018-05-14 11:54:41 +00002284 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002285 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002286 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002287 return MatchOperand_ParseFail;
2288 }
2289
2290 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002291 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002292 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002293 return MatchOperand_Success;
2294}
2295
Oliver Stannarda34e4702015-12-01 10:48:51 +00002296/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002297OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002298AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2299 MCAsmParser &Parser = getParser();
2300 SMLoc S = getLoc();
2301 const AsmToken &Tok = Parser.getTok();
2302 if (Tok.isNot(AsmToken::Identifier)) {
2303 TokError("invalid operand for instruction");
2304 return MatchOperand_ParseFail;
2305 }
2306
Tim Northovere6ae6762016-07-05 21:23:04 +00002307 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2308 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002309 TokError("invalid operand for instruction");
2310 return MatchOperand_ParseFail;
2311 }
2312
2313 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002314 Operands.push_back(AArch64Operand::CreatePSBHint(
2315 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002316 return MatchOperand_Success;
2317}
2318
Tim Northover3b0846e2014-05-24 12:50:23 +00002319/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2320/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002321OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002322AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002323 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002324 SMLoc S = getLoc();
2325 const MCExpr *Expr;
2326
2327 if (Parser.getTok().is(AsmToken::Hash)) {
2328 Parser.Lex(); // Eat hash token.
2329 }
2330
2331 if (parseSymbolicImmVal(Expr))
2332 return MatchOperand_ParseFail;
2333
2334 AArch64MCExpr::VariantKind ELFRefKind;
2335 MCSymbolRefExpr::VariantKind DarwinRefKind;
2336 int64_t Addend;
2337 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2338 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2339 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2340 // No modifier was specified at all; this is the syntax for an ELF basic
2341 // ADRP relocation (unfortunately).
2342 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002343 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002344 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2345 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2346 Addend != 0) {
2347 Error(S, "gotpage label reference not allowed an addend");
2348 return MatchOperand_ParseFail;
2349 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2350 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2351 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2352 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2353 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2354 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2355 // The operand must be an @page or @gotpage qualified symbolref.
2356 Error(S, "page or gotpage label reference expected");
2357 return MatchOperand_ParseFail;
2358 }
2359 }
2360
2361 // We have either a label reference possibly with addend or an immediate. The
2362 // addend is a raw value here. The linker will adjust it to only reference the
2363 // page.
2364 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2365 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2366
2367 return MatchOperand_Success;
2368}
2369
2370/// tryParseAdrLabel - Parse and validate a source label for the ADR
2371/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002372OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002373AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2374 SMLoc S = getLoc();
2375 const MCExpr *Expr;
2376
Nirav Davee833c6c2016-11-08 18:31:04 +00002377 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002378 if (getParser().parseExpression(Expr))
2379 return MatchOperand_ParseFail;
2380
2381 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2382 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2383
2384 return MatchOperand_Success;
2385}
2386
2387/// tryParseFPImm - A floating point immediate expression operand.
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002388template<bool AddFPZeroAsLiteral>
Alex Bradbury58eba092016-11-01 16:32:05 +00002389OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002390AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002391 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002392 SMLoc S = getLoc();
2393
Nirav Davee833c6c2016-11-08 18:31:04 +00002394 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002395
2396 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002397 bool isNegative = parseOptionalToken(AsmToken::Minus);
2398
Tim Northover3b0846e2014-05-24 12:50:23 +00002399 const AsmToken &Tok = Parser.getTok();
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002400 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2401 if (!Hash)
2402 return MatchOperand_NoMatch;
2403 TokError("invalid floating point immediate");
2404 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002405 }
2406
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002407 // Parse hexadecimal representation.
2408 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2409 if (Tok.getIntVal() > 255 || isNegative) {
2410 TokError("encoded floating point value out of range");
2411 return MatchOperand_ParseFail;
2412 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002413
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002414 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2415 Operands.push_back(
2416 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2417 } else {
2418 // Parse FP representation.
2419 APFloat RealVal(APFloat::IEEEdouble());
2420 auto Status =
2421 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2422 if (isNegative)
2423 RealVal.changeSign();
2424
2425 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2426 Operands.push_back(
2427 AArch64Operand::CreateToken("#0", false, S, getContext()));
2428 Operands.push_back(
2429 AArch64Operand::CreateToken(".0", false, S, getContext()));
2430 } else
2431 Operands.push_back(AArch64Operand::CreateFPImm(
2432 RealVal, Status == APFloat::opOK, S, getContext()));
2433 }
2434
2435 Parser.Lex(); // Eat the token.
2436
2437 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002438}
2439
Sander de Smalen62770792018-05-25 09:47:52 +00002440/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2441/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002442OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002443AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002444 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002445 SMLoc S = getLoc();
2446
2447 if (Parser.getTok().is(AsmToken::Hash))
2448 Parser.Lex(); // Eat '#'
2449 else if (Parser.getTok().isNot(AsmToken::Integer))
2450 // Operand should start from # or should be integer, emit error otherwise.
2451 return MatchOperand_NoMatch;
2452
2453 const MCExpr *Imm;
2454 if (parseSymbolicImmVal(Imm))
2455 return MatchOperand_ParseFail;
2456 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002457 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002458 Operands.push_back(
2459 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002460 return MatchOperand_Success;
2461 }
2462
2463 // Eat ','
2464 Parser.Lex();
2465
2466 // The optional operand must be "lsl #N" where N is non-negative.
2467 if (!Parser.getTok().is(AsmToken::Identifier) ||
2468 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2469 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2470 return MatchOperand_ParseFail;
2471 }
2472
2473 // Eat 'lsl'
2474 Parser.Lex();
2475
Nirav Davee833c6c2016-11-08 18:31:04 +00002476 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002477
2478 if (Parser.getTok().isNot(AsmToken::Integer)) {
2479 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2480 return MatchOperand_ParseFail;
2481 }
2482
2483 int64_t ShiftAmount = Parser.getTok().getIntVal();
2484
2485 if (ShiftAmount < 0) {
2486 Error(Parser.getTok().getLoc(), "positive shift amount required");
2487 return MatchOperand_ParseFail;
2488 }
2489 Parser.Lex(); // Eat the number
2490
Sander de Smalen62770792018-05-25 09:47:52 +00002491 // Just in case the optional lsl #0 is used for immediates other than zero.
2492 if (ShiftAmount == 0 && Imm != 0) {
2493 SMLoc E = Parser.getTok().getLoc();
2494 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2495 return MatchOperand_Success;
2496 }
2497
Tim Northover3b0846e2014-05-24 12:50:23 +00002498 SMLoc E = Parser.getTok().getLoc();
2499 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2500 S, E, getContext()));
2501 return MatchOperand_Success;
2502}
2503
2504/// parseCondCodeString - Parse a Condition Code string.
2505AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2506 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2507 .Case("eq", AArch64CC::EQ)
2508 .Case("ne", AArch64CC::NE)
2509 .Case("cs", AArch64CC::HS)
2510 .Case("hs", AArch64CC::HS)
2511 .Case("cc", AArch64CC::LO)
2512 .Case("lo", AArch64CC::LO)
2513 .Case("mi", AArch64CC::MI)
2514 .Case("pl", AArch64CC::PL)
2515 .Case("vs", AArch64CC::VS)
2516 .Case("vc", AArch64CC::VC)
2517 .Case("hi", AArch64CC::HI)
2518 .Case("ls", AArch64CC::LS)
2519 .Case("ge", AArch64CC::GE)
2520 .Case("lt", AArch64CC::LT)
2521 .Case("gt", AArch64CC::GT)
2522 .Case("le", AArch64CC::LE)
2523 .Case("al", AArch64CC::AL)
2524 .Case("nv", AArch64CC::NV)
2525 .Default(AArch64CC::Invalid);
Sander de Smalene31e6d42018-07-04 08:50:49 +00002526
2527 if (CC == AArch64CC::Invalid &&
2528 getSTI().getFeatureBits()[AArch64::FeatureSVE])
2529 CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2530 .Case("none", AArch64CC::EQ)
2531 .Case("any", AArch64CC::NE)
2532 .Case("nlast", AArch64CC::HS)
2533 .Case("last", AArch64CC::LO)
2534 .Case("first", AArch64CC::MI)
2535 .Case("nfrst", AArch64CC::PL)
2536 .Case("pmore", AArch64CC::HI)
2537 .Case("plast", AArch64CC::LS)
2538 .Case("tcont", AArch64CC::GE)
2539 .Case("tstop", AArch64CC::LT)
2540 .Default(AArch64CC::Invalid);
2541
Tim Northover3b0846e2014-05-24 12:50:23 +00002542 return CC;
2543}
2544
2545/// parseCondCode - Parse a Condition Code operand.
2546bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2547 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002548 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002549 SMLoc S = getLoc();
2550 const AsmToken &Tok = Parser.getTok();
2551 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2552
2553 StringRef Cond = Tok.getString();
2554 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2555 if (CC == AArch64CC::Invalid)
2556 return TokError("invalid condition code");
2557 Parser.Lex(); // Eat identifier token.
2558
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002559 if (invertCondCode) {
2560 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2561 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002562 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002563 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002564
2565 Operands.push_back(
2566 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2567 return false;
2568}
2569
2570/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2571/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002572OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002573AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002574 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002575 const AsmToken &Tok = Parser.getTok();
2576 std::string LowerID = Tok.getString().lower();
2577 AArch64_AM::ShiftExtendType ShOp =
2578 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2579 .Case("lsl", AArch64_AM::LSL)
2580 .Case("lsr", AArch64_AM::LSR)
2581 .Case("asr", AArch64_AM::ASR)
2582 .Case("ror", AArch64_AM::ROR)
2583 .Case("msl", AArch64_AM::MSL)
2584 .Case("uxtb", AArch64_AM::UXTB)
2585 .Case("uxth", AArch64_AM::UXTH)
2586 .Case("uxtw", AArch64_AM::UXTW)
2587 .Case("uxtx", AArch64_AM::UXTX)
2588 .Case("sxtb", AArch64_AM::SXTB)
2589 .Case("sxth", AArch64_AM::SXTH)
2590 .Case("sxtw", AArch64_AM::SXTW)
2591 .Case("sxtx", AArch64_AM::SXTX)
2592 .Default(AArch64_AM::InvalidShiftExtend);
2593
2594 if (ShOp == AArch64_AM::InvalidShiftExtend)
2595 return MatchOperand_NoMatch;
2596
2597 SMLoc S = Tok.getLoc();
2598 Parser.Lex();
2599
Nirav Davee833c6c2016-11-08 18:31:04 +00002600 bool Hash = parseOptionalToken(AsmToken::Hash);
2601
Tim Northover3b0846e2014-05-24 12:50:23 +00002602 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2603 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2604 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2605 ShOp == AArch64_AM::MSL) {
2606 // We expect a number here.
2607 TokError("expected #imm after shift specifier");
2608 return MatchOperand_ParseFail;
2609 }
2610
Chad Rosier2ff37b82016-12-27 16:58:09 +00002611 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002612 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2613 Operands.push_back(
2614 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2615 return MatchOperand_Success;
2616 }
2617
Chad Rosier2ff37b82016-12-27 16:58:09 +00002618 // Make sure we do actually have a number, identifier or a parenthesized
2619 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002620 SMLoc E = Parser.getTok().getLoc();
2621 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002622 !Parser.getTok().is(AsmToken::LParen) &&
2623 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002624 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002625 return MatchOperand_ParseFail;
2626 }
2627
2628 const MCExpr *ImmVal;
2629 if (getParser().parseExpression(ImmVal))
2630 return MatchOperand_ParseFail;
2631
2632 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2633 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002634 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002635 return MatchOperand_ParseFail;
2636 }
2637
Jim Grosbach57fd2622014-09-23 22:16:02 +00002638 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002639 Operands.push_back(AArch64Operand::CreateShiftExtend(
2640 ShOp, MCE->getValue(), true, S, E, getContext()));
2641 return MatchOperand_Success;
2642}
2643
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002644static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2645 if (FBS[AArch64::HasV8_1aOps])
2646 Str += "ARMv8.1a";
2647 else if (FBS[AArch64::HasV8_2aOps])
2648 Str += "ARMv8.2a";
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002649 else if (FBS[AArch64::HasV8_3aOps])
2650 Str += "ARMv8.3a";
2651 else if (FBS[AArch64::HasV8_4aOps])
2652 Str += "ARMv8.4a";
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002653 else
2654 Str += "(unknown)";
2655}
2656
2657void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2658 SMLoc S) {
2659 const uint16_t Op2 = Encoding & 7;
2660 const uint16_t Cm = (Encoding & 0x78) >> 3;
2661 const uint16_t Cn = (Encoding & 0x780) >> 7;
2662 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2663
2664 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2665
2666 Operands.push_back(
2667 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2668 Operands.push_back(
2669 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2670 Operands.push_back(
2671 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2672 Expr = MCConstantExpr::create(Op2, getContext());
2673 Operands.push_back(
2674 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2675}
2676
Tim Northover3b0846e2014-05-24 12:50:23 +00002677/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2678/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2679bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2680 OperandVector &Operands) {
2681 if (Name.find('.') != StringRef::npos)
2682 return TokError("invalid operand");
2683
2684 Mnemonic = Name;
2685 Operands.push_back(
2686 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2687
Rafael Espindola961d4692014-11-11 05:18:41 +00002688 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002689 const AsmToken &Tok = Parser.getTok();
2690 StringRef Op = Tok.getString();
2691 SMLoc S = Tok.getLoc();
2692
Tim Northover3b0846e2014-05-24 12:50:23 +00002693 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002694 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2695 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002696 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002697 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2698 std::string Str("IC " + std::string(IC->Name) + " requires ");
2699 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2700 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002701 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002702 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002703 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002704 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2705 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002706 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002707 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2708 std::string Str("DC " + std::string(DC->Name) + " requires ");
2709 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2710 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002711 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002712 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002713 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002714 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2715 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002716 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002717 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2718 std::string Str("AT " + std::string(AT->Name) + " requires ");
2719 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2720 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002721 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002722 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002723 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002724 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2725 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002726 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002727 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2728 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2729 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2730 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002731 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002732 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002733 }
2734
Tim Northover3b0846e2014-05-24 12:50:23 +00002735 Parser.Lex(); // Eat operand.
2736
2737 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2738 bool HasRegister = false;
2739
2740 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002741 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002742 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2743 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002744 HasRegister = true;
2745 }
2746
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002747 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002748 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002749 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002750 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002751
Nirav Davee833c6c2016-11-08 18:31:04 +00002752 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2753 return true;
2754
Tim Northover3b0846e2014-05-24 12:50:23 +00002755 return false;
2756}
2757
Alex Bradbury58eba092016-11-01 16:32:05 +00002758OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002759AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002760 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002761 const AsmToken &Tok = Parser.getTok();
2762
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002763 if (Mnemonic == "tsb" && Tok.isNot(AsmToken::Identifier)) {
2764 TokError("'csync' operand expected");
2765 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002766 // Can be either a #imm style literal or an option name
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002767 } else if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002768 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002769 const MCExpr *ImmVal;
2770 SMLoc ExprLoc = getLoc();
2771 if (getParser().parseExpression(ImmVal))
2772 return MatchOperand_ParseFail;
2773 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2774 if (!MCE) {
2775 Error(ExprLoc, "immediate value expected for barrier operand");
2776 return MatchOperand_ParseFail;
2777 }
2778 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2779 Error(ExprLoc, "barrier operand out of range");
2780 return MatchOperand_ParseFail;
2781 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002782 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2783 Operands.push_back(AArch64Operand::CreateBarrier(
2784 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002785 return MatchOperand_Success;
2786 }
2787
2788 if (Tok.isNot(AsmToken::Identifier)) {
2789 TokError("invalid operand for instruction");
2790 return MatchOperand_ParseFail;
2791 }
2792
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002793 auto TSB = AArch64TSB::lookupTSBByName(Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00002794 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002795 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2796 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002797 TokError("'sy' or #imm operand expected");
2798 return MatchOperand_ParseFail;
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002799 // The only valid named option for TSB is 'csync'
2800 } else if (Mnemonic == "tsb" && (!TSB || TSB->Encoding != AArch64TSB::csync)) {
2801 TokError("'csync' operand expected");
2802 return MatchOperand_ParseFail;
2803 } else if (!DB && !TSB) {
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002804 TokError("invalid barrier option name");
2805 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002806 }
2807
Tim Northovere6ae6762016-07-05 21:23:04 +00002808 Operands.push_back(AArch64Operand::CreateBarrier(
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002809 DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002810 Parser.Lex(); // Consume the option
2811
2812 return MatchOperand_Success;
2813}
2814
Alex Bradbury58eba092016-11-01 16:32:05 +00002815OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002816AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002817 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002818 const AsmToken &Tok = Parser.getTok();
2819
2820 if (Tok.isNot(AsmToken::Identifier))
2821 return MatchOperand_NoMatch;
2822
Tim Northovere6ae6762016-07-05 21:23:04 +00002823 int MRSReg, MSRReg;
2824 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2825 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2826 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2827 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2828 } else
2829 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002830
Tim Northovere6ae6762016-07-05 21:23:04 +00002831 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2832 unsigned PStateImm = -1;
2833 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2834 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002835
Tim Northovere6ae6762016-07-05 21:23:04 +00002836 Operands.push_back(
2837 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2838 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002839 Parser.Lex(); // Eat identifier
2840
2841 return MatchOperand_Success;
2842}
2843
Florian Hahnc4422242017-11-07 13:07:50 +00002844/// tryParseNeonVectorRegister - Parse a vector register operand.
2845bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002846 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002847 if (Parser.getTok().isNot(AsmToken::Identifier))
2848 return true;
2849
2850 SMLoc S = getLoc();
2851 // Check for a vector register specifier first.
2852 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002853 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002854 OperandMatchResultTy Res =
2855 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2856 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002857 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002858
2859 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2860 if (!KindRes)
2861 return true;
2862
2863 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002864 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002865 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2866 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002867
Tim Northover3b0846e2014-05-24 12:50:23 +00002868 // If there was an explicit qualifier, that goes on as a literal text
2869 // operand.
2870 if (!Kind.empty())
2871 Operands.push_back(
2872 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2873
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002874 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2875}
2876
2877OperandMatchResultTy
2878AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002879 SMLoc SIdx = getLoc();
2880 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002881 const MCExpr *ImmVal;
2882 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002883 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002884 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2885 if (!MCE) {
2886 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002887 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002888 }
2889
2890 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002891
Nirav Davee833c6c2016-11-08 18:31:04 +00002892 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002893 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002894
2895 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2896 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002897 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002898 }
2899
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002900 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002901}
2902
Sander de Smalen73937b72018-04-11 07:36:10 +00002903// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002904// optional kind specifier. If it is a register specifier, eat the token
2905// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002906OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002907AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002908 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002909 MCAsmParser &Parser = getParser();
2910 const AsmToken &Tok = Parser.getTok();
2911
Florian Hahn91f11e52017-11-07 16:45:48 +00002912 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002913 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002914
2915 StringRef Name = Tok.getString();
2916 // If there is a kind specifier, it's separated from the register name by
2917 // a '.'.
2918 size_t Start = 0, Next = Name.find('.');
2919 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002920 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002921
2922 if (RegNum) {
2923 if (Next != StringRef::npos) {
2924 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002925 if (!isValidVectorKind(Kind, MatchKind)) {
2926 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002927 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002928 }
2929 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002930 Parser.Lex(); // Eat the register token.
2931
2932 Reg = RegNum;
2933 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002934 }
2935
Sander de Smalen8e607342017-11-15 15:44:43 +00002936 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002937}
2938
Sander de Smalencd6be962017-12-20 11:02:42 +00002939/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2940OperandMatchResultTy
2941AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2942 // Check for a SVE predicate register specifier first.
2943 const SMLoc S = getLoc();
2944 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002945 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002946 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002947 if (Res != MatchOperand_Success)
2948 return Res;
2949
Sander de Smalen73937b72018-04-11 07:36:10 +00002950 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2951 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002952 return MatchOperand_NoMatch;
2953
Sander de Smalen73937b72018-04-11 07:36:10 +00002954 unsigned ElementWidth = KindRes->second;
2955 Operands.push_back(AArch64Operand::CreateVectorReg(
2956 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2957 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002958
Sander de Smalen7868e742018-01-09 11:17:06 +00002959 // Not all predicates are followed by a '/m' or '/z'.
2960 MCAsmParser &Parser = getParser();
2961 if (Parser.getTok().isNot(AsmToken::Slash))
2962 return MatchOperand_Success;
2963
2964 // But when they do they shouldn't have an element type suffix.
2965 if (!Kind.empty()) {
2966 Error(S, "not expecting size suffix");
2967 return MatchOperand_ParseFail;
2968 }
2969
2970 // Add a literal slash as operand
2971 Operands.push_back(
2972 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2973
2974 Parser.Lex(); // Eat the slash.
2975
2976 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002977 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002978 if (Pred != "z" && Pred != "m") {
2979 Error(getLoc(), "expecting 'm' or 'z' predication");
2980 return MatchOperand_ParseFail;
2981 }
2982
2983 // Add zero/merge token.
2984 const char *ZM = Pred == "z" ? "z" : "m";
2985 Operands.push_back(
2986 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2987
2988 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002989 return MatchOperand_Success;
2990}
2991
Sander de Smalen50d87022018-04-19 07:35:08 +00002992/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002993bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002994 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002995 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002996 return false;
2997
Sander de Smalen149916d2018-04-20 07:24:20 +00002998 // Otherwise try for a scalar register.
2999 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
3000 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003001
Sander de Smalen149916d2018-04-20 07:24:20 +00003002 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003003}
3004
3005bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003006 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003007 bool HasELFModifier = false;
3008 AArch64MCExpr::VariantKind RefKind;
3009
Nirav Davee833c6c2016-11-08 18:31:04 +00003010 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003011 HasELFModifier = true;
3012
Nirav Davee833c6c2016-11-08 18:31:04 +00003013 if (Parser.getTok().isNot(AsmToken::Identifier))
3014 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003015
3016 std::string LowerCase = Parser.getTok().getIdentifier().lower();
3017 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
3018 .Case("lo12", AArch64MCExpr::VK_LO12)
3019 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
3020 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
3021 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
3022 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
3023 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
3024 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
3025 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
3026 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
3027 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
3028 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
3029 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
3030 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
3031 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3032 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3033 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3034 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3035 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3036 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3037 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3038 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3039 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3040 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3041 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3042 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3043 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3044 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3045 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3046 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3047 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3048 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3049 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3050 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3051 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3052 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003053 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3054 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00003055 .Default(AArch64MCExpr::VK_INVALID);
3056
Nirav Davee833c6c2016-11-08 18:31:04 +00003057 if (RefKind == AArch64MCExpr::VK_INVALID)
3058 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003059
3060 Parser.Lex(); // Eat identifier
3061
Nirav Davee833c6c2016-11-08 18:31:04 +00003062 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003063 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003064 }
3065
3066 if (getParser().parseExpression(ImmVal))
3067 return true;
3068
3069 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003070 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003071
3072 return false;
3073}
3074
Sander de Smalen650234b2018-04-12 11:40:52 +00003075template <RegKind VectorKind>
3076OperandMatchResultTy
3077AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3078 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003079 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003080 if (!Parser.getTok().is(AsmToken::LCurly))
3081 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003082
3083 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003084 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003085 bool NoMatchIsError) {
3086 auto RegTok = Parser.getTok();
3087 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3088 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003089 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003090 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003091 llvm_unreachable("Expected a valid vector kind");
3092 }
3093
Sander de Smalen650234b2018-04-12 11:40:52 +00003094 if (RegTok.isNot(AsmToken::Identifier) ||
3095 ParseRes == MatchOperand_ParseFail ||
3096 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3097 Error(Loc, "vector register expected");
3098 return MatchOperand_ParseFail;
3099 }
3100
3101 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003102 };
3103
Tim Northover3b0846e2014-05-24 12:50:23 +00003104 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003105 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003106 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003107
Tim Northover3b0846e2014-05-24 12:50:23 +00003108 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003109 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003110 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3111
3112 // Put back the original left bracket if there was no match, so that
3113 // different types of list-operands can be matched (e.g. SVE, Neon).
3114 if (ParseRes == MatchOperand_NoMatch)
3115 Parser.getLexer().UnLex(LCurly);
3116
3117 if (ParseRes != MatchOperand_Success)
3118 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003119
Tim Northover3b0846e2014-05-24 12:50:23 +00003120 int64_t PrevReg = FirstReg;
3121 unsigned Count = 1;
3122
Nirav Davee833c6c2016-11-08 18:31:04 +00003123 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003124 SMLoc Loc = getLoc();
3125 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003126
Sander de Smalen50d87022018-04-19 07:35:08 +00003127 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003128 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3129 if (ParseRes != MatchOperand_Success)
3130 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003131
Tim Northover3b0846e2014-05-24 12:50:23 +00003132 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003133 if (Kind != NextKind) {
3134 Error(Loc, "mismatched register size suffix");
3135 return MatchOperand_ParseFail;
3136 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003137
3138 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3139
3140 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003141 Error(Loc, "invalid number of vectors");
3142 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003143 }
3144
3145 Count += Space;
3146 }
3147 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003148 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003149 SMLoc Loc = getLoc();
3150 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003151 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003152 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3153 if (ParseRes != MatchOperand_Success)
3154 return ParseRes;
3155
Tim Northover3b0846e2014-05-24 12:50:23 +00003156 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003157 if (Kind != NextKind) {
3158 Error(Loc, "mismatched register size suffix");
3159 return MatchOperand_ParseFail;
3160 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003161
3162 // Registers must be incremental (with wraparound at 31)
3163 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003164 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3165 Error(Loc, "registers must be sequential");
3166 return MatchOperand_ParseFail;
3167 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003168
3169 PrevReg = Reg;
3170 ++Count;
3171 }
3172 }
3173
Nirav Davee833c6c2016-11-08 18:31:04 +00003174 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003175 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003176
Sander de Smalen650234b2018-04-12 11:40:52 +00003177 if (Count > 4) {
3178 Error(S, "invalid number of vectors");
3179 return MatchOperand_ParseFail;
3180 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003181
3182 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003183 unsigned ElementWidth = 0;
3184 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003185 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003186 std::tie(NumElements, ElementWidth) = *VK;
3187 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003188
3189 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003190 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3191 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003192
Sander de Smalen650234b2018-04-12 11:40:52 +00003193 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003194}
3195
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003196/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3197bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003198 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3199 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003200 return true;
3201
3202 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3203}
3204
Alex Bradbury58eba092016-11-01 16:32:05 +00003205OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003206AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003207 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003208
Sander de Smalen50d87022018-04-19 07:35:08 +00003209 unsigned RegNum;
3210 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3211 if (Res != MatchOperand_Success)
3212 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003213
Nirav Davee833c6c2016-11-08 18:31:04 +00003214 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003215 Operands.push_back(AArch64Operand::CreateReg(
3216 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003217 return MatchOperand_Success;
3218 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003219
Nirav Davee833c6c2016-11-08 18:31:04 +00003220 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003221
Sander de Smalen50d87022018-04-19 07:35:08 +00003222 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003223 Error(getLoc(), "index must be absent or #0");
3224 return MatchOperand_ParseFail;
3225 }
3226
3227 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003228 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003229 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3230 Error(getLoc(), "index must be absent or #0");
3231 return MatchOperand_ParseFail;
3232 }
3233
Sander de Smalen50d87022018-04-19 07:35:08 +00003234 Operands.push_back(AArch64Operand::CreateReg(
3235 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003236 return MatchOperand_Success;
3237}
3238
Sander de Smalen0325e302018-07-02 07:34:52 +00003239template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
Sander de Smalen149916d2018-04-20 07:24:20 +00003240OperandMatchResultTy
3241AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3242 SMLoc StartLoc = getLoc();
3243
3244 unsigned RegNum;
3245 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3246 if (Res != MatchOperand_Success)
3247 return Res;
3248
3249 // No shift/extend is the default.
3250 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3251 Operands.push_back(AArch64Operand::CreateReg(
Sander de Smalen0325e302018-07-02 07:34:52 +00003252 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
Sander de Smalen149916d2018-04-20 07:24:20 +00003253 return MatchOperand_Success;
3254 }
3255
3256 // Eat the comma
3257 getParser().Lex();
3258
3259 // Match the shift
3260 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3261 Res = tryParseOptionalShiftExtend(ExtOpnd);
3262 if (Res != MatchOperand_Success)
3263 return Res;
3264
3265 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
Sander de Smalen0325e302018-07-02 07:34:52 +00003266 Operands.push_back(AArch64Operand::CreateReg(
3267 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3268 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3269 Ext->hasShiftExtendAmount()));
Sander de Smalen149916d2018-04-20 07:24:20 +00003270
3271 return MatchOperand_Success;
3272}
3273
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003274bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
Sander de Smalen5c625982018-04-13 12:56:14 +00003275 MCAsmParser &Parser = getParser();
3276
3277 // Some SVE instructions have a decoration after the immediate, i.e.
3278 // "mul vl". We parse them here and add tokens, which must be present in the
3279 // asm string in the tablegen instruction.
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003280 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3281 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
Sander de Smalen5c625982018-04-13 12:56:14 +00003282 if (!Parser.getTok().getString().equals_lower("mul") ||
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003283 !(NextIsVL || NextIsHash))
Sander de Smalen5c625982018-04-13 12:56:14 +00003284 return true;
3285
Sander de Smalen5c625982018-04-13 12:56:14 +00003286 Operands.push_back(
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003287 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
Sander de Smalen5c625982018-04-13 12:56:14 +00003288 Parser.Lex(); // Eat the "mul"
3289
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003290 if (NextIsVL) {
3291 Operands.push_back(
3292 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3293 Parser.Lex(); // Eat the "vl"
3294 return false;
3295 }
Sander de Smalen5c625982018-04-13 12:56:14 +00003296
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003297 if (NextIsHash) {
3298 Parser.Lex(); // Eat the #
3299 SMLoc S = getLoc();
3300
3301 // Parse immediate operand.
3302 const MCExpr *ImmVal;
3303 if (!Parser.parseExpression(ImmVal))
3304 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3305 Operands.push_back(AArch64Operand::CreateImm(
3306 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3307 getContext()));
3308 return MatchOperand_Success;
3309 }
3310 }
3311
3312 return Error(getLoc(), "expected 'vl' or '#<imm>'");
Sander de Smalen5c625982018-04-13 12:56:14 +00003313}
3314
Tim Northover3b0846e2014-05-24 12:50:23 +00003315/// parseOperand - Parse a arm instruction operand. For now this parses the
3316/// operand regardless of the mnemonic.
3317bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3318 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003319 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003320
3321 OperandMatchResultTy ResTy =
3322 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3323
Tim Northover3b0846e2014-05-24 12:50:23 +00003324 // Check if the current operand has a custom associated parser, if so, try to
3325 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003326 if (ResTy == MatchOperand_Success)
3327 return false;
3328 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3329 // there was a match, but an error occurred, in which case, just return that
3330 // the operand parsing failed.
3331 if (ResTy == MatchOperand_ParseFail)
3332 return true;
3333
3334 // Nothing custom, so do general case parsing.
3335 SMLoc S, E;
3336 switch (getLexer().getKind()) {
3337 default: {
3338 SMLoc S = getLoc();
3339 const MCExpr *Expr;
3340 if (parseSymbolicImmVal(Expr))
3341 return Error(S, "invalid operand");
3342
3343 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3344 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3345 return false;
3346 }
3347 case AsmToken::LBrac: {
3348 SMLoc Loc = Parser.getTok().getLoc();
3349 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3350 getContext()));
3351 Parser.Lex(); // Eat '['
3352
3353 // There's no comma after a '[', so we can parse the next operand
3354 // immediately.
3355 return parseOperand(Operands, false, false);
3356 }
3357 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003358 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003359 case AsmToken::Identifier: {
3360 // If we're expecting a Condition Code operand, then just parse that.
3361 if (isCondCode)
3362 return parseCondCode(Operands, invertCondCode);
3363
3364 // If it's a register name, parse it.
3365 if (!parseRegister(Operands))
3366 return false;
3367
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003368 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3369 // by SVE instructions.
3370 if (!parseOptionalMulOperand(Operands))
Sander de Smalen5c625982018-04-13 12:56:14 +00003371 return false;
3372
Tim Northover3b0846e2014-05-24 12:50:23 +00003373 // This could be an optional "shift" or "extend" operand.
3374 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3375 // We can only continue if no tokens were eaten.
3376 if (GotShift != MatchOperand_NoMatch)
3377 return GotShift;
3378
3379 // This was not a register so parse other operands that start with an
3380 // identifier (like labels) as expressions and create them as immediates.
3381 const MCExpr *IdVal;
3382 S = getLoc();
3383 if (getParser().parseExpression(IdVal))
3384 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003385 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3386 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3387 return false;
3388 }
3389 case AsmToken::Integer:
3390 case AsmToken::Real:
3391 case AsmToken::Hash: {
3392 // #42 -> immediate.
3393 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003394
3395 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003396
3397 // Parse a negative sign
3398 bool isNegative = false;
3399 if (Parser.getTok().is(AsmToken::Minus)) {
3400 isNegative = true;
3401 // We need to consume this token only when we have a Real, otherwise
3402 // we let parseSymbolicImmVal take care of it
3403 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3404 Parser.Lex();
3405 }
3406
3407 // The only Real that should come through here is a literal #0.0 for
3408 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3409 // so convert the value.
3410 const AsmToken &Tok = Parser.getTok();
3411 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003412 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003413 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3414 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3415 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
Sander de Smalen8fcc3f52018-07-03 09:07:23 +00003416 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
Tim Northover3b0846e2014-05-24 12:50:23 +00003417 return TokError("unexpected floating point literal");
3418 else if (IntVal != 0 || isNegative)
3419 return TokError("expected floating-point constant #0.0");
3420 Parser.Lex(); // Eat the token.
3421
3422 Operands.push_back(
3423 AArch64Operand::CreateToken("#0", false, S, getContext()));
3424 Operands.push_back(
3425 AArch64Operand::CreateToken(".0", false, S, getContext()));
3426 return false;
3427 }
3428
3429 const MCExpr *ImmVal;
3430 if (parseSymbolicImmVal(ImmVal))
3431 return true;
3432
3433 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3434 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3435 return false;
3436 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003437 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003438 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003439 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003440 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003441 Parser.Lex(); // Eat '='
3442 const MCExpr *SubExprVal;
3443 if (getParser().parseExpression(SubExprVal))
3444 return true;
3445
David Peixottoae5ba762014-07-18 16:05:14 +00003446 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003447 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003448 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003449
3450 bool IsXReg =
3451 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3452 Operands[1]->getReg());
3453
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003454 MCContext& Ctx = getContext();
3455 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3456 // 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 +00003457 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003458 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3459 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3460 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3461 ShiftAmt += 16;
3462 Imm >>= 16;
3463 }
3464 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3465 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3466 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003467 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003468 if (ShiftAmt)
3469 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3470 ShiftAmt, true, S, E, Ctx));
3471 return false;
3472 }
David Peixottoae5ba762014-07-18 16:05:14 +00003473 APInt Simm = APInt(64, Imm << ShiftAmt);
3474 // check if the immediate is an unsigned or signed 32-bit int for W regs
3475 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3476 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003477 }
3478 // 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 +00003479 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003480 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003481 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3482 return false;
3483 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003484 }
3485}
3486
Sander de Smalen0325e302018-07-02 07:34:52 +00003487bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3488 const MCParsedAsmOperand &Op2) const {
3489 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3490 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3491 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3492 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3493 return MCTargetAsmParser::regsEqual(Op1, Op2);
3494
3495 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3496 "Testing equality of non-scalar registers not supported");
3497
3498 // Check if a registers match their sub/super register classes.
3499 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3500 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3501 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3502 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3503 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3504 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3505 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3506 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3507
3508 return false;
3509}
3510
Tim Northover3b0846e2014-05-24 12:50:23 +00003511/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3512/// operands.
3513bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3514 StringRef Name, SMLoc NameLoc,
3515 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003516 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003517 Name = StringSwitch<StringRef>(Name.lower())
3518 .Case("beq", "b.eq")
3519 .Case("bne", "b.ne")
3520 .Case("bhs", "b.hs")
3521 .Case("bcs", "b.cs")
3522 .Case("blo", "b.lo")
3523 .Case("bcc", "b.cc")
3524 .Case("bmi", "b.mi")
3525 .Case("bpl", "b.pl")
3526 .Case("bvs", "b.vs")
3527 .Case("bvc", "b.vc")
3528 .Case("bhi", "b.hi")
3529 .Case("bls", "b.ls")
3530 .Case("bge", "b.ge")
3531 .Case("blt", "b.lt")
3532 .Case("bgt", "b.gt")
3533 .Case("ble", "b.le")
3534 .Case("bal", "b.al")
3535 .Case("bnv", "b.nv")
3536 .Default(Name);
3537
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003538 // First check for the AArch64-specific .req directive.
3539 if (Parser.getTok().is(AsmToken::Identifier) &&
3540 Parser.getTok().getIdentifier() == ".req") {
3541 parseDirectiveReq(Name, NameLoc);
3542 // We always return 'error' for this, as we're done with this
3543 // statement and don't need to match the 'instruction."
3544 return true;
3545 }
3546
Tim Northover3b0846e2014-05-24 12:50:23 +00003547 // Create the leading tokens for the mnemonic, split by '.' characters.
3548 size_t Start = 0, Next = Name.find('.');
3549 StringRef Head = Name.slice(Start, Next);
3550
3551 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003552 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3553 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003554
3555 Operands.push_back(
3556 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3557 Mnemonic = Head;
3558
3559 // Handle condition codes for a branch mnemonic
3560 if (Head == "b" && Next != StringRef::npos) {
3561 Start = Next;
3562 Next = Name.find('.', Start + 1);
3563 Head = Name.slice(Start + 1, Next);
3564
3565 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3566 (Head.data() - Name.data()));
3567 AArch64CC::CondCode CC = parseCondCodeString(Head);
3568 if (CC == AArch64CC::Invalid)
3569 return Error(SuffixLoc, "invalid condition code");
3570 Operands.push_back(
3571 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3572 Operands.push_back(
3573 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3574 }
3575
3576 // Add the remaining tokens in the mnemonic.
3577 while (Next != StringRef::npos) {
3578 Start = Next;
3579 Next = Name.find('.', Start + 1);
3580 Head = Name.slice(Start, Next);
3581 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3582 (Head.data() - Name.data()) + 1);
3583 Operands.push_back(
3584 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3585 }
3586
3587 // Conditional compare instructions have a Condition Code operand, which needs
3588 // to be parsed and an immediate operand created.
3589 bool condCodeFourthOperand =
3590 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3591 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3592 Head == "csinc" || Head == "csinv" || Head == "csneg");
3593
3594 // These instructions are aliases to some of the conditional select
3595 // instructions. However, the condition code is inverted in the aliased
3596 // instruction.
3597 //
3598 // FIXME: Is this the correct way to handle these? Or should the parser
3599 // generate the aliased instructions directly?
3600 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3601 bool condCodeThirdOperand =
3602 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3603
3604 // Read the remaining operands.
3605 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3606 // Read the first operand.
3607 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003608 return true;
3609 }
3610
3611 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003612 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003613 // Parse and remember the operand.
3614 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3615 (N == 3 && condCodeThirdOperand) ||
3616 (N == 2 && condCodeSecondOperand),
3617 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003618 return true;
3619 }
3620
3621 // After successfully parsing some operands there are two special cases to
3622 // consider (i.e. notional operands not separated by commas). Both are due
3623 // to memory specifiers:
3624 // + An RBrac will end an address for load/store/prefetch
3625 // + An '!' will indicate a pre-indexed operation.
3626 //
3627 // It's someone else's responsibility to make sure these tokens are sane
3628 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003629
Nirav Davee833c6c2016-11-08 18:31:04 +00003630 SMLoc RLoc = Parser.getTok().getLoc();
3631 if (parseOptionalToken(AsmToken::RBrac))
3632 Operands.push_back(
3633 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3634 SMLoc ELoc = Parser.getTok().getLoc();
3635 if (parseOptionalToken(AsmToken::Exclaim))
3636 Operands.push_back(
3637 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003638
3639 ++N;
3640 }
3641 }
3642
Nirav Davee833c6c2016-11-08 18:31:04 +00003643 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3644 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003645
Tim Northover3b0846e2014-05-24 12:50:23 +00003646 return false;
3647}
3648
3649// FIXME: This entire function is a giant hack to provide us with decent
3650// operand range validation/diagnostics until TableGen/MC can be extended
3651// to support autogeneration of this kind of validation.
3652bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3653 SmallVectorImpl<SMLoc> &Loc) {
3654 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3655 // Check for indexed addressing modes w/ the base register being the
3656 // same as a destination/source register or pair load where
3657 // the Rt == Rt2. All of those are undefined behaviour.
3658 switch (Inst.getOpcode()) {
3659 case AArch64::LDPSWpre:
3660 case AArch64::LDPWpost:
3661 case AArch64::LDPWpre:
3662 case AArch64::LDPXpost:
3663 case AArch64::LDPXpre: {
3664 unsigned Rt = Inst.getOperand(1).getReg();
3665 unsigned Rt2 = Inst.getOperand(2).getReg();
3666 unsigned Rn = Inst.getOperand(3).getReg();
3667 if (RI->isSubRegisterEq(Rn, Rt))
3668 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3669 "is also a destination");
3670 if (RI->isSubRegisterEq(Rn, Rt2))
3671 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3672 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003673 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003674 }
3675 case AArch64::LDPDi:
3676 case AArch64::LDPQi:
3677 case AArch64::LDPSi:
3678 case AArch64::LDPSWi:
3679 case AArch64::LDPWi:
3680 case AArch64::LDPXi: {
3681 unsigned Rt = Inst.getOperand(0).getReg();
3682 unsigned Rt2 = Inst.getOperand(1).getReg();
3683 if (Rt == Rt2)
3684 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3685 break;
3686 }
3687 case AArch64::LDPDpost:
3688 case AArch64::LDPDpre:
3689 case AArch64::LDPQpost:
3690 case AArch64::LDPQpre:
3691 case AArch64::LDPSpost:
3692 case AArch64::LDPSpre:
3693 case AArch64::LDPSWpost: {
3694 unsigned Rt = Inst.getOperand(1).getReg();
3695 unsigned Rt2 = Inst.getOperand(2).getReg();
3696 if (Rt == Rt2)
3697 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3698 break;
3699 }
3700 case AArch64::STPDpost:
3701 case AArch64::STPDpre:
3702 case AArch64::STPQpost:
3703 case AArch64::STPQpre:
3704 case AArch64::STPSpost:
3705 case AArch64::STPSpre:
3706 case AArch64::STPWpost:
3707 case AArch64::STPWpre:
3708 case AArch64::STPXpost:
3709 case AArch64::STPXpre: {
3710 unsigned Rt = Inst.getOperand(1).getReg();
3711 unsigned Rt2 = Inst.getOperand(2).getReg();
3712 unsigned Rn = Inst.getOperand(3).getReg();
3713 if (RI->isSubRegisterEq(Rn, Rt))
3714 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3715 "is also a source");
3716 if (RI->isSubRegisterEq(Rn, Rt2))
3717 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3718 "is also a source");
3719 break;
3720 }
3721 case AArch64::LDRBBpre:
3722 case AArch64::LDRBpre:
3723 case AArch64::LDRHHpre:
3724 case AArch64::LDRHpre:
3725 case AArch64::LDRSBWpre:
3726 case AArch64::LDRSBXpre:
3727 case AArch64::LDRSHWpre:
3728 case AArch64::LDRSHXpre:
3729 case AArch64::LDRSWpre:
3730 case AArch64::LDRWpre:
3731 case AArch64::LDRXpre:
3732 case AArch64::LDRBBpost:
3733 case AArch64::LDRBpost:
3734 case AArch64::LDRHHpost:
3735 case AArch64::LDRHpost:
3736 case AArch64::LDRSBWpost:
3737 case AArch64::LDRSBXpost:
3738 case AArch64::LDRSHWpost:
3739 case AArch64::LDRSHXpost:
3740 case AArch64::LDRSWpost:
3741 case AArch64::LDRWpost:
3742 case AArch64::LDRXpost: {
3743 unsigned Rt = Inst.getOperand(1).getReg();
3744 unsigned Rn = Inst.getOperand(2).getReg();
3745 if (RI->isSubRegisterEq(Rn, Rt))
3746 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3747 "is also a source");
3748 break;
3749 }
3750 case AArch64::STRBBpost:
3751 case AArch64::STRBpost:
3752 case AArch64::STRHHpost:
3753 case AArch64::STRHpost:
3754 case AArch64::STRWpost:
3755 case AArch64::STRXpost:
3756 case AArch64::STRBBpre:
3757 case AArch64::STRBpre:
3758 case AArch64::STRHHpre:
3759 case AArch64::STRHpre:
3760 case AArch64::STRWpre:
3761 case AArch64::STRXpre: {
3762 unsigned Rt = Inst.getOperand(1).getReg();
3763 unsigned Rn = Inst.getOperand(2).getReg();
3764 if (RI->isSubRegisterEq(Rn, Rt))
3765 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3766 "is also a source");
3767 break;
3768 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003769 case AArch64::STXRB:
3770 case AArch64::STXRH:
3771 case AArch64::STXRW:
3772 case AArch64::STXRX:
3773 case AArch64::STLXRB:
3774 case AArch64::STLXRH:
3775 case AArch64::STLXRW:
3776 case AArch64::STLXRX: {
3777 unsigned Rs = Inst.getOperand(0).getReg();
3778 unsigned Rt = Inst.getOperand(1).getReg();
3779 unsigned Rn = Inst.getOperand(2).getReg();
3780 if (RI->isSubRegisterEq(Rt, Rs) ||
3781 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3782 return Error(Loc[0],
3783 "unpredictable STXR instruction, status is also a source");
3784 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003785 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003786 case AArch64::STXPW:
3787 case AArch64::STXPX:
3788 case AArch64::STLXPW:
3789 case AArch64::STLXPX: {
3790 unsigned Rs = Inst.getOperand(0).getReg();
3791 unsigned Rt1 = Inst.getOperand(1).getReg();
3792 unsigned Rt2 = Inst.getOperand(2).getReg();
3793 unsigned Rn = Inst.getOperand(3).getReg();
3794 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3795 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3796 return Error(Loc[0],
3797 "unpredictable STXP instruction, status is also a source");
3798 break;
3799 }
3800 }
3801
Tim Northover3b0846e2014-05-24 12:50:23 +00003802
3803 // Now check immediate ranges. Separate from the above as there is overlap
3804 // in the instructions being checked and this keeps the nested conditionals
3805 // to a minimum.
3806 switch (Inst.getOpcode()) {
3807 case AArch64::ADDSWri:
3808 case AArch64::ADDSXri:
3809 case AArch64::ADDWri:
3810 case AArch64::ADDXri:
3811 case AArch64::SUBSWri:
3812 case AArch64::SUBSXri:
3813 case AArch64::SUBWri:
3814 case AArch64::SUBXri: {
3815 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3816 // some slight duplication here.
3817 if (Inst.getOperand(2).isExpr()) {
3818 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3819 AArch64MCExpr::VariantKind ELFRefKind;
3820 MCSymbolRefExpr::VariantKind DarwinRefKind;
3821 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003822 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3823
3824 // Only allow these with ADDXri.
3825 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3826 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3827 Inst.getOpcode() == AArch64::ADDXri)
3828 return false;
3829
3830 // Only allow these with ADDXri/ADDWri
3831 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3832 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3833 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3834 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3835 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3836 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3837 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003838 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3839 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3840 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003841 (Inst.getOpcode() == AArch64::ADDXri ||
3842 Inst.getOpcode() == AArch64::ADDWri))
3843 return false;
3844
3845 // Don't allow symbol refs in the immediate field otherwise
3846 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3847 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3848 // 'cmp w0, 'borked')
3849 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003850 }
Diana Picusc93518d2016-10-11 09:17:47 +00003851 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003852 }
3853 return false;
3854 }
3855 default:
3856 return false;
3857 }
3858}
3859
Craig Topper05515562017-10-26 06:46:41 +00003860static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3861 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003862
3863bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
Sander de Smalen0325e302018-07-02 07:34:52 +00003864 uint64_t ErrorInfo,
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003865 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003866 switch (ErrCode) {
Sander de Smalen0325e302018-07-02 07:34:52 +00003867 case Match_InvalidTiedOperand: {
3868 RegConstraintEqualityTy EqTy =
3869 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
3870 .getRegEqualityTy();
3871 switch (EqTy) {
3872 case RegConstraintEqualityTy::EqualsSubReg:
3873 return Error(Loc, "operand must be 64-bit form of destination register");
3874 case RegConstraintEqualityTy::EqualsSuperReg:
3875 return Error(Loc, "operand must be 32-bit form of destination register");
3876 case RegConstraintEqualityTy::EqualsReg:
3877 return Error(Loc, "operand must match destination register");
3878 }
Simon Pilgrim6dc45e62018-07-05 09:48:01 +00003879 llvm_unreachable("Unknown RegConstraintEqualityTy");
Sander de Smalen0325e302018-07-02 07:34:52 +00003880 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003881 case Match_MissingFeature:
3882 return Error(Loc,
3883 "instruction requires a CPU feature not currently enabled");
3884 case Match_InvalidOperand:
3885 return Error(Loc, "invalid operand for instruction");
3886 case Match_InvalidSuffix:
3887 return Error(Loc, "invalid type suffix for instruction");
3888 case Match_InvalidCondCode:
3889 return Error(Loc, "expected AArch64 condition code");
3890 case Match_AddSubRegExtendSmall:
3891 return Error(Loc,
3892 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3893 case Match_AddSubRegExtendLarge:
3894 return Error(Loc,
3895 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3896 case Match_AddSubSecondSource:
3897 return Error(Loc,
3898 "expected compatible register, symbol or integer in range [0, 4095]");
3899 case Match_LogicalSecondSource:
3900 return Error(Loc, "expected compatible register or logical immediate");
3901 case Match_InvalidMovImm32Shift:
3902 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3903 case Match_InvalidMovImm64Shift:
3904 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3905 case Match_AddSubRegShift32:
3906 return Error(Loc,
3907 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3908 case Match_AddSubRegShift64:
3909 return Error(Loc,
3910 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3911 case Match_InvalidFPImm:
3912 return Error(Loc,
3913 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003914 case Match_InvalidMemoryIndexedSImm6:
3915 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003916 case Match_InvalidMemoryIndexedSImm5:
3917 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003918 case Match_InvalidMemoryIndexed1SImm4:
3919 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003920 case Match_InvalidMemoryIndexed2SImm4:
3921 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003922 case Match_InvalidMemoryIndexed3SImm4:
3923 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003924 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00003925 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00003926 case Match_InvalidMemoryIndexed16SImm4:
3927 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00003928 case Match_InvalidMemoryIndexed1SImm6:
3929 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen592718f2018-07-05 07:54:10 +00003930 case Match_InvalidMemoryIndexedSImm8:
3931 return Error(Loc, "index must be an integer in range [-128, 127].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003932 case Match_InvalidMemoryIndexedSImm9:
3933 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00003934 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00003935 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003936 case Match_InvalidMemoryIndexed4SImm7:
3937 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3938 case Match_InvalidMemoryIndexed8SImm7:
3939 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3940 case Match_InvalidMemoryIndexed16SImm7:
3941 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00003942 case Match_InvalidMemoryIndexed8UImm5:
3943 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
3944 case Match_InvalidMemoryIndexed4UImm5:
3945 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
3946 case Match_InvalidMemoryIndexed2UImm5:
3947 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00003948 case Match_InvalidMemoryIndexed8UImm6:
3949 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
3950 case Match_InvalidMemoryIndexed4UImm6:
3951 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
3952 case Match_InvalidMemoryIndexed2UImm6:
3953 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
3954 case Match_InvalidMemoryIndexed1UImm6:
3955 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003956 case Match_InvalidMemoryWExtend8:
3957 return Error(Loc,
3958 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3959 case Match_InvalidMemoryWExtend16:
3960 return Error(Loc,
3961 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3962 case Match_InvalidMemoryWExtend32:
3963 return Error(Loc,
3964 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3965 case Match_InvalidMemoryWExtend64:
3966 return Error(Loc,
3967 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3968 case Match_InvalidMemoryWExtend128:
3969 return Error(Loc,
3970 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3971 case Match_InvalidMemoryXExtend8:
3972 return Error(Loc,
3973 "expected 'lsl' or 'sxtx' with optional shift of #0");
3974 case Match_InvalidMemoryXExtend16:
3975 return Error(Loc,
3976 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3977 case Match_InvalidMemoryXExtend32:
3978 return Error(Loc,
3979 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3980 case Match_InvalidMemoryXExtend64:
3981 return Error(Loc,
3982 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3983 case Match_InvalidMemoryXExtend128:
3984 return Error(Loc,
3985 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3986 case Match_InvalidMemoryIndexed1:
3987 return Error(Loc, "index must be an integer in range [0, 4095].");
3988 case Match_InvalidMemoryIndexed2:
3989 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3990 case Match_InvalidMemoryIndexed4:
3991 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3992 case Match_InvalidMemoryIndexed8:
3993 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3994 case Match_InvalidMemoryIndexed16:
3995 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003996 case Match_InvalidImm0_1:
3997 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003998 case Match_InvalidImm0_7:
3999 return Error(Loc, "immediate must be an integer in range [0, 7].");
4000 case Match_InvalidImm0_15:
4001 return Error(Loc, "immediate must be an integer in range [0, 15].");
4002 case Match_InvalidImm0_31:
4003 return Error(Loc, "immediate must be an integer in range [0, 31].");
4004 case Match_InvalidImm0_63:
4005 return Error(Loc, "immediate must be an integer in range [0, 63].");
4006 case Match_InvalidImm0_127:
4007 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004008 case Match_InvalidImm0_255:
4009 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004010 case Match_InvalidImm0_65535:
4011 return Error(Loc, "immediate must be an integer in range [0, 65535].");
4012 case Match_InvalidImm1_8:
4013 return Error(Loc, "immediate must be an integer in range [1, 8].");
4014 case Match_InvalidImm1_16:
4015 return Error(Loc, "immediate must be an integer in range [1, 16].");
4016 case Match_InvalidImm1_32:
4017 return Error(Loc, "immediate must be an integer in range [1, 32].");
4018 case Match_InvalidImm1_64:
4019 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00004020 case Match_InvalidSVEAddSubImm8:
4021 return Error(Loc, "immediate must be an integer in range [0, 255]"
4022 " with a shift amount of 0");
4023 case Match_InvalidSVEAddSubImm16:
4024 case Match_InvalidSVEAddSubImm32:
4025 case Match_InvalidSVEAddSubImm64:
4026 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
4027 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004028 case Match_InvalidSVECpyImm8:
4029 return Error(Loc, "immediate must be an integer in range [-128, 255]"
4030 " with a shift amount of 0");
4031 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00004032 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4033 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004034 case Match_InvalidSVECpyImm32:
4035 case Match_InvalidSVECpyImm64:
4036 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4037 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004038 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004039 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004040 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00004041 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004042 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00004043 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004044 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004045 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004046 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004047 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004048 case Match_InvalidSVEIndexRange0_63:
4049 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4050 case Match_InvalidSVEIndexRange0_31:
4051 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4052 case Match_InvalidSVEIndexRange0_15:
4053 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4054 case Match_InvalidSVEIndexRange0_7:
4055 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4056 case Match_InvalidSVEIndexRange0_3:
4057 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004058 case Match_InvalidLabel:
4059 return Error(Loc, "expected label or encodable integer pc offset");
4060 case Match_MRS:
4061 return Error(Loc, "expected readable system register");
4062 case Match_MSR:
4063 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00004064 case Match_InvalidComplexRotationEven:
4065 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4066 case Match_InvalidComplexRotationOdd:
4067 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004068 case Match_MnemonicFail: {
4069 std::string Suggestion = AArch64MnemonicSpellCheck(
4070 ((AArch64Operand &)*Operands[0]).getToken(),
4071 ComputeAvailableFeatures(STI->getFeatureBits()));
4072 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4073 }
Sander de Smalen367694b2018-04-20 08:54:49 +00004074 case Match_InvalidGPR64shifted8:
4075 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4076 case Match_InvalidGPR64shifted16:
4077 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4078 case Match_InvalidGPR64shifted32:
4079 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4080 case Match_InvalidGPR64shifted64:
4081 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4082 case Match_InvalidGPR64NoXZRshifted8:
4083 return Error(Loc, "register must be x0..x30 without shift");
4084 case Match_InvalidGPR64NoXZRshifted16:
4085 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4086 case Match_InvalidGPR64NoXZRshifted32:
4087 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4088 case Match_InvalidGPR64NoXZRshifted64:
4089 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004090 case Match_InvalidZPR32UXTW8:
4091 case Match_InvalidZPR32SXTW8:
4092 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4093 case Match_InvalidZPR32UXTW16:
4094 case Match_InvalidZPR32SXTW16:
4095 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4096 case Match_InvalidZPR32UXTW32:
4097 case Match_InvalidZPR32SXTW32:
4098 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4099 case Match_InvalidZPR32UXTW64:
4100 case Match_InvalidZPR32SXTW64:
4101 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4102 case Match_InvalidZPR64UXTW8:
4103 case Match_InvalidZPR64SXTW8:
4104 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4105 case Match_InvalidZPR64UXTW16:
4106 case Match_InvalidZPR64SXTW16:
4107 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4108 case Match_InvalidZPR64UXTW32:
4109 case Match_InvalidZPR64SXTW32:
4110 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4111 case Match_InvalidZPR64UXTW64:
4112 case Match_InvalidZPR64SXTW64:
4113 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
4114 case Match_InvalidZPR64LSL8:
4115 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4116 case Match_InvalidZPR64LSL16:
4117 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4118 case Match_InvalidZPR64LSL32:
4119 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4120 case Match_InvalidZPR64LSL64:
4121 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00004122 case Match_InvalidZPR0:
4123 return Error(Loc, "expected register without element width sufix");
4124 case Match_InvalidZPR8:
4125 case Match_InvalidZPR16:
4126 case Match_InvalidZPR32:
4127 case Match_InvalidZPR64:
4128 case Match_InvalidZPR128:
4129 return Error(Loc, "invalid element width");
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004130 case Match_InvalidZPR_3b8:
4131 return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b");
4132 case Match_InvalidZPR_3b16:
4133 return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h");
4134 case Match_InvalidZPR_3b32:
4135 return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s");
4136 case Match_InvalidZPR_4b16:
4137 return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h");
4138 case Match_InvalidZPR_4b32:
4139 return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s");
4140 case Match_InvalidZPR_4b64:
4141 return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004142 case Match_InvalidSVEPattern:
4143 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004144 case Match_InvalidSVEPredicateAnyReg:
4145 case Match_InvalidSVEPredicateBReg:
4146 case Match_InvalidSVEPredicateHReg:
4147 case Match_InvalidSVEPredicateSReg:
4148 case Match_InvalidSVEPredicateDReg:
4149 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004150 case Match_InvalidSVEPredicate3bAnyReg:
4151 case Match_InvalidSVEPredicate3bBReg:
4152 case Match_InvalidSVEPredicate3bHReg:
4153 case Match_InvalidSVEPredicate3bSReg:
4154 case Match_InvalidSVEPredicate3bDReg:
4155 return Error(Loc, "restricted predicate has range [0, 7].");
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004156 case Match_InvalidSVEExactFPImmOperandHalfOne:
4157 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4158 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4159 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4160 case Match_InvalidSVEExactFPImmOperandZeroOne:
4161 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004162 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004163 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004164 }
4165}
4166
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004167static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004168
4169bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4170 OperandVector &Operands,
4171 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004172 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004173 bool MatchingInlineAsm) {
4174 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004175 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4176 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004177
David Blaikie960ea3f2014-06-08 16:18:35 +00004178 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004179 unsigned NumOperands = Operands.size();
4180
4181 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004182 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4183 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004184 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004185 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004186 if (Op3CE) {
4187 uint64_t Op3Val = Op3CE->getValue();
4188 uint64_t NewOp3Val = 0;
4189 uint64_t NewOp4Val = 0;
4190 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004191 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004192 NewOp3Val = (32 - Op3Val) & 0x1f;
4193 NewOp4Val = 31 - Op3Val;
4194 } else {
4195 NewOp3Val = (64 - Op3Val) & 0x3f;
4196 NewOp4Val = 63 - Op3Val;
4197 }
4198
Jim Grosbach13760bd2015-05-30 01:25:56 +00004199 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4200 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004201
4202 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004203 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004204 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004205 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4206 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4207 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004208 }
4209 }
Tim Northover03b99f62015-04-30 18:28:58 +00004210 } else if (NumOperands == 4 && Tok == "bfc") {
4211 // FIXME: Horrible hack to handle BFC->BFM alias.
4212 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4213 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4214 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4215
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004216 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004217 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4218 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4219
4220 if (LSBCE && WidthCE) {
4221 uint64_t LSB = LSBCE->getValue();
4222 uint64_t Width = WidthCE->getValue();
4223
4224 uint64_t RegWidth = 0;
4225 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4226 Op1.getReg()))
4227 RegWidth = 64;
4228 else
4229 RegWidth = 32;
4230
4231 if (LSB >= RegWidth)
4232 return Error(LSBOp.getStartLoc(),
4233 "expected integer in range [0, 31]");
4234 if (Width < 1 || Width > RegWidth)
4235 return Error(WidthOp.getStartLoc(),
4236 "expected integer in range [1, 32]");
4237
4238 uint64_t ImmR = 0;
4239 if (RegWidth == 32)
4240 ImmR = (32 - LSB) & 0x1f;
4241 else
4242 ImmR = (64 - LSB) & 0x3f;
4243
4244 uint64_t ImmS = Width - 1;
4245
4246 if (ImmR != 0 && ImmS >= ImmR)
4247 return Error(WidthOp.getStartLoc(),
4248 "requested insert overflows register");
4249
Jim Grosbach13760bd2015-05-30 01:25:56 +00004250 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4251 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004252 Operands[0] = AArch64Operand::CreateToken(
4253 "bfm", false, Op.getStartLoc(), getContext());
4254 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004255 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4256 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004257 Operands[3] = AArch64Operand::CreateImm(
4258 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4259 Operands.emplace_back(
4260 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4261 WidthOp.getEndLoc(), getContext()));
4262 }
4263 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004264 } else if (NumOperands == 5) {
4265 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4266 // UBFIZ -> UBFM aliases.
4267 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004268 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4269 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4270 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004271
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004272 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004273 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4274 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004275
4276 if (Op3CE && Op4CE) {
4277 uint64_t Op3Val = Op3CE->getValue();
4278 uint64_t Op4Val = Op4CE->getValue();
4279
4280 uint64_t RegWidth = 0;
4281 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004282 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004283 RegWidth = 64;
4284 else
4285 RegWidth = 32;
4286
4287 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004288 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004289 "expected integer in range [0, 31]");
4290 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004291 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004292 "expected integer in range [1, 32]");
4293
4294 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004295 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004296 NewOp3Val = (32 - Op3Val) & 0x1f;
4297 else
4298 NewOp3Val = (64 - Op3Val) & 0x3f;
4299
4300 uint64_t NewOp4Val = Op4Val - 1;
4301
4302 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004303 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004304 "requested insert overflows register");
4305
4306 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004307 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004308 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004309 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004310 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004311 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004312 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004313 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004314 if (Tok == "bfi")
4315 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004316 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004317 else if (Tok == "sbfiz")
4318 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004319 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004320 else if (Tok == "ubfiz")
4321 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004322 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004323 else
4324 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004325 }
4326 }
4327
4328 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4329 // UBFX -> UBFM aliases.
4330 } else if (NumOperands == 5 &&
4331 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004332 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4333 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4334 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004335
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004336 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004337 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4338 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004339
4340 if (Op3CE && Op4CE) {
4341 uint64_t Op3Val = Op3CE->getValue();
4342 uint64_t Op4Val = Op4CE->getValue();
4343
4344 uint64_t RegWidth = 0;
4345 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004346 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004347 RegWidth = 64;
4348 else
4349 RegWidth = 32;
4350
4351 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004352 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004353 "expected integer in range [0, 31]");
4354 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004355 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004356 "expected integer in range [1, 32]");
4357
4358 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4359
4360 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004361 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004362 "requested extract overflows register");
4363
4364 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004365 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004366 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004367 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004368 if (Tok == "bfxil")
4369 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004370 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004371 else if (Tok == "sbfx")
4372 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004373 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004374 else if (Tok == "ubfx")
4375 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004376 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004377 else
4378 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004379 }
4380 }
4381 }
4382 }
Tim Northover9097a072017-12-18 10:36:00 +00004383
4384 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4385 // instruction for FP registers correctly in some rare circumstances. Convert
4386 // it to a safe instruction and warn (because silently changing someone's
4387 // assembly is rude).
4388 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4389 NumOperands == 4 && Tok == "movi") {
4390 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4391 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4392 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4393 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4394 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4395 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4396 if (Suffix.lower() == ".2d" &&
4397 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4398 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4399 " correctly on this CPU, converting to equivalent movi.16b");
4400 // Switch the suffix to .16b.
4401 unsigned Idx = Op1.isToken() ? 1 : 2;
4402 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4403 getContext());
4404 }
4405 }
4406 }
4407
Tim Northover3b0846e2014-05-24 12:50:23 +00004408 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4409 // InstAlias can't quite handle this since the reg classes aren't
4410 // subclasses.
4411 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4412 // The source register can be Wn here, but the matcher expects a
4413 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004414 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004415 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004416 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004417 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4418 Op.getStartLoc(), Op.getEndLoc(),
4419 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004420 }
4421 }
4422 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4423 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004424 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004425 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004426 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004427 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004428 // The source register can be Wn here, but the matcher expects a
4429 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004430 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004431 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004432 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004433 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4434 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004435 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004436 }
4437 }
4438 }
4439 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4440 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004441 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004442 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004443 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004444 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004445 // The source register can be Wn here, but the matcher expects a
4446 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004447 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004448 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004449 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004450 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4451 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004452 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004453 }
4454 }
4455 }
4456
Tim Northover3b0846e2014-05-24 12:50:23 +00004457 MCInst Inst;
4458 // First try to match against the secondary set of tables containing the
4459 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4460 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004461 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004462
4463 // If that fails, try against the alternate table containing long-form NEON:
4464 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004465 if (MatchResult != Match_Success) {
4466 // But first, save the short-form match result: we can use it in case the
4467 // long-form match also fails.
4468 auto ShortFormNEONErrorInfo = ErrorInfo;
4469 auto ShortFormNEONMatchResult = MatchResult;
4470
Tim Northover3b0846e2014-05-24 12:50:23 +00004471 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004472 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004473
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004474 // Now, both matches failed, and the long-form match failed on the mnemonic
4475 // suffix token operand. The short-form match failure is probably more
4476 // relevant: use it instead.
4477 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004478 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004479 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4480 MatchResult = ShortFormNEONMatchResult;
4481 ErrorInfo = ShortFormNEONErrorInfo;
4482 }
4483 }
4484
Tim Northover3b0846e2014-05-24 12:50:23 +00004485 switch (MatchResult) {
4486 case Match_Success: {
4487 // Perform range checking and other semantic validations
4488 SmallVector<SMLoc, 8> OperandLocs;
4489 NumOperands = Operands.size();
4490 for (unsigned i = 1; i < NumOperands; ++i)
4491 OperandLocs.push_back(Operands[i]->getStartLoc());
4492 if (validateInstruction(Inst, OperandLocs))
4493 return true;
4494
4495 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004496 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004497 return false;
4498 }
4499 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004500 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004501 // Special case the error message for the very common case where only
4502 // a single subtarget feature is missing (neon, e.g.).
4503 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004504 uint64_t Mask = 1;
4505 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4506 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004507 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004508 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004509 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004510 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004511 }
4512 return Error(IDLoc, Msg);
4513 }
4514 case Match_MnemonicFail:
Sander de Smalen0325e302018-07-02 07:34:52 +00004515 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004516 case Match_InvalidOperand: {
4517 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004518
Tim Northover26bb14e2014-08-18 11:49:42 +00004519 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004520 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004521 return Error(IDLoc, "too few operands for instruction",
4522 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004523
David Blaikie960ea3f2014-06-08 16:18:35 +00004524 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004525 if (ErrorLoc == SMLoc())
4526 ErrorLoc = IDLoc;
4527 }
4528 // If the match failed on a suffix token operand, tweak the diagnostic
4529 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004530 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4531 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004532 MatchResult = Match_InvalidSuffix;
4533
Sander de Smalen0325e302018-07-02 07:34:52 +00004534 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004535 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004536 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004537 case Match_InvalidMemoryIndexed1:
4538 case Match_InvalidMemoryIndexed2:
4539 case Match_InvalidMemoryIndexed4:
4540 case Match_InvalidMemoryIndexed8:
4541 case Match_InvalidMemoryIndexed16:
4542 case Match_InvalidCondCode:
4543 case Match_AddSubRegExtendSmall:
4544 case Match_AddSubRegExtendLarge:
4545 case Match_AddSubSecondSource:
4546 case Match_LogicalSecondSource:
4547 case Match_AddSubRegShift32:
4548 case Match_AddSubRegShift64:
4549 case Match_InvalidMovImm32Shift:
4550 case Match_InvalidMovImm64Shift:
4551 case Match_InvalidFPImm:
4552 case Match_InvalidMemoryWExtend8:
4553 case Match_InvalidMemoryWExtend16:
4554 case Match_InvalidMemoryWExtend32:
4555 case Match_InvalidMemoryWExtend64:
4556 case Match_InvalidMemoryWExtend128:
4557 case Match_InvalidMemoryXExtend8:
4558 case Match_InvalidMemoryXExtend16:
4559 case Match_InvalidMemoryXExtend32:
4560 case Match_InvalidMemoryXExtend64:
4561 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004562 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004563 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004564 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004565 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004566 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004567 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004568 case Match_InvalidMemoryIndexed4SImm7:
4569 case Match_InvalidMemoryIndexed8SImm7:
4570 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004571 case Match_InvalidMemoryIndexed8UImm5:
4572 case Match_InvalidMemoryIndexed4UImm5:
4573 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004574 case Match_InvalidMemoryIndexed1UImm6:
4575 case Match_InvalidMemoryIndexed2UImm6:
4576 case Match_InvalidMemoryIndexed4UImm6:
4577 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004578 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004579 case Match_InvalidMemoryIndexedSImm5:
Sander de Smalen592718f2018-07-05 07:54:10 +00004580 case Match_InvalidMemoryIndexedSImm8:
Tim Northover3b0846e2014-05-24 12:50:23 +00004581 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004582 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004583 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004584 case Match_InvalidImm0_7:
4585 case Match_InvalidImm0_15:
4586 case Match_InvalidImm0_31:
4587 case Match_InvalidImm0_63:
4588 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004589 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004590 case Match_InvalidImm0_65535:
4591 case Match_InvalidImm1_8:
4592 case Match_InvalidImm1_16:
4593 case Match_InvalidImm1_32:
4594 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004595 case Match_InvalidSVEAddSubImm8:
4596 case Match_InvalidSVEAddSubImm16:
4597 case Match_InvalidSVEAddSubImm32:
4598 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004599 case Match_InvalidSVECpyImm8:
4600 case Match_InvalidSVECpyImm16:
4601 case Match_InvalidSVECpyImm32:
4602 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004603 case Match_InvalidIndexRange1_1:
4604 case Match_InvalidIndexRange0_15:
4605 case Match_InvalidIndexRange0_7:
4606 case Match_InvalidIndexRange0_3:
4607 case Match_InvalidIndexRange0_1:
4608 case Match_InvalidSVEIndexRange0_63:
4609 case Match_InvalidSVEIndexRange0_31:
4610 case Match_InvalidSVEIndexRange0_15:
4611 case Match_InvalidSVEIndexRange0_7:
4612 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004613 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004614 case Match_InvalidComplexRotationEven:
4615 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004616 case Match_InvalidGPR64shifted8:
4617 case Match_InvalidGPR64shifted16:
4618 case Match_InvalidGPR64shifted32:
4619 case Match_InvalidGPR64shifted64:
4620 case Match_InvalidGPR64NoXZRshifted8:
4621 case Match_InvalidGPR64NoXZRshifted16:
4622 case Match_InvalidGPR64NoXZRshifted32:
4623 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004624 case Match_InvalidZPR32UXTW8:
4625 case Match_InvalidZPR32UXTW16:
4626 case Match_InvalidZPR32UXTW32:
4627 case Match_InvalidZPR32UXTW64:
4628 case Match_InvalidZPR32SXTW8:
4629 case Match_InvalidZPR32SXTW16:
4630 case Match_InvalidZPR32SXTW32:
4631 case Match_InvalidZPR32SXTW64:
4632 case Match_InvalidZPR64UXTW8:
4633 case Match_InvalidZPR64SXTW8:
4634 case Match_InvalidZPR64UXTW16:
4635 case Match_InvalidZPR64SXTW16:
4636 case Match_InvalidZPR64UXTW32:
4637 case Match_InvalidZPR64SXTW32:
4638 case Match_InvalidZPR64UXTW64:
4639 case Match_InvalidZPR64SXTW64:
4640 case Match_InvalidZPR64LSL8:
4641 case Match_InvalidZPR64LSL16:
4642 case Match_InvalidZPR64LSL32:
4643 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004644 case Match_InvalidZPR0:
4645 case Match_InvalidZPR8:
4646 case Match_InvalidZPR16:
4647 case Match_InvalidZPR32:
4648 case Match_InvalidZPR64:
4649 case Match_InvalidZPR128:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004650 case Match_InvalidZPR_3b8:
4651 case Match_InvalidZPR_3b16:
4652 case Match_InvalidZPR_3b32:
4653 case Match_InvalidZPR_4b16:
4654 case Match_InvalidZPR_4b32:
4655 case Match_InvalidZPR_4b64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004656 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004657 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004658 case Match_InvalidSVEPredicateBReg:
4659 case Match_InvalidSVEPredicateHReg:
4660 case Match_InvalidSVEPredicateSReg:
4661 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004662 case Match_InvalidSVEPredicate3bAnyReg:
4663 case Match_InvalidSVEPredicate3bBReg:
4664 case Match_InvalidSVEPredicate3bHReg:
4665 case Match_InvalidSVEPredicate3bSReg:
4666 case Match_InvalidSVEPredicate3bDReg:
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004667 case Match_InvalidSVEExactFPImmOperandHalfOne:
4668 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4669 case Match_InvalidSVEExactFPImmOperandZeroOne:
Tim Northover3b0846e2014-05-24 12:50:23 +00004670 case Match_MSR:
4671 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004672 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004673 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004674 // Any time we get here, there's nothing fancy to do. Just get the
4675 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004676 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004677 if (ErrorLoc == SMLoc())
4678 ErrorLoc = IDLoc;
Sander de Smalen0325e302018-07-02 07:34:52 +00004679 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004680 }
4681 }
4682
4683 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004684}
4685
4686/// ParseDirective parses the arm specific directives
4687bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004688 const MCObjectFileInfo::Environment Format =
4689 getContext().getObjectFileInfo()->getObjectFileType();
4690 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4691 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004692
Tim Northover3b0846e2014-05-24 12:50:23 +00004693 StringRef IDVal = DirectiveID.getIdentifier();
4694 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004695 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004696 parseDirectiveArch(Loc);
4697 else if (IDVal == ".cpu")
4698 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00004699 else if (IDVal == ".tlsdesccall")
4700 parseDirectiveTLSDescCall(Loc);
4701 else if (IDVal == ".ltorg" || IDVal == ".pool")
4702 parseDirectiveLtorg(Loc);
4703 else if (IDVal == ".unreq")
4704 parseDirectiveUnreq(Loc);
4705 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004706 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004707 parseDirectiveInst(Loc);
4708 else
4709 return true;
4710 } else if (IDVal == MCLOHDirectiveName())
4711 parseDirectiveLOH(IDVal, Loc);
4712 else
4713 return true;
4714 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004715}
4716
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004717static const struct {
4718 const char *Name;
4719 const FeatureBitset Features;
4720} ExtensionMap[] = {
4721 { "crc", {AArch64::FeatureCRC} },
4722 { "crypto", {AArch64::FeatureCrypto} },
4723 { "fp", {AArch64::FeatureFPARMv8} },
4724 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004725 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004726 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004727
4728 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004729 { "pan", {} },
4730 { "lor", {} },
4731 { "rdma", {} },
4732 { "profile", {} },
4733};
4734
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004735/// parseDirectiveArch
4736/// ::= .arch token
4737bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4738 SMLoc ArchLoc = getLoc();
4739
4740 StringRef Arch, ExtensionString;
4741 std::tie(Arch, ExtensionString) =
4742 getParser().parseStringToEndOfStatement().trim().split('+');
4743
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004744 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4745 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004746 return Error(ArchLoc, "unknown arch name");
4747
4748 if (parseToken(AsmToken::EndOfStatement))
4749 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004750
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004751 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004752 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004753 AArch64::getArchFeatures(ID, AArch64Features);
4754 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4755 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004756
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004757 MCSubtargetInfo &STI = copySTI();
4758 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4759 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4760
4761 SmallVector<StringRef, 4> RequestedExtensions;
4762 if (!ExtensionString.empty())
4763 ExtensionString.split(RequestedExtensions, '+');
4764
4765 FeatureBitset Features = STI.getFeatureBits();
4766 for (auto Name : RequestedExtensions) {
4767 bool EnableFeature = true;
4768
4769 if (Name.startswith_lower("no")) {
4770 EnableFeature = false;
4771 Name = Name.substr(2);
4772 }
4773
4774 for (const auto &Extension : ExtensionMap) {
4775 if (Extension.Name != Name)
4776 continue;
4777
4778 if (Extension.Features.none())
4779 report_fatal_error("unsupported architectural extension: " + Name);
4780
4781 FeatureBitset ToggleFeatures = EnableFeature
4782 ? (~Features & Extension.Features)
4783 : ( Features & Extension.Features);
4784 uint64_t Features =
4785 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4786 setAvailableFeatures(Features);
4787 break;
4788 }
4789 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004790 return false;
4791}
4792
Tim Northover8b96c7e2017-05-15 19:42:15 +00004793static SMLoc incrementLoc(SMLoc L, int Offset) {
4794 return SMLoc::getFromPointer(L.getPointer() + Offset);
4795}
4796
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004797/// parseDirectiveCPU
4798/// ::= .cpu id
4799bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004800 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004801
4802 StringRef CPU, ExtensionString;
4803 std::tie(CPU, ExtensionString) =
4804 getParser().parseStringToEndOfStatement().trim().split('+');
4805
Nirav Davee833c6c2016-11-08 18:31:04 +00004806 if (parseToken(AsmToken::EndOfStatement))
4807 return true;
4808
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004809 SmallVector<StringRef, 4> RequestedExtensions;
4810 if (!ExtensionString.empty())
4811 ExtensionString.split(RequestedExtensions, '+');
4812
4813 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4814 // once that is tablegen'ed
4815 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004816 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004817 return false;
4818 }
4819
4820 MCSubtargetInfo &STI = copySTI();
4821 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004822 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004823
4824 FeatureBitset Features = STI.getFeatureBits();
4825 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004826 // Advance source location past '+'.
4827 CurLoc = incrementLoc(CurLoc, 1);
4828
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004829 bool EnableFeature = true;
4830
4831 if (Name.startswith_lower("no")) {
4832 EnableFeature = false;
4833 Name = Name.substr(2);
4834 }
4835
Tim Northover8b96c7e2017-05-15 19:42:15 +00004836 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004837 for (const auto &Extension : ExtensionMap) {
4838 if (Extension.Name != Name)
4839 continue;
4840
4841 if (Extension.Features.none())
4842 report_fatal_error("unsupported architectural extension: " + Name);
4843
4844 FeatureBitset ToggleFeatures = EnableFeature
4845 ? (~Features & Extension.Features)
4846 : ( Features & Extension.Features);
4847 uint64_t Features =
4848 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4849 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004850 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004851
4852 break;
4853 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004854
4855 if (!FoundExtension)
4856 Error(CurLoc, "unsupported architectural extension");
4857
4858 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004859 }
4860 return false;
4861}
4862
Chad Rosierdcd2a302014-10-22 20:35:57 +00004863/// parseDirectiveInst
4864/// ::= .inst opcode [, ...]
4865bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004866 if (getLexer().is(AsmToken::EndOfStatement))
4867 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004868
Nirav Davee833c6c2016-11-08 18:31:04 +00004869 auto parseOp = [&]() -> bool {
4870 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004871 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004872 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4873 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004874 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004875 if (check(!Value, L, "expected constant expression"))
4876 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004877 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004878 return false;
4879 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004880
Nirav Davee833c6c2016-11-08 18:31:04 +00004881 if (parseMany(parseOp))
4882 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004883 return false;
4884}
4885
Tim Northover3b0846e2014-05-24 12:50:23 +00004886// parseDirectiveTLSDescCall:
4887// ::= .tlsdesccall symbol
4888bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4889 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004890 if (check(getParser().parseIdentifier(Name), L,
4891 "expected symbol after directive") ||
4892 parseToken(AsmToken::EndOfStatement))
4893 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004894
Jim Grosbach6f482002015-05-18 18:43:14 +00004895 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004896 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4897 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004898
4899 MCInst Inst;
4900 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004901 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004902
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004903 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004904 return false;
4905}
4906
4907/// ::= .loh <lohName | lohId> label1, ..., labelN
4908/// The number of arguments depends on the loh identifier.
4909bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004910 MCLOHType Kind;
4911 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4912 if (getParser().getTok().isNot(AsmToken::Integer))
4913 return TokError("expected an identifier or a number in directive");
4914 // We successfully get a numeric value for the identifier.
4915 // Check if it is valid.
4916 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004917 if (Id <= -1U && !isValidMCLOHType(Id))
4918 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004919 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004920 } else {
4921 StringRef Name = getTok().getIdentifier();
4922 // We successfully parse an identifier.
4923 // Check if it is a recognized one.
4924 int Id = MCLOHNameToId(Name);
4925
4926 if (Id == -1)
4927 return TokError("invalid identifier in directive");
4928 Kind = (MCLOHType)Id;
4929 }
4930 // Consume the identifier.
4931 Lex();
4932 // Get the number of arguments of this LOH.
4933 int NbArgs = MCLOHIdToNbArgs(Kind);
4934
4935 assert(NbArgs != -1 && "Invalid number of arguments");
4936
4937 SmallVector<MCSymbol *, 3> Args;
4938 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4939 StringRef Name;
4940 if (getParser().parseIdentifier(Name))
4941 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004942 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004943
4944 if (Idx + 1 == NbArgs)
4945 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004946 if (parseToken(AsmToken::Comma,
4947 "unexpected token in '" + Twine(IDVal) + "' directive"))
4948 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004949 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004950 if (parseToken(AsmToken::EndOfStatement,
4951 "unexpected token in '" + Twine(IDVal) + "' directive"))
4952 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004953
4954 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4955 return false;
4956}
4957
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004958/// parseDirectiveLtorg
4959/// ::= .ltorg | .pool
4960bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004961 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4962 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004963 getTargetStreamer().emitCurrentConstantPool();
4964 return false;
4965}
4966
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004967/// parseDirectiveReq
4968/// ::= name .req registername
4969bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004970 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004971 Parser.Lex(); // Eat the '.req' token.
4972 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004973 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004974 unsigned RegNum;
4975 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004976
Sander de Smalen50d87022018-04-19 07:35:08 +00004977 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004978 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004979 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004980 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004981
Sander de Smalen50d87022018-04-19 07:35:08 +00004982 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004983 return true;
4984
Sander de Smalen50d87022018-04-19 07:35:08 +00004985 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004986 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004987 }
4988
Sander de Smalen50d87022018-04-19 07:35:08 +00004989 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004990 StringRef Kind;
4991 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004992 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004993 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004994
Sander de Smalen50d87022018-04-19 07:35:08 +00004995 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004996 return true;
4997
Sander de Smalen50d87022018-04-19 07:35:08 +00004998 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004999 return Error(SRegLoc,
5000 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00005001 }
5002
Sander de Smalen50d87022018-04-19 07:35:08 +00005003 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00005004 StringRef Kind;
5005 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005006 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00005007
Sander de Smalen50d87022018-04-19 07:35:08 +00005008 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00005009 return true;
5010
Sander de Smalen50d87022018-04-19 07:35:08 +00005011 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00005012 return Error(SRegLoc,
5013 "sve predicate register without type specifier expected");
5014 }
5015
Sander de Smalen50d87022018-04-19 07:35:08 +00005016 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00005017 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005018
5019 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00005020 if (parseToken(AsmToken::EndOfStatement,
5021 "unexpected input in .req directive"))
5022 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005023
Sander de Smalen8e607342017-11-15 15:44:43 +00005024 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00005025 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005026 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
5027
Nirav Dave2364748a2016-09-16 18:30:20 +00005028 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005029}
5030
5031/// parseDirectiveUneq
5032/// ::= .unreq registername
5033bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005034 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00005035 if (getTok().isNot(AsmToken::Identifier))
5036 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005037 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
5038 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00005039 if (parseToken(AsmToken::EndOfStatement))
5040 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005041 return false;
5042}
5043
Tim Northover3b0846e2014-05-24 12:50:23 +00005044bool
5045AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
5046 AArch64MCExpr::VariantKind &ELFRefKind,
5047 MCSymbolRefExpr::VariantKind &DarwinRefKind,
5048 int64_t &Addend) {
5049 ELFRefKind = AArch64MCExpr::VK_INVALID;
5050 DarwinRefKind = MCSymbolRefExpr::VK_None;
5051 Addend = 0;
5052
5053 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5054 ELFRefKind = AE->getKind();
5055 Expr = AE->getSubExpr();
5056 }
5057
5058 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5059 if (SE) {
5060 // It's a simple symbol reference with no addend.
5061 DarwinRefKind = SE->getKind();
5062 return true;
5063 }
5064
5065 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
5066 if (!BE)
5067 return false;
5068
5069 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
5070 if (!SE)
5071 return false;
5072 DarwinRefKind = SE->getKind();
5073
5074 if (BE->getOpcode() != MCBinaryExpr::Add &&
5075 BE->getOpcode() != MCBinaryExpr::Sub)
5076 return false;
5077
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00005078 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00005079 // on here than we can deal with.
5080 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
5081 if (!AddendExpr)
5082 return false;
5083
5084 Addend = AddendExpr->getValue();
5085 if (BE->getOpcode() == MCBinaryExpr::Sub)
5086 Addend = -Addend;
5087
5088 // It's some symbol reference + a constant addend, but really
5089 // shouldn't use both Darwin and ELF syntax.
5090 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5091 DarwinRefKind == MCSymbolRefExpr::VK_None;
5092}
5093
5094/// Force static initialization.
5095extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00005096 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5097 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5098 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00005099}
5100
5101#define GET_REGISTER_MATCHER
5102#define GET_SUBTARGET_FEATURE_NAME
5103#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00005104#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00005105#include "AArch64GenAsmMatcher.inc"
5106
5107// Define this matcher function after the auto-generated include so we
5108// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00005109unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00005110 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005111 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00005112 // If the kind is a token for a literal immediate, check if our asm
5113 // operand matches. This is for InstAliases which have a fixed-value
5114 // immediate in the syntax.
5115 int64_t ExpectedVal;
5116 switch (Kind) {
5117 default:
5118 return Match_InvalidOperand;
5119 case MCK__35_0:
5120 ExpectedVal = 0;
5121 break;
5122 case MCK__35_1:
5123 ExpectedVal = 1;
5124 break;
5125 case MCK__35_12:
5126 ExpectedVal = 12;
5127 break;
5128 case MCK__35_16:
5129 ExpectedVal = 16;
5130 break;
5131 case MCK__35_2:
5132 ExpectedVal = 2;
5133 break;
5134 case MCK__35_24:
5135 ExpectedVal = 24;
5136 break;
5137 case MCK__35_3:
5138 ExpectedVal = 3;
5139 break;
5140 case MCK__35_32:
5141 ExpectedVal = 32;
5142 break;
5143 case MCK__35_4:
5144 ExpectedVal = 4;
5145 break;
5146 case MCK__35_48:
5147 ExpectedVal = 48;
5148 break;
5149 case MCK__35_6:
5150 ExpectedVal = 6;
5151 break;
5152 case MCK__35_64:
5153 ExpectedVal = 64;
5154 break;
5155 case MCK__35_8:
5156 ExpectedVal = 8;
5157 break;
5158 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005159 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005160 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005161 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005162 if (!CE)
5163 return Match_InvalidOperand;
5164 if (CE->getValue() == ExpectedVal)
5165 return Match_Success;
5166 return Match_InvalidOperand;
5167}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005168
Alex Bradbury58eba092016-11-01 16:32:05 +00005169OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005170AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5171
5172 SMLoc S = getLoc();
5173
5174 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5175 Error(S, "expected register");
5176 return MatchOperand_ParseFail;
5177 }
5178
Sander de Smalen50d87022018-04-19 07:35:08 +00005179 unsigned FirstReg;
5180 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5181 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005182 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005183
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005184 const MCRegisterClass &WRegClass =
5185 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5186 const MCRegisterClass &XRegClass =
5187 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5188
5189 bool isXReg = XRegClass.contains(FirstReg),
5190 isWReg = WRegClass.contains(FirstReg);
5191 if (!isXReg && !isWReg) {
5192 Error(S, "expected first even register of a "
5193 "consecutive same-size even/odd register pair");
5194 return MatchOperand_ParseFail;
5195 }
5196
5197 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5198 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5199
5200 if (FirstEncoding & 0x1) {
5201 Error(S, "expected first even register of a "
5202 "consecutive same-size even/odd register pair");
5203 return MatchOperand_ParseFail;
5204 }
5205
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005206 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005207 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005208 return MatchOperand_ParseFail;
5209 }
5210 // Eat the comma
5211 getParser().Lex();
5212
5213 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005214 unsigned SecondReg;
5215 Res = tryParseScalarRegister(SecondReg);
5216 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005217 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005218
Eugene Zelenko049b0172017-01-06 00:30:53 +00005219 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005220 (isXReg && !XRegClass.contains(SecondReg)) ||
5221 (isWReg && !WRegClass.contains(SecondReg))) {
5222 Error(E,"expected second odd register of a "
5223 "consecutive same-size even/odd register pair");
5224 return MatchOperand_ParseFail;
5225 }
Joel Jones504bf332016-10-24 13:37:13 +00005226
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005227 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005228 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005229 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5230 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5231 } else {
5232 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5233 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5234 }
5235
Florian Hahnc4422242017-11-07 13:07:50 +00005236 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5237 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005238
5239 return MatchOperand_Success;
5240}
Florian Hahn91f11e52017-11-07 16:45:48 +00005241
Sander de Smaleneb896b12018-04-25 09:26:47 +00005242template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005243OperandMatchResultTy
5244AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005245 const SMLoc S = getLoc();
5246 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005247 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005248 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005249
Sander de Smalen8e607342017-11-15 15:44:43 +00005250 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005251 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005252
5253 if (Res != MatchOperand_Success)
5254 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005255
5256 if (ParseSuffix && Kind.empty())
5257 return MatchOperand_NoMatch;
5258
Sander de Smalen73937b72018-04-11 07:36:10 +00005259 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5260 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005261 return MatchOperand_NoMatch;
5262
Sander de Smalen73937b72018-04-11 07:36:10 +00005263 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005264
5265 // No shift/extend is the default.
5266 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5267 Operands.push_back(AArch64Operand::CreateVectorReg(
5268 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5269
Sander de Smalenc33d6682018-06-04 06:40:55 +00005270 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5271 if (Res == MatchOperand_ParseFail)
5272 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005273 return MatchOperand_Success;
5274 }
5275
5276 // Eat the comma
5277 getParser().Lex();
5278
5279 // Match the shift
5280 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5281 Res = tryParseOptionalShiftExtend(ExtOpnd);
5282 if (Res != MatchOperand_Success)
5283 return Res;
5284
5285 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005286 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005287 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5288 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5289 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005290
5291 return MatchOperand_Success;
5292}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005293
5294OperandMatchResultTy
5295AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5296 MCAsmParser &Parser = getParser();
5297
5298 SMLoc SS = getLoc();
5299 const AsmToken &TokE = Parser.getTok();
5300 bool IsHash = TokE.is(AsmToken::Hash);
5301
5302 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5303 return MatchOperand_NoMatch;
5304
5305 int64_t Pattern;
5306 if (IsHash) {
5307 Parser.Lex(); // Eat hash
5308
5309 // Parse the immediate operand.
5310 const MCExpr *ImmVal;
5311 SS = getLoc();
5312 if (Parser.parseExpression(ImmVal))
5313 return MatchOperand_ParseFail;
5314
5315 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5316 if (!MCE)
5317 return MatchOperand_ParseFail;
5318
5319 Pattern = MCE->getValue();
5320 } else {
5321 // Parse the pattern
5322 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5323 if (!Pat)
5324 return MatchOperand_NoMatch;
5325
5326 Parser.Lex();
5327 Pattern = Pat->Encoding;
5328 assert(Pattern >= 0 && Pattern < 32);
5329 }
5330
5331 Operands.push_back(
5332 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5333 SS, getLoc(), getContext()));
5334
5335 return MatchOperand_Success;
5336}