blob: 384b474abe82b1359e68fc346f4e6e25df0f6307 [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"
Sander de Smalen9b333092018-07-30 15:42:46 +000014#include "AArch64InstrInfo.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000015#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000016#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000017#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000018#include "llvm/ADT/ArrayRef.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000019#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000020#include "llvm/ADT/SmallVector.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000021#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000022#include "llvm/ADT/StringMap.h"
23#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000024#include "llvm/ADT/StringSwitch.h"
25#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000026#include "llvm/MC/MCContext.h"
27#include "llvm/MC/MCExpr.h"
28#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000029#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000030#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000031#include "llvm/MC/MCParser/MCAsmLexer.h"
32#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000033#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000034#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000035#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000036#include "llvm/MC/MCRegisterInfo.h"
37#include "llvm/MC/MCStreamer.h"
38#include "llvm/MC/MCSubtargetInfo.h"
39#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000040#include "llvm/MC/MCTargetOptions.h"
41#include "llvm/MC/SubtargetFeature.h"
David Green85d6a552018-09-18 09:44:53 +000042#include "llvm/MC/MCValue.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000043#include "llvm/Support/Casting.h"
44#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000045#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000046#include "llvm/Support/MathExtras.h"
47#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000048#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000049#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000050#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000051#include <cassert>
52#include <cctype>
53#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000054#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000055#include <string>
56#include <tuple>
57#include <utility>
58#include <vector>
59
Tim Northover3b0846e2014-05-24 12:50:23 +000060using namespace llvm;
61
62namespace {
63
Sander de Smalencd6be962017-12-20 11:02:42 +000064enum class RegKind {
65 Scalar,
66 NeonVector,
67 SVEDataVector,
68 SVEPredicateVector
69};
Florian Hahnc4422242017-11-07 13:07:50 +000070
Sander de Smalen0325e302018-07-02 07:34:52 +000071enum RegConstraintEqualityTy {
72 EqualsReg,
73 EqualsSuperReg,
74 EqualsSubReg
75};
76
Tim Northover3b0846e2014-05-24 12:50:23 +000077class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000078private:
79 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000080
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000081 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000082 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000083
Sander de Smalen9b333092018-07-30 15:42:46 +000084 class PrefixInfo {
85 public:
86 static PrefixInfo CreateFromInst(const MCInst &Inst, uint64_t TSFlags) {
87 PrefixInfo Prefix;
88 switch (Inst.getOpcode()) {
89 case AArch64::MOVPRFX_ZZ:
90 Prefix.Active = true;
91 Prefix.Dst = Inst.getOperand(0).getReg();
92 break;
93 case AArch64::MOVPRFX_ZPmZ_B:
94 case AArch64::MOVPRFX_ZPmZ_H:
95 case AArch64::MOVPRFX_ZPmZ_S:
96 case AArch64::MOVPRFX_ZPmZ_D:
97 Prefix.Active = true;
98 Prefix.Predicated = true;
99 Prefix.ElementSize = TSFlags & AArch64::ElementSizeMask;
100 assert(Prefix.ElementSize != AArch64::ElementSizeNone &&
101 "No destructive element size set for movprfx");
102 Prefix.Dst = Inst.getOperand(0).getReg();
103 Prefix.Pg = Inst.getOperand(2).getReg();
104 break;
105 case AArch64::MOVPRFX_ZPzZ_B:
106 case AArch64::MOVPRFX_ZPzZ_H:
107 case AArch64::MOVPRFX_ZPzZ_S:
108 case AArch64::MOVPRFX_ZPzZ_D:
109 Prefix.Active = true;
110 Prefix.Predicated = true;
111 Prefix.ElementSize = TSFlags & AArch64::ElementSizeMask;
112 assert(Prefix.ElementSize != AArch64::ElementSizeNone &&
113 "No destructive element size set for movprfx");
114 Prefix.Dst = Inst.getOperand(0).getReg();
115 Prefix.Pg = Inst.getOperand(1).getReg();
116 break;
117 default:
118 break;
119 }
120
121 return Prefix;
122 }
123
124 PrefixInfo() : Active(false), Predicated(false) {}
125 bool isActive() const { return Active; }
126 bool isPredicated() const { return Predicated; }
127 unsigned getElementSize() const {
128 assert(Predicated);
129 return ElementSize;
130 }
131 unsigned getDstReg() const { return Dst; }
132 unsigned getPgReg() const {
133 assert(Predicated);
134 return Pg;
135 }
136
137 private:
138 bool Active;
139 bool Predicated;
140 unsigned ElementSize;
141 unsigned Dst;
142 unsigned Pg;
143 } NextPrefix;
144
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000145 AArch64TargetStreamer &getTargetStreamer() {
146 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
147 return static_cast<AArch64TargetStreamer &>(TS);
148 }
149
Rafael Espindola961d4692014-11-11 05:18:41 +0000150 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +0000151
152 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +0000153 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000154 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
155 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +0000156 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000157 bool parseRegister(OperandVector &Operands);
158 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000159 bool parseNeonVectorList(OperandVector &Operands);
Sander de Smalen18ac8f92018-06-15 15:47:44 +0000160 bool parseOptionalMulOperand(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000161 bool parseOperand(OperandVector &Operands, bool isCondCode,
162 bool invertCondCode);
163
Sander de Smalen0325e302018-07-02 07:34:52 +0000164 bool showMatchError(SMLoc Loc, unsigned ErrCode, uint64_t ErrorInfo,
165 OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000166
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +0000167 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +0000168 bool parseDirectiveCPU(SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +0000169 bool parseDirectiveInst(SMLoc L);
170
Tim Northover3b0846e2014-05-24 12:50:23 +0000171 bool parseDirectiveTLSDescCall(SMLoc L);
172
173 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000174 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000175
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000176 bool parseDirectiveReq(StringRef Name, SMLoc L);
177 bool parseDirectiveUnreq(SMLoc L);
Luke Cheesemanf57d7d82018-12-18 10:37:42 +0000178 bool parseDirectiveCFINegateRAState();
Luke Cheeseman41a9e532018-12-21 10:45:08 +0000179 bool parseDirectiveCFIBKeyFrame();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000180
Sander de Smalen9b333092018-07-30 15:42:46 +0000181 bool validateInstruction(MCInst &Inst, SMLoc &IDLoc,
182 SmallVectorImpl<SMLoc> &Loc);
Tim Northover3b0846e2014-05-24 12:50:23 +0000183 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
184 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000185 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000186 bool MatchingInlineAsm) override;
187/// @name Auto-generated Match Functions
188/// {
189
190#define GET_ASSEMBLER_HEADER
191#include "AArch64GenAsmMatcher.inc"
192
193 /// }
194
Sander de Smalen50d87022018-04-19 07:35:08 +0000195 OperandMatchResultTy tryParseScalarRegister(unsigned &Reg);
196 OperandMatchResultTy tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +0000197 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000198 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
199 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
200 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
201 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
202 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
Sander de Smalen93380372018-05-14 11:54:41 +0000203 template <bool IsSVEPrefetch = false>
Tim Northover3b0846e2014-05-24 12:50:23 +0000204 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000205 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000206 OperandMatchResultTy tryParseBTIHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000207 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
208 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000209 template<bool AddFPZeroAsLiteral>
Tim Northover3b0846e2014-05-24 12:50:23 +0000210 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
Sander de Smalen62770792018-05-25 09:47:52 +0000211 OperandMatchResultTy tryParseImmWithOptionalShift(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000212 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000213 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000214 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000215 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Sander de Smalen0325e302018-07-02 07:34:52 +0000216 template <bool ParseShiftExtend,
217 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg>
Sander de Smalen149916d2018-04-20 07:24:20 +0000218 OperandMatchResultTy tryParseGPROperand(OperandVector &Operands);
Sander de Smaleneb896b12018-04-25 09:26:47 +0000219 template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +0000220 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000221 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000222 template <RegKind VectorKind>
223 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
224 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000225 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000226
227public:
228 enum AArch64MatchResultTy {
229 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
230#define GET_OPERAND_DIAGNOSTIC_TYPES
231#include "AArch64GenAsmMatcher.inc"
232 };
Joel Jones504bf332016-10-24 13:37:13 +0000233 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000234
Akira Hatanakab11ef082015-11-14 06:35:56 +0000235 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000236 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000237 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000238 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000239 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000240 MCStreamer &S = getParser().getStreamer();
241 if (S.getTargetStreamer() == nullptr)
242 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000243
Alex Bradbury0a59f182018-05-23 11:17:20 +0000244 // Alias .hword/.word/xword to the target-independent .2byte/.4byte/.8byte
245 // directives as they have the same form and semantics:
246 /// ::= (.hword | .word | .xword ) [ expression (, expression)* ]
247 Parser.addAliasForDirective(".hword", ".2byte");
248 Parser.addAliasForDirective(".word", ".4byte");
249 Parser.addAliasForDirective(".xword", ".8byte");
250
Tim Northover3b0846e2014-05-24 12:50:23 +0000251 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000252 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000253 }
254
Sander de Smalen0325e302018-07-02 07:34:52 +0000255 bool regsEqual(const MCParsedAsmOperand &Op1,
256 const MCParsedAsmOperand &Op2) const override;
Tim Northover3b0846e2014-05-24 12:50:23 +0000257 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
258 SMLoc NameLoc, OperandVector &Operands) override;
259 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
260 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000261 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000262 unsigned Kind) override;
263
264 static bool classifySymbolRef(const MCExpr *Expr,
265 AArch64MCExpr::VariantKind &ELFRefKind,
266 MCSymbolRefExpr::VariantKind &DarwinRefKind,
267 int64_t &Addend);
268};
Tim Northover3b0846e2014-05-24 12:50:23 +0000269
270/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
271/// instruction.
272class AArch64Operand : public MCParsedAsmOperand {
273private:
274 enum KindTy {
275 k_Immediate,
276 k_ShiftedImm,
277 k_CondCode,
278 k_Register,
279 k_VectorList,
280 k_VectorIndex,
281 k_Token,
282 k_SysReg,
283 k_SysCR,
284 k_Prefetch,
285 k_ShiftExtend,
286 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000287 k_Barrier,
288 k_PSBHint,
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000289 k_BTIHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000290 } Kind;
291
292 SMLoc StartLoc, EndLoc;
293
294 struct TokOp {
295 const char *Data;
296 unsigned Length;
297 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
298 };
299
Sander de Smalen149916d2018-04-20 07:24:20 +0000300 // Separate shift/extend operand.
301 struct ShiftExtendOp {
302 AArch64_AM::ShiftExtendType Type;
303 unsigned Amount;
304 bool HasExplicitAmount;
305 };
306
Tim Northover3b0846e2014-05-24 12:50:23 +0000307 struct RegOp {
308 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000309 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000310 int ElementWidth;
Sander de Smalen149916d2018-04-20 07:24:20 +0000311
Sander de Smalen0325e302018-07-02 07:34:52 +0000312 // The register may be allowed as a different register class,
313 // e.g. for GPR64as32 or GPR32as64.
314 RegConstraintEqualityTy EqualityTy;
315
Sander de Smalen149916d2018-04-20 07:24:20 +0000316 // In some cases the shift/extend needs to be explicitly parsed together
317 // with the register, rather than as a separate operand. This is needed
318 // for addressing modes where the instruction as a whole dictates the
319 // scaling/extend, rather than specific bits in the instruction.
320 // By parsing them as a single operand, we avoid the need to pass an
321 // extra operand in all CodeGen patterns (because all operands need to
322 // have an associated value), and we avoid the need to update TableGen to
323 // accept operands that have no associated bits in the instruction.
324 //
325 // An added benefit of parsing them together is that the assembler
326 // can give a sensible diagnostic if the scaling is not correct.
327 //
328 // The default is 'lsl #0' (HasExplicitAmount = false) if no
329 // ShiftExtend is specified.
330 ShiftExtendOp ShiftExtend;
Tim Northover3b0846e2014-05-24 12:50:23 +0000331 };
332
333 struct VectorListOp {
334 unsigned RegNum;
335 unsigned Count;
336 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000337 unsigned ElementWidth;
338 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000339 };
340
341 struct VectorIndexOp {
342 unsigned Val;
343 };
344
345 struct ImmOp {
346 const MCExpr *Val;
347 };
348
349 struct ShiftedImmOp {
350 const MCExpr *Val;
351 unsigned ShiftAmount;
352 };
353
354 struct CondCodeOp {
355 AArch64CC::CondCode Code;
356 };
357
358 struct FPImmOp {
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000359 uint64_t Val; // APFloat value bitcasted to uint64_t.
360 bool IsExact; // describes whether parsed value was exact.
Tim Northover3b0846e2014-05-24 12:50:23 +0000361 };
362
363 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000364 const char *Data;
365 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000366 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000367 };
368
369 struct SysRegOp {
370 const char *Data;
371 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000372 uint32_t MRSReg;
373 uint32_t MSRReg;
374 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000375 };
376
377 struct SysCRImmOp {
378 unsigned Val;
379 };
380
381 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000382 const char *Data;
383 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000384 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000385 };
386
Oliver Stannarda34e4702015-12-01 10:48:51 +0000387 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000388 const char *Data;
389 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000390 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000391 };
392
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000393 struct BTIHintOp {
394 const char *Data;
395 unsigned Length;
396 unsigned Val;
397 };
398
Tim Northover3b0846e2014-05-24 12:50:23 +0000399 struct ExtendOp {
400 unsigned Val;
401 };
402
403 union {
404 struct TokOp Tok;
405 struct RegOp Reg;
406 struct VectorListOp VectorList;
407 struct VectorIndexOp VectorIndex;
408 struct ImmOp Imm;
409 struct ShiftedImmOp ShiftedImm;
410 struct CondCodeOp CondCode;
411 struct FPImmOp FPImm;
412 struct BarrierOp Barrier;
413 struct SysRegOp SysReg;
414 struct SysCRImmOp SysCRImm;
415 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000416 struct PSBHintOp PSBHint;
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000417 struct BTIHintOp BTIHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000418 struct ShiftExtendOp ShiftExtend;
419 };
420
421 // Keep the MCContext around as the MCExprs may need manipulated during
422 // the add<>Operands() calls.
423 MCContext &Ctx;
424
David Blaikie960ea3f2014-06-08 16:18:35 +0000425public:
David Blaikie9f380a32015-03-16 18:06:57 +0000426 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000427
Tim Northover3b0846e2014-05-24 12:50:23 +0000428 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
429 Kind = o.Kind;
430 StartLoc = o.StartLoc;
431 EndLoc = o.EndLoc;
432 switch (Kind) {
433 case k_Token:
434 Tok = o.Tok;
435 break;
436 case k_Immediate:
437 Imm = o.Imm;
438 break;
439 case k_ShiftedImm:
440 ShiftedImm = o.ShiftedImm;
441 break;
442 case k_CondCode:
443 CondCode = o.CondCode;
444 break;
445 case k_FPImm:
446 FPImm = o.FPImm;
447 break;
448 case k_Barrier:
449 Barrier = o.Barrier;
450 break;
451 case k_Register:
452 Reg = o.Reg;
453 break;
454 case k_VectorList:
455 VectorList = o.VectorList;
456 break;
457 case k_VectorIndex:
458 VectorIndex = o.VectorIndex;
459 break;
460 case k_SysReg:
461 SysReg = o.SysReg;
462 break;
463 case k_SysCR:
464 SysCRImm = o.SysCRImm;
465 break;
466 case k_Prefetch:
467 Prefetch = o.Prefetch;
468 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000469 case k_PSBHint:
470 PSBHint = o.PSBHint;
471 break;
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000472 case k_BTIHint:
473 BTIHint = o.BTIHint;
474 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000475 case k_ShiftExtend:
476 ShiftExtend = o.ShiftExtend;
477 break;
478 }
479 }
480
481 /// getStartLoc - Get the location of the first token of this operand.
482 SMLoc getStartLoc() const override { return StartLoc; }
483 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000484 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000485
486 StringRef getToken() const {
487 assert(Kind == k_Token && "Invalid access!");
488 return StringRef(Tok.Data, Tok.Length);
489 }
490
491 bool isTokenSuffix() const {
492 assert(Kind == k_Token && "Invalid access!");
493 return Tok.IsSuffix;
494 }
495
496 const MCExpr *getImm() const {
497 assert(Kind == k_Immediate && "Invalid access!");
498 return Imm.Val;
499 }
500
501 const MCExpr *getShiftedImmVal() const {
502 assert(Kind == k_ShiftedImm && "Invalid access!");
503 return ShiftedImm.Val;
504 }
505
506 unsigned getShiftedImmShift() const {
507 assert(Kind == k_ShiftedImm && "Invalid access!");
508 return ShiftedImm.ShiftAmount;
509 }
510
511 AArch64CC::CondCode getCondCode() const {
512 assert(Kind == k_CondCode && "Invalid access!");
513 return CondCode.Code;
514 }
515
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000516 APFloat getFPImm() const {
517 assert (Kind == k_FPImm && "Invalid access!");
518 return APFloat(APFloat::IEEEdouble(), APInt(64, FPImm.Val, true));
519 }
520
521 bool getFPImmIsExact() const {
522 assert (Kind == k_FPImm && "Invalid access!");
523 return FPImm.IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +0000524 }
525
526 unsigned getBarrier() const {
527 assert(Kind == k_Barrier && "Invalid access!");
528 return Barrier.Val;
529 }
530
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000531 StringRef getBarrierName() const {
532 assert(Kind == k_Barrier && "Invalid access!");
533 return StringRef(Barrier.Data, Barrier.Length);
534 }
535
Tim Northover3b0846e2014-05-24 12:50:23 +0000536 unsigned getReg() const override {
537 assert(Kind == k_Register && "Invalid access!");
538 return Reg.RegNum;
539 }
540
Sander de Smalen0325e302018-07-02 07:34:52 +0000541 RegConstraintEqualityTy getRegEqualityTy() const {
542 assert(Kind == k_Register && "Invalid access!");
543 return Reg.EqualityTy;
544 }
545
Tim Northover3b0846e2014-05-24 12:50:23 +0000546 unsigned getVectorListStart() const {
547 assert(Kind == k_VectorList && "Invalid access!");
548 return VectorList.RegNum;
549 }
550
551 unsigned getVectorListCount() const {
552 assert(Kind == k_VectorList && "Invalid access!");
553 return VectorList.Count;
554 }
555
556 unsigned getVectorIndex() const {
557 assert(Kind == k_VectorIndex && "Invalid access!");
558 return VectorIndex.Val;
559 }
560
561 StringRef getSysReg() const {
562 assert(Kind == k_SysReg && "Invalid access!");
563 return StringRef(SysReg.Data, SysReg.Length);
564 }
565
Tim Northover3b0846e2014-05-24 12:50:23 +0000566 unsigned getSysCR() const {
567 assert(Kind == k_SysCR && "Invalid access!");
568 return SysCRImm.Val;
569 }
570
571 unsigned getPrefetch() const {
572 assert(Kind == k_Prefetch && "Invalid access!");
573 return Prefetch.Val;
574 }
575
Oliver Stannarda34e4702015-12-01 10:48:51 +0000576 unsigned getPSBHint() const {
577 assert(Kind == k_PSBHint && "Invalid access!");
578 return PSBHint.Val;
579 }
580
581 StringRef getPSBHintName() const {
582 assert(Kind == k_PSBHint && "Invalid access!");
583 return StringRef(PSBHint.Data, PSBHint.Length);
584 }
585
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000586 unsigned getBTIHint() const {
587 assert(Kind == k_BTIHint && "Invalid access!");
588 return BTIHint.Val;
589 }
590
591 StringRef getBTIHintName() const {
592 assert(Kind == k_BTIHint && "Invalid access!");
593 return StringRef(BTIHint.Data, BTIHint.Length);
594 }
595
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000596 StringRef getPrefetchName() const {
597 assert(Kind == k_Prefetch && "Invalid access!");
598 return StringRef(Prefetch.Data, Prefetch.Length);
599 }
600
Tim Northover3b0846e2014-05-24 12:50:23 +0000601 AArch64_AM::ShiftExtendType getShiftExtendType() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000602 if (Kind == k_ShiftExtend)
603 return ShiftExtend.Type;
604 if (Kind == k_Register)
605 return Reg.ShiftExtend.Type;
606 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000607 }
608
609 unsigned getShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000610 if (Kind == k_ShiftExtend)
611 return ShiftExtend.Amount;
612 if (Kind == k_Register)
613 return Reg.ShiftExtend.Amount;
614 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000615 }
616
617 bool hasShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000618 if (Kind == k_ShiftExtend)
619 return ShiftExtend.HasExplicitAmount;
620 if (Kind == k_Register)
621 return Reg.ShiftExtend.HasExplicitAmount;
622 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000623 }
624
625 bool isImm() const override { return Kind == k_Immediate; }
626 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000627
Sjoerd Meijera3dad802018-07-06 12:32:33 +0000628 bool isUImm6() const {
629 if (!isImm())
630 return false;
631 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
632 if (!MCE)
633 return false;
634 int64_t Val = MCE->getValue();
635 return (Val >= 0 && Val < 64);
636 }
637
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000638 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
639
Sander de Smalen50ded902018-04-29 17:33:38 +0000640 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
641 return isImmScaled<Bits, Scale>(true);
642 }
643
644 template <int Bits, int Scale> DiagnosticPredicate isUImmScaled() const {
645 return isImmScaled<Bits, Scale>(false);
646 }
647
Sander de Smalenfe17a782018-04-26 12:54:42 +0000648 template <int Bits, int Scale>
Sander de Smalen50ded902018-04-29 17:33:38 +0000649 DiagnosticPredicate isImmScaled(bool Signed) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000650 if (!isImm())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000651 return DiagnosticPredicateTy::NoMatch;
652
Tim Northover3b0846e2014-05-24 12:50:23 +0000653 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
654 if (!MCE)
Sander de Smalenfe17a782018-04-26 12:54:42 +0000655 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000656
Sander de Smalen50ded902018-04-29 17:33:38 +0000657 int64_t MinVal, MaxVal;
658 if (Signed) {
659 int64_t Shift = Bits - 1;
660 MinVal = (int64_t(1) << Shift) * -Scale;
661 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
662 } else {
663 MinVal = 0;
664 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
665 }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000666
Tim Northover3b0846e2014-05-24 12:50:23 +0000667 int64_t Val = MCE->getValue();
Sander de Smalenfe17a782018-04-26 12:54:42 +0000668 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
669 return DiagnosticPredicateTy::Match;
670
671 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +0000672 }
673
Sander de Smalen0325e302018-07-02 07:34:52 +0000674 DiagnosticPredicate isSVEPattern() const {
Sander de Smalen245e0e62018-01-22 10:46:00 +0000675 if (!isImm())
Sander de Smalen0325e302018-07-02 07:34:52 +0000676 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000677 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
678 if (!MCE)
Sander de Smalen0325e302018-07-02 07:34:52 +0000679 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000680 int64_t Val = MCE->getValue();
Sander de Smalen0325e302018-07-02 07:34:52 +0000681 if (Val >= 0 && Val < 32)
682 return DiagnosticPredicateTy::Match;
683 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000684 }
685
David Green85d6a552018-09-18 09:44:53 +0000686 bool isSymbolicUImm12Offset(const MCExpr *Expr) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000687 AArch64MCExpr::VariantKind ELFRefKind;
688 MCSymbolRefExpr::VariantKind DarwinRefKind;
689 int64_t Addend;
690 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
691 Addend)) {
692 // If we don't understand the expression, assume the best and
693 // let the fixup and relocation code deal with it.
694 return true;
695 }
696
697 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
698 ELFRefKind == AArch64MCExpr::VK_LO12 ||
699 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
700 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
701 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
702 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
703 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
704 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000705 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
706 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
707 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000708 // Note that we don't range-check the addend. It's adjusted modulo page
709 // size when converted, so there is no "out of range" condition when using
710 // @pageoff.
David Green85d6a552018-09-18 09:44:53 +0000711 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000712 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
713 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
714 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
715 return Addend == 0;
716 }
717
718 return false;
719 }
720
721 template <int Scale> bool isUImm12Offset() const {
722 if (!isImm())
723 return false;
724
725 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
726 if (!MCE)
David Green85d6a552018-09-18 09:44:53 +0000727 return isSymbolicUImm12Offset(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +0000728
729 int64_t Val = MCE->getValue();
730 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
731 }
732
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000733 template <int N, int M>
734 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000735 if (!isImm())
736 return false;
737 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
738 if (!MCE)
739 return false;
740 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000741 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000742 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000743
Sander de Smalena1c259c2018-01-29 13:05:38 +0000744 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
745 // a logical immediate can always be represented when inverted.
746 template <typename T>
747 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000748 if (!isImm())
749 return false;
750 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
751 if (!MCE)
752 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000753
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000754 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000755 int64_t SVal = typename std::make_signed<T>::type(Val);
756 int64_t UVal = typename std::make_unsigned<T>::type(Val);
757 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000758 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000759
Sander de Smalena1c259c2018-01-29 13:05:38 +0000760 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000761 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000762
Tim Northover3b0846e2014-05-24 12:50:23 +0000763 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000764
Sander de Smalen62770792018-05-25 09:47:52 +0000765 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
766 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
767 /// immediate that can be shifted by 'Shift'.
768 template <unsigned Width>
769 Optional<std::pair<int64_t, unsigned> > getShiftedVal() const {
770 if (isShiftedImm() && Width == getShiftedImmShift())
771 if (auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
772 return std::make_pair(CE->getValue(), Width);
773
774 if (isImm())
775 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
776 int64_t Val = CE->getValue();
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000777 if ((Val != 0) && (uint64_t(Val >> Width) << Width) == uint64_t(Val))
Sander de Smalen62770792018-05-25 09:47:52 +0000778 return std::make_pair(Val >> Width, Width);
779 else
780 return std::make_pair(Val, 0u);
781 }
782
783 return {};
784 }
785
Tim Northover3b0846e2014-05-24 12:50:23 +0000786 bool isAddSubImm() const {
787 if (!isShiftedImm() && !isImm())
788 return false;
789
790 const MCExpr *Expr;
791
792 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
793 if (isShiftedImm()) {
794 unsigned Shift = ShiftedImm.ShiftAmount;
795 Expr = ShiftedImm.Val;
796 if (Shift != 0 && Shift != 12)
797 return false;
798 } else {
799 Expr = getImm();
800 }
801
802 AArch64MCExpr::VariantKind ELFRefKind;
803 MCSymbolRefExpr::VariantKind DarwinRefKind;
804 int64_t Addend;
805 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
806 DarwinRefKind, Addend)) {
807 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
808 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
809 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
810 || ELFRefKind == AArch64MCExpr::VK_LO12
811 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
812 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
813 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
814 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
815 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
816 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000817 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
818 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
819 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000820 }
821
Sander de Smalen98686c62018-05-29 10:39:49 +0000822 // If it's a constant, it should be a real immediate in range.
Sander de Smalen62770792018-05-25 09:47:52 +0000823 if (auto ShiftedVal = getShiftedVal<12>())
824 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
Diana Picusc93518d2016-10-11 09:17:47 +0000825
826 // If it's an expression, we hope for the best and let the fixup/relocation
827 // code deal with it.
828 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000829 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000830
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000831 bool isAddSubImmNeg() const {
832 if (!isShiftedImm() && !isImm())
833 return false;
834
Sander de Smalen98686c62018-05-29 10:39:49 +0000835 // Otherwise it should be a real negative immediate in range.
836 if (auto ShiftedVal = getShiftedVal<12>())
837 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000838
Sander de Smalen98686c62018-05-29 10:39:49 +0000839 return false;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000840 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000841
Sander de Smalen62770792018-05-25 09:47:52 +0000842 // Signed value in the range -128 to +127. For element widths of
843 // 16 bits or higher it may also be a signed multiple of 256 in the
844 // range -32768 to +32512.
845 // For element-width of 8 bits a range of -128 to 255 is accepted,
846 // since a copy of a byte can be either signed/unsigned.
847 template <typename T>
848 DiagnosticPredicate isSVECpyImm() const {
849 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
850 return DiagnosticPredicateTy::NoMatch;
851
852 bool IsByte =
853 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
854 if (auto ShiftedImm = getShiftedVal<8>())
855 if (!(IsByte && ShiftedImm->second) &&
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000856 AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
857 << ShiftedImm->second))
Sander de Smalen62770792018-05-25 09:47:52 +0000858 return DiagnosticPredicateTy::Match;
859
860 return DiagnosticPredicateTy::NearMatch;
861 }
862
Sander de Smalen98686c62018-05-29 10:39:49 +0000863 // Unsigned value in the range 0 to 255. For element widths of
864 // 16 bits or higher it may also be a signed multiple of 256 in the
865 // range 0 to 65280.
866 template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
867 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
868 return DiagnosticPredicateTy::NoMatch;
869
870 bool IsByte =
871 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
872 if (auto ShiftedImm = getShiftedVal<8>())
873 if (!(IsByte && ShiftedImm->second) &&
874 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
875 << ShiftedImm->second))
876 return DiagnosticPredicateTy::Match;
877
878 return DiagnosticPredicateTy::NearMatch;
879 }
880
Sander de Smalen97ca6b92018-06-01 07:25:46 +0000881 template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
882 if (isLogicalImm<T>() && !isSVECpyImm<T>())
883 return DiagnosticPredicateTy::Match;
884 return DiagnosticPredicateTy::NoMatch;
885 }
886
Tim Northover3b0846e2014-05-24 12:50:23 +0000887 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000888
Tim Northover3b0846e2014-05-24 12:50:23 +0000889 bool isSIMDImmType10() const {
890 if (!isImm())
891 return false;
892 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
893 if (!MCE)
894 return false;
895 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
896 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000897
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000898 template<int N>
899 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000900 if (!isImm())
901 return false;
902 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
903 if (!MCE)
904 return true;
905 int64_t Val = MCE->getValue();
906 if (Val & 0x3)
907 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000908 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
909 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000910 }
911
912 bool
913 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
914 if (!isImm())
915 return false;
916
917 AArch64MCExpr::VariantKind ELFRefKind;
918 MCSymbolRefExpr::VariantKind DarwinRefKind;
919 int64_t Addend;
920 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
921 DarwinRefKind, Addend)) {
922 return false;
923 }
924 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
925 return false;
926
927 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
928 if (ELFRefKind == AllowedModifiers[i])
David Green85d6a552018-09-18 09:44:53 +0000929 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000930 }
931
932 return false;
933 }
934
935 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000936 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000937 }
938
939 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000940 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
941 AArch64MCExpr::VK_TPREL_G2,
942 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000943 }
944
945 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000946 return isMovWSymbol({
947 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000948 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
949 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000950 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000951 }
952
953 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000954 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
955 AArch64MCExpr::VK_TPREL_G0,
956 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000957 }
958
959 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000960 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000961 }
962
963 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000964 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000965 }
966
967 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000968 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
969 AArch64MCExpr::VK_TPREL_G1_NC,
970 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000971 }
972
973 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000974 return isMovWSymbol(
975 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
976 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000977 }
978
979 template<int RegWidth, int Shift>
980 bool isMOVZMovAlias() const {
981 if (!isImm()) return false;
982
983 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
984 if (!CE) return false;
985 uint64_t Value = CE->getValue();
986
Tim Northoverdaa1c012016-06-16 01:42:25 +0000987 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000988 }
989
990 template<int RegWidth, int Shift>
991 bool isMOVNMovAlias() const {
992 if (!isImm()) return false;
993
994 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
995 if (!CE) return false;
996 uint64_t Value = CE->getValue();
997
Tim Northoverdaa1c012016-06-16 01:42:25 +0000998 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000999 }
1000
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001001 bool isFPImm() const {
1002 return Kind == k_FPImm &&
1003 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt()) != -1;
1004 }
1005
Tim Northover3b0846e2014-05-24 12:50:23 +00001006 bool isBarrier() const { return Kind == k_Barrier; }
1007 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001008
Tim Northover3b0846e2014-05-24 12:50:23 +00001009 bool isMRSSystemRegister() const {
1010 if (!isSysReg()) return false;
1011
Tim Northover7cd58932015-01-22 17:23:04 +00001012 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +00001013 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001014
Tim Northover3b0846e2014-05-24 12:50:23 +00001015 bool isMSRSystemRegister() const {
1016 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +00001017 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +00001018 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001019
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001020 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001021 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +00001022 return (SysReg.PStateField == AArch64PState::PAN ||
Sjoerd Meijer173b7f02018-07-03 12:09:20 +00001023 SysReg.PStateField == AArch64PState::DIT ||
Oliver Stannard8459d342018-09-27 14:05:46 +00001024 SysReg.PStateField == AArch64PState::UAO ||
1025 SysReg.PStateField == AArch64PState::SSBS);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001026 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001027
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001028 bool isSystemPStateFieldWithImm0_15() const {
1029 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +00001030 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +00001031 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001032
Florian Hahnc4422242017-11-07 13:07:50 +00001033 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00001034 return Kind == k_Register;
1035 }
1036
1037 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001038 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
1039 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001040
Florian Hahnc4422242017-11-07 13:07:50 +00001041 bool isNeonVectorReg() const {
1042 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
1043 }
1044
1045 bool isNeonVectorRegLo() const {
1046 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001047 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
1048 Reg.RegNum);
1049 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001050
Sander de Smalencd6be962017-12-20 11:02:42 +00001051 template <unsigned Class> bool isSVEVectorReg() const {
1052 RegKind RK;
1053 switch (Class) {
1054 case AArch64::ZPRRegClassID:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00001055 case AArch64::ZPR_3bRegClassID:
1056 case AArch64::ZPR_4bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +00001057 RK = RegKind::SVEDataVector;
1058 break;
1059 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +00001060 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +00001061 RK = RegKind::SVEPredicateVector;
1062 break;
1063 default:
1064 llvm_unreachable("Unsupport register class");
1065 }
1066
1067 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +00001068 AArch64MCRegisterClasses[Class].contains(getReg());
1069 }
1070
Sander de Smalenfd54a782018-06-04 07:07:35 +00001071 template <unsigned Class> bool isFPRasZPR() const {
1072 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1073 AArch64MCRegisterClasses[Class].contains(getReg());
1074 }
1075
Sander de Smalencd6be962017-12-20 11:02:42 +00001076 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +00001077 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
1078 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
1079 return DiagnosticPredicateTy::NoMatch;
1080
1081 if (isSVEVectorReg<Class>() &&
1082 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
1083 return DiagnosticPredicateTy::Match;
1084
1085 return DiagnosticPredicateTy::NearMatch;
1086 }
1087
1088 template <int ElementWidth, unsigned Class>
1089 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
1090 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
1091 return DiagnosticPredicateTy::NoMatch;
1092
1093 if (isSVEVectorReg<Class>() &&
1094 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
1095 return DiagnosticPredicateTy::Match;
1096
1097 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00001098 }
1099
Sander de Smaleneb896b12018-04-25 09:26:47 +00001100 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +00001101 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
1102 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +00001103 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
1104 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
1105 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001106 return DiagnosticPredicateTy::NoMatch;
1107
Sander de Smalen5861c262018-04-30 07:24:38 +00001108 // Give a more specific diagnostic when the user has explicitly typed in
1109 // a shift-amount that does not match what is expected, but for which
1110 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
1111 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
1112 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
1113 ShiftExtendTy == AArch64_AM::SXTW) &&
1114 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
1115 return DiagnosticPredicateTy::NoMatch;
1116
1117 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001118 return DiagnosticPredicateTy::Match;
1119
1120 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +00001121 }
1122
Tim Northover3b0846e2014-05-24 12:50:23 +00001123 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001124 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001125 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
1126 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001127
Sander de Smalen0325e302018-07-02 07:34:52 +00001128 bool isGPR64as32() const {
1129 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1130 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(Reg.RegNum);
1131 }
1132
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001133 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001134 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001135 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
1136 Reg.RegNum);
1137 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001138
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001139 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001140 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001141 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1142 Reg.RegNum);
1143 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001144
Sam Parker5f934642017-08-31 09:27:04 +00001145 template<int64_t Angle, int64_t Remainder>
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001146 DiagnosticPredicate isComplexRotation() const {
1147 if (!isImm()) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001148
1149 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001150 if (!CE) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001151 uint64_t Value = CE->getValue();
1152
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001153 if (Value % Angle == Remainder && Value <= 270)
1154 return DiagnosticPredicateTy::Match;
1155 return DiagnosticPredicateTy::NearMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001156 }
1157
Sander de Smalen149916d2018-04-20 07:24:20 +00001158 template <unsigned RegClassID> bool isGPR64() const {
1159 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1160 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1161 }
1162
1163 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001164 DiagnosticPredicate isGPR64WithShiftExtend() const {
1165 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1166 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001167
Sander de Smalenfe17a782018-04-26 12:54:42 +00001168 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1169 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1170 return DiagnosticPredicateTy::Match;
1171 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001172 }
1173
Tim Northover3b0846e2014-05-24 12:50:23 +00001174 /// Is this a vector list with the type implicit (presumably attached to the
1175 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001176 template <RegKind VectorKind, unsigned NumRegs>
1177 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001178 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001179 VectorList.NumElements == 0 &&
1180 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001181 }
1182
Sander de Smalen650234b2018-04-12 11:40:52 +00001183 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1184 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001185 bool isTypedVectorList() const {
1186 if (Kind != k_VectorList)
1187 return false;
1188 if (VectorList.Count != NumRegs)
1189 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001190 if (VectorList.RegisterKind != VectorKind)
1191 return false;
1192 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001193 return false;
1194 return VectorList.NumElements == NumElements;
1195 }
1196
Sander de Smalenc33d6682018-06-04 06:40:55 +00001197 template <int Min, int Max>
1198 DiagnosticPredicate isVectorIndex() const {
1199 if (Kind != k_VectorIndex)
1200 return DiagnosticPredicateTy::NoMatch;
1201 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1202 return DiagnosticPredicateTy::Match;
1203 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001204 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001205
Tim Northover3b0846e2014-05-24 12:50:23 +00001206 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001207
Tim Northover3b0846e2014-05-24 12:50:23 +00001208 bool isTokenEqual(StringRef Str) const {
1209 return Kind == k_Token && getToken() == Str;
1210 }
1211 bool isSysCR() const { return Kind == k_SysCR; }
1212 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001213 bool isPSBHint() const { return Kind == k_PSBHint; }
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001214 bool isBTIHint() const { return Kind == k_BTIHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001215 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1216 bool isShifter() const {
1217 if (!isShiftExtend())
1218 return false;
1219
1220 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1221 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1222 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1223 ST == AArch64_AM::MSL);
1224 }
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001225
1226 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1227 if (Kind != k_FPImm)
1228 return DiagnosticPredicateTy::NoMatch;
1229
1230 if (getFPImmIsExact()) {
1231 // Lookup the immediate from table of supported immediates.
1232 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1233 assert(Desc && "Unknown enum value");
1234
1235 // Calculate its FP value.
1236 APFloat RealVal(APFloat::IEEEdouble());
1237 if (RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero) !=
1238 APFloat::opOK)
1239 llvm_unreachable("FP immediate is not exact");
1240
1241 if (getFPImm().bitwiseIsEqual(RealVal))
1242 return DiagnosticPredicateTy::Match;
1243 }
1244
1245 return DiagnosticPredicateTy::NearMatch;
1246 }
1247
1248 template <unsigned ImmA, unsigned ImmB>
1249 DiagnosticPredicate isExactFPImm() const {
1250 DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1251 if ((Res = isExactFPImm<ImmA>()))
1252 return DiagnosticPredicateTy::Match;
1253 if ((Res = isExactFPImm<ImmB>()))
1254 return DiagnosticPredicateTy::Match;
1255 return Res;
1256 }
1257
Tim Northover3b0846e2014-05-24 12:50:23 +00001258 bool isExtend() const {
1259 if (!isShiftExtend())
1260 return false;
1261
1262 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1263 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1264 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1265 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1266 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1267 ET == AArch64_AM::LSL) &&
1268 getShiftExtendAmount() <= 4;
1269 }
1270
1271 bool isExtend64() const {
1272 if (!isExtend())
1273 return false;
1274 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1275 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1276 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1277 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001278
Tim Northover3b0846e2014-05-24 12:50:23 +00001279 bool isExtendLSL64() const {
1280 if (!isExtend())
1281 return false;
1282 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1283 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1284 ET == AArch64_AM::LSL) &&
1285 getShiftExtendAmount() <= 4;
1286 }
1287
1288 template<int Width> bool isMemXExtend() const {
1289 if (!isExtend())
1290 return false;
1291 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1292 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1293 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1294 getShiftExtendAmount() == 0);
1295 }
1296
1297 template<int Width> bool isMemWExtend() const {
1298 if (!isExtend())
1299 return false;
1300 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1301 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1302 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1303 getShiftExtendAmount() == 0);
1304 }
1305
1306 template <unsigned width>
1307 bool isArithmeticShifter() const {
1308 if (!isShifter())
1309 return false;
1310
1311 // An arithmetic shifter is LSL, LSR, or ASR.
1312 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1313 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1314 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1315 }
1316
1317 template <unsigned width>
1318 bool isLogicalShifter() const {
1319 if (!isShifter())
1320 return false;
1321
1322 // A logical shifter is LSL, LSR, ASR or ROR.
1323 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1324 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1325 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1326 getShiftExtendAmount() < width;
1327 }
1328
1329 bool isMovImm32Shifter() const {
1330 if (!isShifter())
1331 return false;
1332
1333 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1334 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1335 if (ST != AArch64_AM::LSL)
1336 return false;
1337 uint64_t Val = getShiftExtendAmount();
1338 return (Val == 0 || Val == 16);
1339 }
1340
1341 bool isMovImm64Shifter() const {
1342 if (!isShifter())
1343 return false;
1344
1345 // A MOVi shifter is LSL of 0 or 16.
1346 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1347 if (ST != AArch64_AM::LSL)
1348 return false;
1349 uint64_t Val = getShiftExtendAmount();
1350 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1351 }
1352
1353 bool isLogicalVecShifter() const {
1354 if (!isShifter())
1355 return false;
1356
1357 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1358 unsigned Shift = getShiftExtendAmount();
1359 return getShiftExtendType() == AArch64_AM::LSL &&
1360 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1361 }
1362
1363 bool isLogicalVecHalfWordShifter() const {
1364 if (!isLogicalVecShifter())
1365 return false;
1366
1367 // A logical vector shifter is a left shift by 0 or 8.
1368 unsigned Shift = getShiftExtendAmount();
1369 return getShiftExtendType() == AArch64_AM::LSL &&
1370 (Shift == 0 || Shift == 8);
1371 }
1372
1373 bool isMoveVecShifter() const {
1374 if (!isShiftExtend())
1375 return false;
1376
1377 // A logical vector shifter is a left shift by 8 or 16.
1378 unsigned Shift = getShiftExtendAmount();
1379 return getShiftExtendType() == AArch64_AM::MSL &&
1380 (Shift == 8 || Shift == 16);
1381 }
1382
1383 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1384 // to LDUR/STUR when the offset is not legal for the former but is for
1385 // the latter. As such, in addition to checking for being a legal unscaled
1386 // address, also check that it is not a legal scaled address. This avoids
1387 // ambiguity in the matcher.
1388 template<int Width>
1389 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001390 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001391 }
1392
1393 bool isAdrpLabel() const {
1394 // Validation was handled during parsing, so we just sanity check that
1395 // something didn't go haywire.
1396 if (!isImm())
1397 return false;
1398
1399 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1400 int64_t Val = CE->getValue();
1401 int64_t Min = - (4096 * (1LL << (21 - 1)));
1402 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1403 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1404 }
1405
1406 return true;
1407 }
1408
1409 bool isAdrLabel() const {
1410 // Validation was handled during parsing, so we just sanity check that
1411 // something didn't go haywire.
1412 if (!isImm())
1413 return false;
1414
1415 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1416 int64_t Val = CE->getValue();
1417 int64_t Min = - (1LL << (21 - 1));
1418 int64_t Max = ((1LL << (21 - 1)) - 1);
1419 return Val >= Min && Val <= Max;
1420 }
1421
1422 return true;
1423 }
1424
1425 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1426 // Add as immediates when possible. Null MCExpr = 0.
1427 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001428 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001429 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001430 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001431 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001432 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001433 }
1434
1435 void addRegOperands(MCInst &Inst, unsigned N) const {
1436 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001437 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001438 }
1439
1440 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1441 assert(N == 1 && "Invalid number of operands!");
1442 assert(
1443 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1444
1445 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1446 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1447 RI->getEncodingValue(getReg()));
1448
Jim Grosbache9119e42015-05-13 18:37:00 +00001449 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001450 }
1451
Sander de Smalen0325e302018-07-02 07:34:52 +00001452 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1453 assert(N == 1 && "Invalid number of operands!");
1454 assert(
1455 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(getReg()));
1456
1457 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1458 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID).getRegister(
1459 RI->getEncodingValue(getReg()));
1460
1461 Inst.addOperand(MCOperand::createReg(Reg));
1462 }
1463
Sander de Smalenfd54a782018-06-04 07:07:35 +00001464 template <int Width>
1465 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1466 unsigned Base;
1467 switch (Width) {
1468 case 8: Base = AArch64::B0; break;
1469 case 16: Base = AArch64::H0; break;
1470 case 32: Base = AArch64::S0; break;
1471 case 64: Base = AArch64::D0; break;
1472 case 128: Base = AArch64::Q0; break;
1473 default:
1474 llvm_unreachable("Unsupported width");
1475 }
1476 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1477 }
1478
Tim Northover3b0846e2014-05-24 12:50:23 +00001479 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1480 assert(N == 1 && "Invalid number of operands!");
1481 assert(
1482 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001483 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001484 }
1485
1486 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1487 assert(N == 1 && "Invalid number of operands!");
1488 assert(
1489 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001490 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001491 }
1492
1493 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1494 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001495 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001496 }
1497
Sander de Smalen525e3222018-04-12 13:19:32 +00001498 enum VecListIndexType {
1499 VecListIdx_DReg = 0,
1500 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001501 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001502 };
1503
1504 template <VecListIndexType RegTy, unsigned NumRegs>
1505 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001506 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001507 static const unsigned FirstRegs[][5] = {
1508 /* DReg */ { AArch64::Q0,
1509 AArch64::D0, AArch64::D0_D1,
1510 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1511 /* QReg */ { AArch64::Q0,
1512 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001513 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1514 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001515 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001516 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001517 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001518
Sander de Smalen7a210db2018-04-16 10:46:18 +00001519 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1520 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001521
Sander de Smalen525e3222018-04-12 13:19:32 +00001522 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1523 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1524 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001525 }
1526
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001527 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001528 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001529 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001530 }
1531
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001532 template <unsigned ImmIs0, unsigned ImmIs1>
1533 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1534 assert(N == 1 && "Invalid number of operands!");
1535 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1536 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1537 }
1538
Tim Northover3b0846e2014-05-24 12:50:23 +00001539 void addImmOperands(MCInst &Inst, unsigned N) const {
1540 assert(N == 1 && "Invalid number of operands!");
1541 // If this is a pageoff symrefexpr with an addend, adjust the addend
1542 // to be only the page-offset portion. Otherwise, just add the expr
1543 // as-is.
1544 addExpr(Inst, getImm());
1545 }
1546
Sander de Smalen62770792018-05-25 09:47:52 +00001547 template <int Shift>
1548 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001549 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001550 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1551 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1552 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1553 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001554 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001555 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001556 } else {
1557 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001558 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001559 }
1560 }
1561
Sander de Smalen62770792018-05-25 09:47:52 +00001562 template <int Shift>
1563 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001564 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001565 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1566 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1567 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1568 } else
1569 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001570 }
1571
Tim Northover3b0846e2014-05-24 12:50:23 +00001572 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1573 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001574 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001575 }
1576
1577 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1578 assert(N == 1 && "Invalid number of operands!");
1579 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1580 if (!MCE)
1581 addExpr(Inst, getImm());
1582 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001583 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001584 }
1585
1586 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1587 addImmOperands(Inst, N);
1588 }
1589
1590 template<int Scale>
1591 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1592 assert(N == 1 && "Invalid number of operands!");
1593 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1594
1595 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001596 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001597 return;
1598 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001599 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001600 }
1601
Sjoerd Meijera3dad802018-07-06 12:32:33 +00001602 void addUImm6Operands(MCInst &Inst, unsigned N) const {
1603 assert(N == 1 && "Invalid number of operands!");
1604 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1605 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1606 }
1607
Sander de Smalen5c625982018-04-13 12:56:14 +00001608 template <int Scale>
1609 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1610 assert(N == 1 && "Invalid number of operands!");
1611 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1612 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1613 }
1614
Sander de Smalena1c259c2018-01-29 13:05:38 +00001615 template <typename T>
1616 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001617 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001618 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001619 typename std::make_unsigned<T>::type Val = MCE->getValue();
1620 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001621 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001622 }
1623
Sander de Smalena1c259c2018-01-29 13:05:38 +00001624 template <typename T>
1625 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001626 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001627 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001628 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1629 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001630 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001631 }
1632
Tim Northover3b0846e2014-05-24 12:50:23 +00001633 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1634 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001635 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001636 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001637 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001638 }
1639
1640 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1641 // Branch operands don't encode the low bits, so shift them off
1642 // here. If it's a label, however, just put it on directly as there's
1643 // not enough information now to do anything.
1644 assert(N == 1 && "Invalid number of operands!");
1645 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1646 if (!MCE) {
1647 addExpr(Inst, getImm());
1648 return;
1649 }
1650 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001651 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001652 }
1653
1654 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1655 // Branch operands don't encode the low bits, so shift them off
1656 // here. If it's a label, however, just put it on directly as there's
1657 // not enough information now to do anything.
1658 assert(N == 1 && "Invalid number of operands!");
1659 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1660 if (!MCE) {
1661 addExpr(Inst, getImm());
1662 return;
1663 }
1664 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001665 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001666 }
1667
1668 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1669 // Branch operands don't encode the low bits, so shift them off
1670 // here. If it's a label, however, just put it on directly as there's
1671 // not enough information now to do anything.
1672 assert(N == 1 && "Invalid number of operands!");
1673 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1674 if (!MCE) {
1675 addExpr(Inst, getImm());
1676 return;
1677 }
1678 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001679 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001680 }
1681
1682 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1683 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001684 Inst.addOperand(MCOperand::createImm(
1685 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
Tim Northover3b0846e2014-05-24 12:50:23 +00001686 }
1687
1688 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1689 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001690 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001691 }
1692
1693 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1694 assert(N == 1 && "Invalid number of operands!");
1695
Jim Grosbache9119e42015-05-13 18:37:00 +00001696 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001697 }
1698
1699 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1700 assert(N == 1 && "Invalid number of operands!");
1701
Jim Grosbache9119e42015-05-13 18:37:00 +00001702 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001703 }
1704
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001705 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1706 assert(N == 1 && "Invalid number of operands!");
1707
1708 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1709 }
1710
1711 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001712 assert(N == 1 && "Invalid number of operands!");
1713
Jim Grosbache9119e42015-05-13 18:37:00 +00001714 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001715 }
1716
1717 void addSysCROperands(MCInst &Inst, unsigned N) const {
1718 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001719 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001720 }
1721
1722 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1723 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001724 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001725 }
1726
Oliver Stannarda34e4702015-12-01 10:48:51 +00001727 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1728 assert(N == 1 && "Invalid number of operands!");
1729 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1730 }
1731
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001732 void addBTIHintOperands(MCInst &Inst, unsigned N) const {
1733 assert(N == 1 && "Invalid number of operands!");
1734 Inst.addOperand(MCOperand::createImm(getBTIHint()));
1735 }
1736
Tim Northover3b0846e2014-05-24 12:50:23 +00001737 void addShifterOperands(MCInst &Inst, unsigned N) const {
1738 assert(N == 1 && "Invalid number of operands!");
1739 unsigned Imm =
1740 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001741 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001742 }
1743
1744 void addExtendOperands(MCInst &Inst, unsigned N) const {
1745 assert(N == 1 && "Invalid number of operands!");
1746 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1747 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1748 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001749 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001750 }
1751
1752 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1753 assert(N == 1 && "Invalid number of operands!");
1754 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1755 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1756 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001757 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001758 }
1759
1760 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1761 assert(N == 2 && "Invalid number of operands!");
1762 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1763 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001764 Inst.addOperand(MCOperand::createImm(IsSigned));
1765 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001766 }
1767
1768 // For 8-bit load/store instructions with a register offset, both the
1769 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1770 // they're disambiguated by whether the shift was explicit or implicit rather
1771 // than its size.
1772 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1773 assert(N == 2 && "Invalid number of operands!");
1774 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1775 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001776 Inst.addOperand(MCOperand::createImm(IsSigned));
1777 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001778 }
1779
1780 template<int Shift>
1781 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1782 assert(N == 1 && "Invalid number of operands!");
1783
1784 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1785 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001786 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001787 }
1788
1789 template<int Shift>
1790 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1791 assert(N == 1 && "Invalid number of operands!");
1792
1793 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1794 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001795 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001796 }
1797
Sam Parker5f934642017-08-31 09:27:04 +00001798 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1799 assert(N == 1 && "Invalid number of operands!");
1800 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1801 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1802 }
1803
1804 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1805 assert(N == 1 && "Invalid number of operands!");
1806 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1807 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1808 }
1809
Tim Northover3b0846e2014-05-24 12:50:23 +00001810 void print(raw_ostream &OS) const override;
1811
David Blaikie960ea3f2014-06-08 16:18:35 +00001812 static std::unique_ptr<AArch64Operand>
1813 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1814 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001815 Op->Tok.Data = Str.data();
1816 Op->Tok.Length = Str.size();
1817 Op->Tok.IsSuffix = IsSuffix;
1818 Op->StartLoc = S;
1819 Op->EndLoc = S;
1820 return Op;
1821 }
1822
David Blaikie960ea3f2014-06-08 16:18:35 +00001823 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001824 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
Sander de Smalen0325e302018-07-02 07:34:52 +00001825 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
Sander de Smalen149916d2018-04-20 07:24:20 +00001826 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1827 unsigned ShiftAmount = 0,
1828 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001829 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001830 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001831 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001832 Op->Reg.ElementWidth = 0;
Sander de Smalen0325e302018-07-02 07:34:52 +00001833 Op->Reg.EqualityTy = EqTy;
Sander de Smalen149916d2018-04-20 07:24:20 +00001834 Op->Reg.ShiftExtend.Type = ExtTy;
1835 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1836 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001837 Op->StartLoc = S;
1838 Op->EndLoc = E;
1839 return Op;
1840 }
1841
David Blaikie960ea3f2014-06-08 16:18:35 +00001842 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001843 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001844 SMLoc S, SMLoc E, MCContext &Ctx,
1845 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1846 unsigned ShiftAmount = 0,
1847 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001848 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1849 Kind == RegKind::SVEPredicateVector) &&
1850 "Invalid vector kind");
Sander de Smalen0325e302018-07-02 07:34:52 +00001851 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
Sander de Smalen149916d2018-04-20 07:24:20 +00001852 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001853 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001854 return Op;
1855 }
1856
1857 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001858 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001859 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1860 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001861 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001862 Op->VectorList.RegNum = RegNum;
1863 Op->VectorList.Count = Count;
1864 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001865 Op->VectorList.ElementWidth = ElementWidth;
1866 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001867 Op->StartLoc = S;
1868 Op->EndLoc = E;
1869 return Op;
1870 }
1871
David Blaikie960ea3f2014-06-08 16:18:35 +00001872 static std::unique_ptr<AArch64Operand>
1873 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1874 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001875 Op->VectorIndex.Val = Idx;
1876 Op->StartLoc = S;
1877 Op->EndLoc = E;
1878 return Op;
1879 }
1880
David Blaikie960ea3f2014-06-08 16:18:35 +00001881 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1882 SMLoc E, MCContext &Ctx) {
1883 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001884 Op->Imm.Val = Val;
1885 Op->StartLoc = S;
1886 Op->EndLoc = E;
1887 return Op;
1888 }
1889
David Blaikie960ea3f2014-06-08 16:18:35 +00001890 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1891 unsigned ShiftAmount,
1892 SMLoc S, SMLoc E,
1893 MCContext &Ctx) {
1894 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001895 Op->ShiftedImm .Val = Val;
1896 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1897 Op->StartLoc = S;
1898 Op->EndLoc = E;
1899 return Op;
1900 }
1901
David Blaikie960ea3f2014-06-08 16:18:35 +00001902 static std::unique_ptr<AArch64Operand>
1903 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1904 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001905 Op->CondCode.Code = Code;
1906 Op->StartLoc = S;
1907 Op->EndLoc = E;
1908 return Op;
1909 }
1910
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001911 static std::unique_ptr<AArch64Operand>
1912 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001913 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001914 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
1915 Op->FPImm.IsExact = IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +00001916 Op->StartLoc = S;
1917 Op->EndLoc = S;
1918 return Op;
1919 }
1920
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001921 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1922 StringRef Str,
1923 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001924 MCContext &Ctx) {
1925 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001926 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001927 Op->Barrier.Data = Str.data();
1928 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001929 Op->StartLoc = S;
1930 Op->EndLoc = S;
1931 return Op;
1932 }
1933
Tim Northover7cd58932015-01-22 17:23:04 +00001934 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1935 uint32_t MRSReg,
1936 uint32_t MSRReg,
1937 uint32_t PStateField,
1938 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001939 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001940 Op->SysReg.Data = Str.data();
1941 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001942 Op->SysReg.MRSReg = MRSReg;
1943 Op->SysReg.MSRReg = MSRReg;
1944 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001945 Op->StartLoc = S;
1946 Op->EndLoc = S;
1947 return Op;
1948 }
1949
David Blaikie960ea3f2014-06-08 16:18:35 +00001950 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1951 SMLoc E, MCContext &Ctx) {
1952 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001953 Op->SysCRImm.Val = Val;
1954 Op->StartLoc = S;
1955 Op->EndLoc = E;
1956 return Op;
1957 }
1958
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001959 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1960 StringRef Str,
1961 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001962 MCContext &Ctx) {
1963 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001964 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001965 Op->Barrier.Data = Str.data();
1966 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001967 Op->StartLoc = S;
1968 Op->EndLoc = S;
1969 return Op;
1970 }
1971
Oliver Stannarda34e4702015-12-01 10:48:51 +00001972 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1973 StringRef Str,
1974 SMLoc S,
1975 MCContext &Ctx) {
1976 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1977 Op->PSBHint.Val = Val;
1978 Op->PSBHint.Data = Str.data();
1979 Op->PSBHint.Length = Str.size();
1980 Op->StartLoc = S;
1981 Op->EndLoc = S;
1982 return Op;
1983 }
1984
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001985 static std::unique_ptr<AArch64Operand> CreateBTIHint(unsigned Val,
1986 StringRef Str,
1987 SMLoc S,
1988 MCContext &Ctx) {
1989 auto Op = make_unique<AArch64Operand>(k_BTIHint, Ctx);
1990 Op->BTIHint.Val = Val << 1 | 32;
1991 Op->BTIHint.Data = Str.data();
1992 Op->BTIHint.Length = Str.size();
1993 Op->StartLoc = S;
1994 Op->EndLoc = S;
1995 return Op;
1996 }
1997
David Blaikie960ea3f2014-06-08 16:18:35 +00001998 static std::unique_ptr<AArch64Operand>
1999 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
2000 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
2001 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00002002 Op->ShiftExtend.Type = ShOp;
2003 Op->ShiftExtend.Amount = Val;
2004 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
2005 Op->StartLoc = S;
2006 Op->EndLoc = E;
2007 return Op;
2008 }
2009};
2010
2011} // end anonymous namespace.
2012
2013void AArch64Operand::print(raw_ostream &OS) const {
2014 switch (Kind) {
2015 case k_FPImm:
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002016 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
2017 if (!getFPImmIsExact())
2018 OS << " (inexact)";
2019 OS << ">";
Tim Northover3b0846e2014-05-24 12:50:23 +00002020 break;
2021 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00002022 StringRef Name = getBarrierName();
2023 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00002024 OS << "<barrier " << Name << ">";
2025 else
2026 OS << "<barrier invalid #" << getBarrier() << ">";
2027 break;
2028 }
2029 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00002030 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00002031 break;
2032 case k_ShiftedImm: {
2033 unsigned Shift = getShiftedImmShift();
2034 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00002035 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00002036 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
2037 break;
2038 }
2039 case k_CondCode:
2040 OS << "<condcode " << getCondCode() << ">";
2041 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00002042 case k_VectorList: {
2043 OS << "<vectorlist ";
2044 unsigned Reg = getVectorListStart();
2045 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
2046 OS << Reg + i << " ";
2047 OS << ">";
2048 break;
2049 }
2050 case k_VectorIndex:
2051 OS << "<vectorindex " << getVectorIndex() << ">";
2052 break;
2053 case k_SysReg:
2054 OS << "<sysreg: " << getSysReg() << '>';
2055 break;
2056 case k_Token:
2057 OS << "'" << getToken() << "'";
2058 break;
2059 case k_SysCR:
2060 OS << "c" << getSysCR();
2061 break;
2062 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00002063 StringRef Name = getPrefetchName();
2064 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00002065 OS << "<prfop " << Name << ">";
2066 else
2067 OS << "<prfop invalid #" << getPrefetch() << ">";
2068 break;
2069 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00002070 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00002071 OS << getPSBHintName();
2072 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00002073 case k_Register:
2074 OS << "<register " << getReg() << ">";
2075 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
2076 break;
2077 LLVM_FALLTHROUGH;
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00002078 case k_BTIHint:
2079 OS << getBTIHintName();
2080 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00002081 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00002082 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
2083 << getShiftExtendAmount();
2084 if (!hasShiftExtendAmount())
2085 OS << "<imp>";
2086 OS << '>';
2087 break;
2088 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002089}
2090
2091/// @name Auto-generated Match Functions
2092/// {
2093
2094static unsigned MatchRegisterName(StringRef Name);
2095
2096/// }
2097
Florian Hahnc4422242017-11-07 13:07:50 +00002098static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00002099 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00002100 .Case("v0", AArch64::Q0)
2101 .Case("v1", AArch64::Q1)
2102 .Case("v2", AArch64::Q2)
2103 .Case("v3", AArch64::Q3)
2104 .Case("v4", AArch64::Q4)
2105 .Case("v5", AArch64::Q5)
2106 .Case("v6", AArch64::Q6)
2107 .Case("v7", AArch64::Q7)
2108 .Case("v8", AArch64::Q8)
2109 .Case("v9", AArch64::Q9)
2110 .Case("v10", AArch64::Q10)
2111 .Case("v11", AArch64::Q11)
2112 .Case("v12", AArch64::Q12)
2113 .Case("v13", AArch64::Q13)
2114 .Case("v14", AArch64::Q14)
2115 .Case("v15", AArch64::Q15)
2116 .Case("v16", AArch64::Q16)
2117 .Case("v17", AArch64::Q17)
2118 .Case("v18", AArch64::Q18)
2119 .Case("v19", AArch64::Q19)
2120 .Case("v20", AArch64::Q20)
2121 .Case("v21", AArch64::Q21)
2122 .Case("v22", AArch64::Q22)
2123 .Case("v23", AArch64::Q23)
2124 .Case("v24", AArch64::Q24)
2125 .Case("v25", AArch64::Q25)
2126 .Case("v26", AArch64::Q26)
2127 .Case("v27", AArch64::Q27)
2128 .Case("v28", AArch64::Q28)
2129 .Case("v29", AArch64::Q29)
2130 .Case("v30", AArch64::Q30)
2131 .Case("v31", AArch64::Q31)
2132 .Default(0);
2133}
2134
Sander de Smalen73937b72018-04-11 07:36:10 +00002135/// Returns an optional pair of (#elements, element-width) if Suffix
2136/// is a valid vector kind. Where the number of elements in a vector
2137/// or the vector width is implicit or explicitly unknown (but still a
2138/// valid suffix kind), 0 is used.
2139static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2140 RegKind VectorKind) {
2141 std::pair<int, int> Res = {-1, -1};
2142
2143 switch (VectorKind) {
2144 case RegKind::NeonVector:
2145 Res =
2146 StringSwitch<std::pair<int, int>>(Suffix.lower())
2147 .Case("", {0, 0})
2148 .Case(".1d", {1, 64})
2149 .Case(".1q", {1, 128})
2150 // '.2h' needed for fp16 scalar pairwise reductions
2151 .Case(".2h", {2, 16})
2152 .Case(".2s", {2, 32})
2153 .Case(".2d", {2, 64})
2154 // '.4b' is another special case for the ARMv8.2a dot product
2155 // operand
2156 .Case(".4b", {4, 8})
2157 .Case(".4h", {4, 16})
2158 .Case(".4s", {4, 32})
2159 .Case(".8b", {8, 8})
2160 .Case(".8h", {8, 16})
2161 .Case(".16b", {16, 8})
2162 // Accept the width neutral ones, too, for verbose syntax. If those
2163 // aren't used in the right places, the token operand won't match so
2164 // all will work out.
2165 .Case(".b", {0, 8})
2166 .Case(".h", {0, 16})
2167 .Case(".s", {0, 32})
2168 .Case(".d", {0, 64})
2169 .Default({-1, -1});
2170 break;
2171 case RegKind::SVEPredicateVector:
2172 case RegKind::SVEDataVector:
2173 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2174 .Case("", {0, 0})
2175 .Case(".b", {0, 8})
2176 .Case(".h", {0, 16})
2177 .Case(".s", {0, 32})
2178 .Case(".d", {0, 64})
2179 .Case(".q", {0, 128})
2180 .Default({-1, -1});
2181 break;
2182 default:
2183 llvm_unreachable("Unsupported RegKind");
2184 }
2185
2186 if (Res == std::make_pair(-1, -1))
2187 return Optional<std::pair<int, int>>();
2188
2189 return Optional<std::pair<int, int>>(Res);
2190}
2191
2192static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2193 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002194}
2195
Florian Hahn91f11e52017-11-07 16:45:48 +00002196static unsigned matchSVEDataVectorRegName(StringRef Name) {
2197 return StringSwitch<unsigned>(Name.lower())
2198 .Case("z0", AArch64::Z0)
2199 .Case("z1", AArch64::Z1)
2200 .Case("z2", AArch64::Z2)
2201 .Case("z3", AArch64::Z3)
2202 .Case("z4", AArch64::Z4)
2203 .Case("z5", AArch64::Z5)
2204 .Case("z6", AArch64::Z6)
2205 .Case("z7", AArch64::Z7)
2206 .Case("z8", AArch64::Z8)
2207 .Case("z9", AArch64::Z9)
2208 .Case("z10", AArch64::Z10)
2209 .Case("z11", AArch64::Z11)
2210 .Case("z12", AArch64::Z12)
2211 .Case("z13", AArch64::Z13)
2212 .Case("z14", AArch64::Z14)
2213 .Case("z15", AArch64::Z15)
2214 .Case("z16", AArch64::Z16)
2215 .Case("z17", AArch64::Z17)
2216 .Case("z18", AArch64::Z18)
2217 .Case("z19", AArch64::Z19)
2218 .Case("z20", AArch64::Z20)
2219 .Case("z21", AArch64::Z21)
2220 .Case("z22", AArch64::Z22)
2221 .Case("z23", AArch64::Z23)
2222 .Case("z24", AArch64::Z24)
2223 .Case("z25", AArch64::Z25)
2224 .Case("z26", AArch64::Z26)
2225 .Case("z27", AArch64::Z27)
2226 .Case("z28", AArch64::Z28)
2227 .Case("z29", AArch64::Z29)
2228 .Case("z30", AArch64::Z30)
2229 .Case("z31", AArch64::Z31)
2230 .Default(0);
2231}
2232
Sander de Smalencd6be962017-12-20 11:02:42 +00002233static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2234 return StringSwitch<unsigned>(Name.lower())
2235 .Case("p0", AArch64::P0)
2236 .Case("p1", AArch64::P1)
2237 .Case("p2", AArch64::P2)
2238 .Case("p3", AArch64::P3)
2239 .Case("p4", AArch64::P4)
2240 .Case("p5", AArch64::P5)
2241 .Case("p6", AArch64::P6)
2242 .Case("p7", AArch64::P7)
2243 .Case("p8", AArch64::P8)
2244 .Case("p9", AArch64::P9)
2245 .Case("p10", AArch64::P10)
2246 .Case("p11", AArch64::P11)
2247 .Case("p12", AArch64::P12)
2248 .Case("p13", AArch64::P13)
2249 .Case("p14", AArch64::P14)
2250 .Case("p15", AArch64::P15)
2251 .Default(0);
2252}
2253
Tim Northover3b0846e2014-05-24 12:50:23 +00002254bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2255 SMLoc &EndLoc) {
2256 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002257 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002258 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002259 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002260}
2261
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002262// Matches a register name or register alias previously defined by '.req'
2263unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002264 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002265 unsigned RegNum = 0;
2266 if ((RegNum = matchSVEDataVectorRegName(Name)))
2267 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2268
Sander de Smalencd6be962017-12-20 11:02:42 +00002269 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2270 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2271
Sander de Smalenc067c302017-12-20 09:45:45 +00002272 if ((RegNum = MatchNeonVectorRegName(Name)))
2273 return Kind == RegKind::NeonVector ? RegNum : 0;
2274
2275 // The parsed register must be of RegKind Scalar
2276 if ((RegNum = MatchRegisterName(Name)))
2277 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002278
Florian Hahnc4422242017-11-07 13:07:50 +00002279 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002280 // Handle a few common aliases of registers.
2281 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2282 .Case("fp", AArch64::FP)
2283 .Case("lr", AArch64::LR)
2284 .Case("x31", AArch64::XZR)
2285 .Case("w31", AArch64::WZR)
2286 .Default(0))
2287 return Kind == RegKind::Scalar ? RegNum : 0;
2288
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002289 // Check for aliases registered via .req. Canonicalize to lower case.
2290 // That's more consistent since register names are case insensitive, and
2291 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2292 auto Entry = RegisterReqs.find(Name.lower());
2293 if (Entry == RegisterReqs.end())
2294 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002295
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002296 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002297 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002298 RegNum = Entry->getValue().second;
2299 }
2300 return RegNum;
2301}
2302
Sander de Smalen50d87022018-04-19 07:35:08 +00002303/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002304/// Identifier when called, and if it is a register name the token is eaten and
2305/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002306OperandMatchResultTy
2307AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002308 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002309 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002310 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002311 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002312
2313 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002314 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2315 if (Reg == 0)
2316 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002317
Sander de Smalen50d87022018-04-19 07:35:08 +00002318 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002319 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002320 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002321}
2322
Tim Northover3b0846e2014-05-24 12:50:23 +00002323/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002324OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002325AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002326 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002327 SMLoc S = getLoc();
2328
2329 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2330 Error(S, "Expected cN operand where 0 <= N <= 15");
2331 return MatchOperand_ParseFail;
2332 }
2333
2334 StringRef Tok = Parser.getTok().getIdentifier();
2335 if (Tok[0] != 'c' && Tok[0] != 'C') {
2336 Error(S, "Expected cN operand where 0 <= N <= 15");
2337 return MatchOperand_ParseFail;
2338 }
2339
2340 uint32_t CRNum;
2341 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2342 if (BadNum || CRNum > 15) {
2343 Error(S, "Expected cN operand where 0 <= N <= 15");
2344 return MatchOperand_ParseFail;
2345 }
2346
2347 Parser.Lex(); // Eat identifier token.
2348 Operands.push_back(
2349 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2350 return MatchOperand_Success;
2351}
2352
2353/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002354template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002355OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002356AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002357 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002358 SMLoc S = getLoc();
2359 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002360
2361 auto LookupByName = [](StringRef N) {
2362 if (IsSVEPrefetch) {
2363 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2364 return Optional<unsigned>(Res->Encoding);
2365 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2366 return Optional<unsigned>(Res->Encoding);
2367 return Optional<unsigned>();
2368 };
2369
2370 auto LookupByEncoding = [](unsigned E) {
2371 if (IsSVEPrefetch) {
2372 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2373 return Optional<StringRef>(Res->Name);
2374 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2375 return Optional<StringRef>(Res->Name);
2376 return Optional<StringRef>();
2377 };
2378 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2379
Tim Northover3b0846e2014-05-24 12:50:23 +00002380 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002381 // Eat optional hash.
2382 if (parseOptionalToken(AsmToken::Hash) ||
2383 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002384 const MCExpr *ImmVal;
2385 if (getParser().parseExpression(ImmVal))
2386 return MatchOperand_ParseFail;
2387
2388 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2389 if (!MCE) {
2390 TokError("immediate value expected for prefetch operand");
2391 return MatchOperand_ParseFail;
2392 }
2393 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002394 if (prfop > MaxVal) {
2395 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2396 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002397 return MatchOperand_ParseFail;
2398 }
2399
Sander de Smalen93380372018-05-14 11:54:41 +00002400 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002401 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002402 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002403 return MatchOperand_Success;
2404 }
2405
2406 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002407 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002408 return MatchOperand_ParseFail;
2409 }
2410
Sander de Smalen93380372018-05-14 11:54:41 +00002411 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002412 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002413 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002414 return MatchOperand_ParseFail;
2415 }
2416
2417 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002418 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002419 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002420 return MatchOperand_Success;
2421}
2422
Oliver Stannarda34e4702015-12-01 10:48:51 +00002423/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002424OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002425AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2426 MCAsmParser &Parser = getParser();
2427 SMLoc S = getLoc();
2428 const AsmToken &Tok = Parser.getTok();
2429 if (Tok.isNot(AsmToken::Identifier)) {
2430 TokError("invalid operand for instruction");
2431 return MatchOperand_ParseFail;
2432 }
2433
Tim Northovere6ae6762016-07-05 21:23:04 +00002434 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2435 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002436 TokError("invalid operand for instruction");
2437 return MatchOperand_ParseFail;
2438 }
2439
2440 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002441 Operands.push_back(AArch64Operand::CreatePSBHint(
2442 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002443 return MatchOperand_Success;
2444}
2445
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00002446/// tryParseBTIHint - Try to parse a BTI operand, mapped to Hint command
2447OperandMatchResultTy
2448AArch64AsmParser::tryParseBTIHint(OperandVector &Operands) {
2449 MCAsmParser &Parser = getParser();
2450 SMLoc S = getLoc();
2451 const AsmToken &Tok = Parser.getTok();
2452 if (Tok.isNot(AsmToken::Identifier)) {
2453 TokError("invalid operand for instruction");
2454 return MatchOperand_ParseFail;
2455 }
2456
2457 auto BTI = AArch64BTIHint::lookupBTIByName(Tok.getString());
2458 if (!BTI) {
2459 TokError("invalid operand for instruction");
2460 return MatchOperand_ParseFail;
2461 }
2462
2463 Parser.Lex(); // Eat identifier token.
2464 Operands.push_back(AArch64Operand::CreateBTIHint(
2465 BTI->Encoding, Tok.getString(), S, getContext()));
2466 return MatchOperand_Success;
2467}
2468
Tim Northover3b0846e2014-05-24 12:50:23 +00002469/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2470/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002471OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002472AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002473 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002474 SMLoc S = getLoc();
2475 const MCExpr *Expr;
2476
2477 if (Parser.getTok().is(AsmToken::Hash)) {
2478 Parser.Lex(); // Eat hash token.
2479 }
2480
2481 if (parseSymbolicImmVal(Expr))
2482 return MatchOperand_ParseFail;
2483
2484 AArch64MCExpr::VariantKind ELFRefKind;
2485 MCSymbolRefExpr::VariantKind DarwinRefKind;
2486 int64_t Addend;
2487 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2488 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2489 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2490 // No modifier was specified at all; this is the syntax for an ELF basic
2491 // ADRP relocation (unfortunately).
2492 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002493 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002494 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2495 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2496 Addend != 0) {
2497 Error(S, "gotpage label reference not allowed an addend");
2498 return MatchOperand_ParseFail;
2499 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2500 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2501 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2502 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2503 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2504 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2505 // The operand must be an @page or @gotpage qualified symbolref.
2506 Error(S, "page or gotpage label reference expected");
2507 return MatchOperand_ParseFail;
2508 }
2509 }
2510
2511 // We have either a label reference possibly with addend or an immediate. The
2512 // addend is a raw value here. The linker will adjust it to only reference the
2513 // page.
2514 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2515 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2516
2517 return MatchOperand_Success;
2518}
2519
2520/// tryParseAdrLabel - Parse and validate a source label for the ADR
2521/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002522OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002523AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2524 SMLoc S = getLoc();
2525 const MCExpr *Expr;
2526
David Green9dd1d452018-08-22 11:31:39 +00002527 // Leave anything with a bracket to the default for SVE
2528 if (getParser().getTok().is(AsmToken::LBrac))
2529 return MatchOperand_NoMatch;
2530
2531 if (getParser().getTok().is(AsmToken::Hash))
2532 getParser().Lex(); // Eat hash token.
2533
2534 if (parseSymbolicImmVal(Expr))
2535 return MatchOperand_ParseFail;
2536
2537 AArch64MCExpr::VariantKind ELFRefKind;
2538 MCSymbolRefExpr::VariantKind DarwinRefKind;
2539 int64_t Addend;
2540 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2541 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2542 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2543 // No modifier was specified at all; this is the syntax for an ELF basic
2544 // ADR relocation (unfortunately).
2545 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS, getContext());
2546 } else {
2547 Error(S, "unexpected adr label");
Sander de Smalenc69944c2018-07-09 09:58:24 +00002548 return MatchOperand_ParseFail;
David Green9dd1d452018-08-22 11:31:39 +00002549 }
Sander de Smalenc69944c2018-07-09 09:58:24 +00002550 }
David Green9dd1d452018-08-22 11:31:39 +00002551
2552 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2553 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2554 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002555}
2556
2557/// tryParseFPImm - A floating point immediate expression operand.
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002558template<bool AddFPZeroAsLiteral>
Alex Bradbury58eba092016-11-01 16:32:05 +00002559OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002560AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002561 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002562 SMLoc S = getLoc();
2563
Nirav Davee833c6c2016-11-08 18:31:04 +00002564 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002565
2566 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002567 bool isNegative = parseOptionalToken(AsmToken::Minus);
2568
Tim Northover3b0846e2014-05-24 12:50:23 +00002569 const AsmToken &Tok = Parser.getTok();
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002570 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2571 if (!Hash)
2572 return MatchOperand_NoMatch;
2573 TokError("invalid floating point immediate");
2574 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002575 }
2576
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002577 // Parse hexadecimal representation.
2578 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2579 if (Tok.getIntVal() > 255 || isNegative) {
2580 TokError("encoded floating point value out of range");
2581 return MatchOperand_ParseFail;
2582 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002583
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002584 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2585 Operands.push_back(
2586 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2587 } else {
2588 // Parse FP representation.
2589 APFloat RealVal(APFloat::IEEEdouble());
2590 auto Status =
2591 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2592 if (isNegative)
2593 RealVal.changeSign();
2594
2595 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2596 Operands.push_back(
2597 AArch64Operand::CreateToken("#0", false, S, getContext()));
2598 Operands.push_back(
2599 AArch64Operand::CreateToken(".0", false, S, getContext()));
2600 } else
2601 Operands.push_back(AArch64Operand::CreateFPImm(
2602 RealVal, Status == APFloat::opOK, S, getContext()));
2603 }
2604
2605 Parser.Lex(); // Eat the token.
2606
2607 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002608}
2609
Sander de Smalen62770792018-05-25 09:47:52 +00002610/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2611/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002612OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002613AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002614 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002615 SMLoc S = getLoc();
2616
2617 if (Parser.getTok().is(AsmToken::Hash))
2618 Parser.Lex(); // Eat '#'
2619 else if (Parser.getTok().isNot(AsmToken::Integer))
2620 // Operand should start from # or should be integer, emit error otherwise.
2621 return MatchOperand_NoMatch;
2622
2623 const MCExpr *Imm;
2624 if (parseSymbolicImmVal(Imm))
2625 return MatchOperand_ParseFail;
2626 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002627 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002628 Operands.push_back(
2629 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002630 return MatchOperand_Success;
2631 }
2632
2633 // Eat ','
2634 Parser.Lex();
2635
2636 // The optional operand must be "lsl #N" where N is non-negative.
2637 if (!Parser.getTok().is(AsmToken::Identifier) ||
2638 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2639 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2640 return MatchOperand_ParseFail;
2641 }
2642
2643 // Eat 'lsl'
2644 Parser.Lex();
2645
Nirav Davee833c6c2016-11-08 18:31:04 +00002646 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002647
2648 if (Parser.getTok().isNot(AsmToken::Integer)) {
2649 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2650 return MatchOperand_ParseFail;
2651 }
2652
2653 int64_t ShiftAmount = Parser.getTok().getIntVal();
2654
2655 if (ShiftAmount < 0) {
2656 Error(Parser.getTok().getLoc(), "positive shift amount required");
2657 return MatchOperand_ParseFail;
2658 }
2659 Parser.Lex(); // Eat the number
2660
Sander de Smalen62770792018-05-25 09:47:52 +00002661 // Just in case the optional lsl #0 is used for immediates other than zero.
2662 if (ShiftAmount == 0 && Imm != 0) {
2663 SMLoc E = Parser.getTok().getLoc();
2664 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2665 return MatchOperand_Success;
2666 }
2667
Tim Northover3b0846e2014-05-24 12:50:23 +00002668 SMLoc E = Parser.getTok().getLoc();
2669 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2670 S, E, getContext()));
2671 return MatchOperand_Success;
2672}
2673
2674/// parseCondCodeString - Parse a Condition Code string.
2675AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2676 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2677 .Case("eq", AArch64CC::EQ)
2678 .Case("ne", AArch64CC::NE)
2679 .Case("cs", AArch64CC::HS)
2680 .Case("hs", AArch64CC::HS)
2681 .Case("cc", AArch64CC::LO)
2682 .Case("lo", AArch64CC::LO)
2683 .Case("mi", AArch64CC::MI)
2684 .Case("pl", AArch64CC::PL)
2685 .Case("vs", AArch64CC::VS)
2686 .Case("vc", AArch64CC::VC)
2687 .Case("hi", AArch64CC::HI)
2688 .Case("ls", AArch64CC::LS)
2689 .Case("ge", AArch64CC::GE)
2690 .Case("lt", AArch64CC::LT)
2691 .Case("gt", AArch64CC::GT)
2692 .Case("le", AArch64CC::LE)
2693 .Case("al", AArch64CC::AL)
2694 .Case("nv", AArch64CC::NV)
2695 .Default(AArch64CC::Invalid);
Sander de Smalene31e6d42018-07-04 08:50:49 +00002696
2697 if (CC == AArch64CC::Invalid &&
2698 getSTI().getFeatureBits()[AArch64::FeatureSVE])
2699 CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2700 .Case("none", AArch64CC::EQ)
2701 .Case("any", AArch64CC::NE)
2702 .Case("nlast", AArch64CC::HS)
2703 .Case("last", AArch64CC::LO)
2704 .Case("first", AArch64CC::MI)
2705 .Case("nfrst", AArch64CC::PL)
2706 .Case("pmore", AArch64CC::HI)
2707 .Case("plast", AArch64CC::LS)
2708 .Case("tcont", AArch64CC::GE)
2709 .Case("tstop", AArch64CC::LT)
2710 .Default(AArch64CC::Invalid);
2711
Tim Northover3b0846e2014-05-24 12:50:23 +00002712 return CC;
2713}
2714
2715/// parseCondCode - Parse a Condition Code operand.
2716bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2717 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002718 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002719 SMLoc S = getLoc();
2720 const AsmToken &Tok = Parser.getTok();
2721 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2722
2723 StringRef Cond = Tok.getString();
2724 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2725 if (CC == AArch64CC::Invalid)
2726 return TokError("invalid condition code");
2727 Parser.Lex(); // Eat identifier token.
2728
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002729 if (invertCondCode) {
2730 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2731 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002732 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002733 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002734
2735 Operands.push_back(
2736 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2737 return false;
2738}
2739
2740/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2741/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002742OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002743AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002744 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002745 const AsmToken &Tok = Parser.getTok();
2746 std::string LowerID = Tok.getString().lower();
2747 AArch64_AM::ShiftExtendType ShOp =
2748 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2749 .Case("lsl", AArch64_AM::LSL)
2750 .Case("lsr", AArch64_AM::LSR)
2751 .Case("asr", AArch64_AM::ASR)
2752 .Case("ror", AArch64_AM::ROR)
2753 .Case("msl", AArch64_AM::MSL)
2754 .Case("uxtb", AArch64_AM::UXTB)
2755 .Case("uxth", AArch64_AM::UXTH)
2756 .Case("uxtw", AArch64_AM::UXTW)
2757 .Case("uxtx", AArch64_AM::UXTX)
2758 .Case("sxtb", AArch64_AM::SXTB)
2759 .Case("sxth", AArch64_AM::SXTH)
2760 .Case("sxtw", AArch64_AM::SXTW)
2761 .Case("sxtx", AArch64_AM::SXTX)
2762 .Default(AArch64_AM::InvalidShiftExtend);
2763
2764 if (ShOp == AArch64_AM::InvalidShiftExtend)
2765 return MatchOperand_NoMatch;
2766
2767 SMLoc S = Tok.getLoc();
2768 Parser.Lex();
2769
Nirav Davee833c6c2016-11-08 18:31:04 +00002770 bool Hash = parseOptionalToken(AsmToken::Hash);
2771
Tim Northover3b0846e2014-05-24 12:50:23 +00002772 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2773 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2774 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2775 ShOp == AArch64_AM::MSL) {
2776 // We expect a number here.
2777 TokError("expected #imm after shift specifier");
2778 return MatchOperand_ParseFail;
2779 }
2780
Chad Rosier2ff37b82016-12-27 16:58:09 +00002781 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002782 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2783 Operands.push_back(
2784 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2785 return MatchOperand_Success;
2786 }
2787
Chad Rosier2ff37b82016-12-27 16:58:09 +00002788 // Make sure we do actually have a number, identifier or a parenthesized
2789 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002790 SMLoc E = Parser.getTok().getLoc();
2791 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002792 !Parser.getTok().is(AsmToken::LParen) &&
2793 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002794 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002795 return MatchOperand_ParseFail;
2796 }
2797
2798 const MCExpr *ImmVal;
2799 if (getParser().parseExpression(ImmVal))
2800 return MatchOperand_ParseFail;
2801
2802 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2803 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002804 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002805 return MatchOperand_ParseFail;
2806 }
2807
Jim Grosbach57fd2622014-09-23 22:16:02 +00002808 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002809 Operands.push_back(AArch64Operand::CreateShiftExtend(
2810 ShOp, MCE->getValue(), true, S, E, getContext()));
2811 return MatchOperand_Success;
2812}
2813
Oliver Stannard89b16042018-09-26 13:52:27 +00002814static const struct Extension {
2815 const char *Name;
2816 const FeatureBitset Features;
2817} ExtensionMap[] = {
Diogo N. Sampaio9c906732018-12-06 15:39:17 +00002818 {"crc", {AArch64::FeatureCRC}},
2819 {"sm4", {AArch64::FeatureSM4}},
2820 {"sha3", {AArch64::FeatureSHA3}},
2821 {"sha2", {AArch64::FeatureSHA2}},
2822 {"aes", {AArch64::FeatureAES}},
2823 {"crypto", {AArch64::FeatureCrypto}},
2824 {"fp", {AArch64::FeatureFPARMv8}},
2825 {"simd", {AArch64::FeatureNEON}},
2826 {"ras", {AArch64::FeatureRAS}},
2827 {"lse", {AArch64::FeatureLSE}},
2828 {"predctrl", {AArch64::FeaturePredCtrl}},
2829 {"ccdp", {AArch64::FeatureCacheDeepPersist}},
2830 {"mte", {AArch64::FeatureMTE}},
2831 {"tlb-rmi", {AArch64::FeatureTLB_RMI}},
2832 {"pan-rwv", {AArch64::FeaturePAN_RWV}},
2833 {"ccpp", {AArch64::FeatureCCPP}},
2834 // FIXME: Unsupported extensions
2835 {"pan", {}},
2836 {"lor", {}},
2837 {"rdma", {}},
2838 {"profile", {}},
Oliver Stannard89b16042018-09-26 13:52:27 +00002839};
2840
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002841static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2842 if (FBS[AArch64::HasV8_1aOps])
2843 Str += "ARMv8.1a";
2844 else if (FBS[AArch64::HasV8_2aOps])
2845 Str += "ARMv8.2a";
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002846 else if (FBS[AArch64::HasV8_3aOps])
2847 Str += "ARMv8.3a";
2848 else if (FBS[AArch64::HasV8_4aOps])
2849 Str += "ARMv8.4a";
Oliver Stannard89b16042018-09-26 13:52:27 +00002850 else if (FBS[AArch64::HasV8_5aOps])
2851 Str += "ARMv8.5a";
2852 else {
2853 auto ext = std::find_if(std::begin(ExtensionMap),
2854 std::end(ExtensionMap),
2855 [&](const Extension& e)
2856 // Use & in case multiple features are enabled
2857 { return (FBS & e.Features) != FeatureBitset(); }
2858 );
2859
2860 Str += ext != std::end(ExtensionMap) ? ext->Name : "(unknown)";
2861 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002862}
2863
2864void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2865 SMLoc S) {
2866 const uint16_t Op2 = Encoding & 7;
2867 const uint16_t Cm = (Encoding & 0x78) >> 3;
2868 const uint16_t Cn = (Encoding & 0x780) >> 7;
2869 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2870
2871 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2872
2873 Operands.push_back(
2874 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2875 Operands.push_back(
2876 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2877 Operands.push_back(
2878 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2879 Expr = MCConstantExpr::create(Op2, getContext());
2880 Operands.push_back(
2881 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2882}
2883
Tim Northover3b0846e2014-05-24 12:50:23 +00002884/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2885/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2886bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2887 OperandVector &Operands) {
2888 if (Name.find('.') != StringRef::npos)
2889 return TokError("invalid operand");
2890
2891 Mnemonic = Name;
2892 Operands.push_back(
2893 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2894
Rafael Espindola961d4692014-11-11 05:18:41 +00002895 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002896 const AsmToken &Tok = Parser.getTok();
2897 StringRef Op = Tok.getString();
2898 SMLoc S = Tok.getLoc();
2899
Tim Northover3b0846e2014-05-24 12:50:23 +00002900 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002901 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2902 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002903 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002904 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2905 std::string Str("IC " + std::string(IC->Name) + " requires ");
2906 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2907 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002908 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002909 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002910 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002911 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2912 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002913 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002914 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2915 std::string Str("DC " + std::string(DC->Name) + " requires ");
2916 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2917 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002918 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002919 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002920 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002921 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2922 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002923 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002924 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2925 std::string Str("AT " + std::string(AT->Name) + " requires ");
2926 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2927 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002928 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002929 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002930 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002931 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2932 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002933 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002934 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2935 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2936 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2937 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002938 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002939 createSysAlias(TLBI->Encoding, Operands, S);
Oliver Stannard224428c2018-09-27 13:47:40 +00002940 } else if (Mnemonic == "cfp" || Mnemonic == "dvp" || Mnemonic == "cpp") {
2941 const AArch64PRCTX::PRCTX *PRCTX = AArch64PRCTX::lookupPRCTXByName(Op);
2942 if (!PRCTX)
2943 return TokError("invalid operand for prediction restriction instruction");
2944 else if (!PRCTX->haveFeatures(getSTI().getFeatureBits())) {
2945 std::string Str(
2946 Mnemonic.upper() + std::string(PRCTX->Name) + " requires ");
2947 setRequiredFeatureString(PRCTX->getRequiredFeatures(), Str);
2948 return TokError(Str.c_str());
2949 }
2950 uint16_t PRCTX_Op2 =
2951 Mnemonic == "cfp" ? 4 :
2952 Mnemonic == "dvp" ? 5 :
2953 Mnemonic == "cpp" ? 7 :
2954 0;
2955 assert(PRCTX_Op2 && "Invalid mnemonic for prediction restriction instruction");
2956 createSysAlias(PRCTX->Encoding << 3 | PRCTX_Op2 , Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002957 }
2958
Tim Northover3b0846e2014-05-24 12:50:23 +00002959 Parser.Lex(); // Eat operand.
2960
2961 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2962 bool HasRegister = false;
2963
2964 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002965 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002966 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2967 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002968 HasRegister = true;
2969 }
2970
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002971 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002972 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002973 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002974 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002975
Nirav Davee833c6c2016-11-08 18:31:04 +00002976 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2977 return true;
2978
Tim Northover3b0846e2014-05-24 12:50:23 +00002979 return false;
2980}
2981
Alex Bradbury58eba092016-11-01 16:32:05 +00002982OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002983AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002984 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002985 const AsmToken &Tok = Parser.getTok();
2986
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002987 if (Mnemonic == "tsb" && Tok.isNot(AsmToken::Identifier)) {
2988 TokError("'csync' operand expected");
2989 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002990 // Can be either a #imm style literal or an option name
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002991 } else if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002992 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002993 const MCExpr *ImmVal;
2994 SMLoc ExprLoc = getLoc();
2995 if (getParser().parseExpression(ImmVal))
2996 return MatchOperand_ParseFail;
2997 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2998 if (!MCE) {
2999 Error(ExprLoc, "immediate value expected for barrier operand");
3000 return MatchOperand_ParseFail;
3001 }
3002 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
3003 Error(ExprLoc, "barrier operand out of range");
3004 return MatchOperand_ParseFail;
3005 }
Tim Northovere6ae6762016-07-05 21:23:04 +00003006 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
3007 Operands.push_back(AArch64Operand::CreateBarrier(
3008 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003009 return MatchOperand_Success;
3010 }
3011
3012 if (Tok.isNot(AsmToken::Identifier)) {
3013 TokError("invalid operand for instruction");
3014 return MatchOperand_ParseFail;
3015 }
3016
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003017 auto TSB = AArch64TSB::lookupTSBByName(Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003018 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00003019 auto DB = AArch64DB::lookupDBByName(Tok.getString());
3020 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003021 TokError("'sy' or #imm operand expected");
3022 return MatchOperand_ParseFail;
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003023 // The only valid named option for TSB is 'csync'
3024 } else if (Mnemonic == "tsb" && (!TSB || TSB->Encoding != AArch64TSB::csync)) {
3025 TokError("'csync' operand expected");
3026 return MatchOperand_ParseFail;
3027 } else if (!DB && !TSB) {
Sjoerd Meijere5b85572017-04-24 08:22:20 +00003028 TokError("invalid barrier option name");
3029 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003030 }
3031
Tim Northovere6ae6762016-07-05 21:23:04 +00003032 Operands.push_back(AArch64Operand::CreateBarrier(
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003033 DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003034 Parser.Lex(); // Consume the option
3035
3036 return MatchOperand_Success;
3037}
3038
Alex Bradbury58eba092016-11-01 16:32:05 +00003039OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003040AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003041 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003042 const AsmToken &Tok = Parser.getTok();
3043
3044 if (Tok.isNot(AsmToken::Identifier))
3045 return MatchOperand_NoMatch;
3046
Tim Northovere6ae6762016-07-05 21:23:04 +00003047 int MRSReg, MSRReg;
3048 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
3049 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
3050 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
3051 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
3052 } else
3053 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00003054
Tim Northovere6ae6762016-07-05 21:23:04 +00003055 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
3056 unsigned PStateImm = -1;
3057 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
3058 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00003059
Tim Northovere6ae6762016-07-05 21:23:04 +00003060 Operands.push_back(
3061 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
3062 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003063 Parser.Lex(); // Eat identifier
3064
3065 return MatchOperand_Success;
3066}
3067
Florian Hahnc4422242017-11-07 13:07:50 +00003068/// tryParseNeonVectorRegister - Parse a vector register operand.
3069bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003070 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003071 if (Parser.getTok().isNot(AsmToken::Identifier))
3072 return true;
3073
3074 SMLoc S = getLoc();
3075 // Check for a vector register specifier first.
3076 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003077 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00003078 OperandMatchResultTy Res =
3079 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
3080 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00003081 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00003082
3083 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
3084 if (!KindRes)
3085 return true;
3086
3087 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00003088 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00003089 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
3090 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00003091
Tim Northover3b0846e2014-05-24 12:50:23 +00003092 // If there was an explicit qualifier, that goes on as a literal text
3093 // operand.
3094 if (!Kind.empty())
3095 Operands.push_back(
3096 AArch64Operand::CreateToken(Kind, false, S, getContext()));
3097
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003098 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3099}
3100
3101OperandMatchResultTy
3102AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00003103 SMLoc SIdx = getLoc();
3104 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003105 const MCExpr *ImmVal;
3106 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003107 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00003108 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3109 if (!MCE) {
3110 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003111 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00003112 }
3113
3114 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003115
Nirav Davee833c6c2016-11-08 18:31:04 +00003116 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003117 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00003118
3119 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
3120 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003121 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003122 }
3123
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003124 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00003125}
3126
Sander de Smalen73937b72018-04-11 07:36:10 +00003127// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00003128// optional kind specifier. If it is a register specifier, eat the token
3129// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00003130OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00003131AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00003132 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00003133 MCAsmParser &Parser = getParser();
3134 const AsmToken &Tok = Parser.getTok();
3135
Florian Hahn91f11e52017-11-07 16:45:48 +00003136 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00003137 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003138
3139 StringRef Name = Tok.getString();
3140 // If there is a kind specifier, it's separated from the register name by
3141 // a '.'.
3142 size_t Start = 0, Next = Name.find('.');
3143 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00003144 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00003145
3146 if (RegNum) {
3147 if (Next != StringRef::npos) {
3148 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00003149 if (!isValidVectorKind(Kind, MatchKind)) {
3150 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00003151 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00003152 }
3153 }
Sander de Smalen8e607342017-11-15 15:44:43 +00003154 Parser.Lex(); // Eat the register token.
3155
3156 Reg = RegNum;
3157 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00003158 }
3159
Sander de Smalen8e607342017-11-15 15:44:43 +00003160 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003161}
3162
Sander de Smalencd6be962017-12-20 11:02:42 +00003163/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
3164OperandMatchResultTy
3165AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
3166 // Check for a SVE predicate register specifier first.
3167 const SMLoc S = getLoc();
3168 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003169 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00003170 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00003171 if (Res != MatchOperand_Success)
3172 return Res;
3173
Sander de Smalen73937b72018-04-11 07:36:10 +00003174 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
3175 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00003176 return MatchOperand_NoMatch;
3177
Sander de Smalen73937b72018-04-11 07:36:10 +00003178 unsigned ElementWidth = KindRes->second;
3179 Operands.push_back(AArch64Operand::CreateVectorReg(
3180 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
3181 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00003182
Sander de Smalen7868e742018-01-09 11:17:06 +00003183 // Not all predicates are followed by a '/m' or '/z'.
3184 MCAsmParser &Parser = getParser();
3185 if (Parser.getTok().isNot(AsmToken::Slash))
3186 return MatchOperand_Success;
3187
3188 // But when they do they shouldn't have an element type suffix.
3189 if (!Kind.empty()) {
3190 Error(S, "not expecting size suffix");
3191 return MatchOperand_ParseFail;
3192 }
3193
3194 // Add a literal slash as operand
3195 Operands.push_back(
3196 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
3197
3198 Parser.Lex(); // Eat the slash.
3199
3200 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00003201 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00003202 if (Pred != "z" && Pred != "m") {
3203 Error(getLoc(), "expecting 'm' or 'z' predication");
3204 return MatchOperand_ParseFail;
3205 }
3206
3207 // Add zero/merge token.
3208 const char *ZM = Pred == "z" ? "z" : "m";
3209 Operands.push_back(
3210 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
3211
3212 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00003213 return MatchOperand_Success;
3214}
3215
Sander de Smalen50d87022018-04-19 07:35:08 +00003216/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00003217bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003218 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00003219 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00003220 return false;
3221
Sander de Smalen149916d2018-04-20 07:24:20 +00003222 // Otherwise try for a scalar register.
3223 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
3224 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003225
Sander de Smalen149916d2018-04-20 07:24:20 +00003226 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003227}
3228
3229bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003230 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003231 bool HasELFModifier = false;
3232 AArch64MCExpr::VariantKind RefKind;
3233
Nirav Davee833c6c2016-11-08 18:31:04 +00003234 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003235 HasELFModifier = true;
3236
Nirav Davee833c6c2016-11-08 18:31:04 +00003237 if (Parser.getTok().isNot(AsmToken::Identifier))
3238 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003239
3240 std::string LowerCase = Parser.getTok().getIdentifier().lower();
3241 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
3242 .Case("lo12", AArch64MCExpr::VK_LO12)
3243 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
3244 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
3245 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
3246 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
3247 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
3248 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
3249 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
3250 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
3251 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
3252 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
3253 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
3254 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
3255 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3256 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3257 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3258 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3259 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3260 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3261 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3262 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3263 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3264 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3265 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3266 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3267 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3268 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3269 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3270 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3271 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3272 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3273 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3274 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3275 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3276 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003277 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3278 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00003279 .Default(AArch64MCExpr::VK_INVALID);
3280
Nirav Davee833c6c2016-11-08 18:31:04 +00003281 if (RefKind == AArch64MCExpr::VK_INVALID)
3282 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003283
3284 Parser.Lex(); // Eat identifier
3285
Nirav Davee833c6c2016-11-08 18:31:04 +00003286 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003287 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003288 }
3289
3290 if (getParser().parseExpression(ImmVal))
3291 return true;
3292
3293 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003294 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003295
3296 return false;
3297}
3298
Sander de Smalen650234b2018-04-12 11:40:52 +00003299template <RegKind VectorKind>
3300OperandMatchResultTy
3301AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3302 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003303 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003304 if (!Parser.getTok().is(AsmToken::LCurly))
3305 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003306
3307 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003308 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003309 bool NoMatchIsError) {
3310 auto RegTok = Parser.getTok();
3311 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3312 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003313 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003314 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003315 llvm_unreachable("Expected a valid vector kind");
3316 }
3317
Sander de Smalen650234b2018-04-12 11:40:52 +00003318 if (RegTok.isNot(AsmToken::Identifier) ||
3319 ParseRes == MatchOperand_ParseFail ||
3320 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3321 Error(Loc, "vector register expected");
3322 return MatchOperand_ParseFail;
3323 }
3324
3325 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003326 };
3327
Tim Northover3b0846e2014-05-24 12:50:23 +00003328 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003329 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003330 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003331
Tim Northover3b0846e2014-05-24 12:50:23 +00003332 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003333 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003334 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3335
3336 // Put back the original left bracket if there was no match, so that
3337 // different types of list-operands can be matched (e.g. SVE, Neon).
3338 if (ParseRes == MatchOperand_NoMatch)
3339 Parser.getLexer().UnLex(LCurly);
3340
3341 if (ParseRes != MatchOperand_Success)
3342 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003343
Tim Northover3b0846e2014-05-24 12:50:23 +00003344 int64_t PrevReg = FirstReg;
3345 unsigned Count = 1;
3346
Nirav Davee833c6c2016-11-08 18:31:04 +00003347 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003348 SMLoc Loc = getLoc();
3349 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003350
Sander de Smalen50d87022018-04-19 07:35:08 +00003351 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003352 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3353 if (ParseRes != MatchOperand_Success)
3354 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003355
Tim Northover3b0846e2014-05-24 12:50:23 +00003356 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003357 if (Kind != NextKind) {
3358 Error(Loc, "mismatched register size suffix");
3359 return MatchOperand_ParseFail;
3360 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003361
3362 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3363
3364 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003365 Error(Loc, "invalid number of vectors");
3366 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003367 }
3368
3369 Count += Space;
3370 }
3371 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003372 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003373 SMLoc Loc = getLoc();
3374 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003375 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003376 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3377 if (ParseRes != MatchOperand_Success)
3378 return ParseRes;
3379
Tim Northover3b0846e2014-05-24 12:50:23 +00003380 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003381 if (Kind != NextKind) {
3382 Error(Loc, "mismatched register size suffix");
3383 return MatchOperand_ParseFail;
3384 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003385
3386 // Registers must be incremental (with wraparound at 31)
3387 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003388 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3389 Error(Loc, "registers must be sequential");
3390 return MatchOperand_ParseFail;
3391 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003392
3393 PrevReg = Reg;
3394 ++Count;
3395 }
3396 }
3397
Nirav Davee833c6c2016-11-08 18:31:04 +00003398 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003399 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003400
Sander de Smalen650234b2018-04-12 11:40:52 +00003401 if (Count > 4) {
3402 Error(S, "invalid number of vectors");
3403 return MatchOperand_ParseFail;
3404 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003405
3406 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003407 unsigned ElementWidth = 0;
3408 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003409 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003410 std::tie(NumElements, ElementWidth) = *VK;
3411 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003412
3413 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003414 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3415 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003416
Sander de Smalen650234b2018-04-12 11:40:52 +00003417 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003418}
3419
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003420/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3421bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003422 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3423 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003424 return true;
3425
3426 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3427}
3428
Alex Bradbury58eba092016-11-01 16:32:05 +00003429OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003430AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003431 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003432
Sander de Smalen50d87022018-04-19 07:35:08 +00003433 unsigned RegNum;
3434 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3435 if (Res != MatchOperand_Success)
3436 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003437
Nirav Davee833c6c2016-11-08 18:31:04 +00003438 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003439 Operands.push_back(AArch64Operand::CreateReg(
3440 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003441 return MatchOperand_Success;
3442 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003443
Nirav Davee833c6c2016-11-08 18:31:04 +00003444 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003445
Sander de Smalen50d87022018-04-19 07:35:08 +00003446 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003447 Error(getLoc(), "index must be absent or #0");
3448 return MatchOperand_ParseFail;
3449 }
3450
3451 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003452 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003453 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3454 Error(getLoc(), "index must be absent or #0");
3455 return MatchOperand_ParseFail;
3456 }
3457
Sander de Smalen50d87022018-04-19 07:35:08 +00003458 Operands.push_back(AArch64Operand::CreateReg(
3459 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003460 return MatchOperand_Success;
3461}
3462
Sander de Smalen0325e302018-07-02 07:34:52 +00003463template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
Sander de Smalen149916d2018-04-20 07:24:20 +00003464OperandMatchResultTy
3465AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3466 SMLoc StartLoc = getLoc();
3467
3468 unsigned RegNum;
3469 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3470 if (Res != MatchOperand_Success)
3471 return Res;
3472
3473 // No shift/extend is the default.
3474 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3475 Operands.push_back(AArch64Operand::CreateReg(
Sander de Smalen0325e302018-07-02 07:34:52 +00003476 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
Sander de Smalen149916d2018-04-20 07:24:20 +00003477 return MatchOperand_Success;
3478 }
3479
3480 // Eat the comma
3481 getParser().Lex();
3482
3483 // Match the shift
3484 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3485 Res = tryParseOptionalShiftExtend(ExtOpnd);
3486 if (Res != MatchOperand_Success)
3487 return Res;
3488
3489 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
Sander de Smalen0325e302018-07-02 07:34:52 +00003490 Operands.push_back(AArch64Operand::CreateReg(
3491 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3492 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3493 Ext->hasShiftExtendAmount()));
Sander de Smalen149916d2018-04-20 07:24:20 +00003494
3495 return MatchOperand_Success;
3496}
3497
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003498bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
Sander de Smalen5c625982018-04-13 12:56:14 +00003499 MCAsmParser &Parser = getParser();
3500
3501 // Some SVE instructions have a decoration after the immediate, i.e.
3502 // "mul vl". We parse them here and add tokens, which must be present in the
3503 // asm string in the tablegen instruction.
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003504 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3505 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
Sander de Smalen5c625982018-04-13 12:56:14 +00003506 if (!Parser.getTok().getString().equals_lower("mul") ||
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003507 !(NextIsVL || NextIsHash))
Sander de Smalen5c625982018-04-13 12:56:14 +00003508 return true;
3509
Sander de Smalen5c625982018-04-13 12:56:14 +00003510 Operands.push_back(
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003511 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
Sander de Smalen5c625982018-04-13 12:56:14 +00003512 Parser.Lex(); // Eat the "mul"
3513
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003514 if (NextIsVL) {
3515 Operands.push_back(
3516 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3517 Parser.Lex(); // Eat the "vl"
3518 return false;
3519 }
Sander de Smalen5c625982018-04-13 12:56:14 +00003520
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003521 if (NextIsHash) {
3522 Parser.Lex(); // Eat the #
3523 SMLoc S = getLoc();
3524
3525 // Parse immediate operand.
3526 const MCExpr *ImmVal;
3527 if (!Parser.parseExpression(ImmVal))
3528 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3529 Operands.push_back(AArch64Operand::CreateImm(
3530 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3531 getContext()));
3532 return MatchOperand_Success;
3533 }
3534 }
3535
3536 return Error(getLoc(), "expected 'vl' or '#<imm>'");
Sander de Smalen5c625982018-04-13 12:56:14 +00003537}
3538
Tim Northover3b0846e2014-05-24 12:50:23 +00003539/// parseOperand - Parse a arm instruction operand. For now this parses the
3540/// operand regardless of the mnemonic.
3541bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3542 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003543 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003544
3545 OperandMatchResultTy ResTy =
3546 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3547
Tim Northover3b0846e2014-05-24 12:50:23 +00003548 // Check if the current operand has a custom associated parser, if so, try to
3549 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003550 if (ResTy == MatchOperand_Success)
3551 return false;
3552 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3553 // there was a match, but an error occurred, in which case, just return that
3554 // the operand parsing failed.
3555 if (ResTy == MatchOperand_ParseFail)
3556 return true;
3557
3558 // Nothing custom, so do general case parsing.
3559 SMLoc S, E;
3560 switch (getLexer().getKind()) {
3561 default: {
3562 SMLoc S = getLoc();
3563 const MCExpr *Expr;
3564 if (parseSymbolicImmVal(Expr))
3565 return Error(S, "invalid operand");
3566
3567 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3568 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3569 return false;
3570 }
3571 case AsmToken::LBrac: {
3572 SMLoc Loc = Parser.getTok().getLoc();
3573 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3574 getContext()));
3575 Parser.Lex(); // Eat '['
3576
3577 // There's no comma after a '[', so we can parse the next operand
3578 // immediately.
3579 return parseOperand(Operands, false, false);
3580 }
3581 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003582 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003583 case AsmToken::Identifier: {
3584 // If we're expecting a Condition Code operand, then just parse that.
3585 if (isCondCode)
3586 return parseCondCode(Operands, invertCondCode);
3587
3588 // If it's a register name, parse it.
3589 if (!parseRegister(Operands))
3590 return false;
3591
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003592 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3593 // by SVE instructions.
3594 if (!parseOptionalMulOperand(Operands))
Sander de Smalen5c625982018-04-13 12:56:14 +00003595 return false;
3596
Tim Northover3b0846e2014-05-24 12:50:23 +00003597 // This could be an optional "shift" or "extend" operand.
3598 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3599 // We can only continue if no tokens were eaten.
3600 if (GotShift != MatchOperand_NoMatch)
3601 return GotShift;
3602
3603 // This was not a register so parse other operands that start with an
3604 // identifier (like labels) as expressions and create them as immediates.
3605 const MCExpr *IdVal;
3606 S = getLoc();
3607 if (getParser().parseExpression(IdVal))
3608 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003609 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3610 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3611 return false;
3612 }
3613 case AsmToken::Integer:
3614 case AsmToken::Real:
3615 case AsmToken::Hash: {
3616 // #42 -> immediate.
3617 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003618
3619 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003620
3621 // Parse a negative sign
3622 bool isNegative = false;
3623 if (Parser.getTok().is(AsmToken::Minus)) {
3624 isNegative = true;
3625 // We need to consume this token only when we have a Real, otherwise
3626 // we let parseSymbolicImmVal take care of it
3627 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3628 Parser.Lex();
3629 }
3630
3631 // The only Real that should come through here is a literal #0.0 for
3632 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3633 // so convert the value.
3634 const AsmToken &Tok = Parser.getTok();
3635 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003636 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003637 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3638 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3639 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
Sander de Smalen8fcc3f52018-07-03 09:07:23 +00003640 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
Tim Northover3b0846e2014-05-24 12:50:23 +00003641 return TokError("unexpected floating point literal");
3642 else if (IntVal != 0 || isNegative)
3643 return TokError("expected floating-point constant #0.0");
3644 Parser.Lex(); // Eat the token.
3645
3646 Operands.push_back(
3647 AArch64Operand::CreateToken("#0", false, S, getContext()));
3648 Operands.push_back(
3649 AArch64Operand::CreateToken(".0", false, S, getContext()));
3650 return false;
3651 }
3652
3653 const MCExpr *ImmVal;
3654 if (parseSymbolicImmVal(ImmVal))
3655 return true;
3656
3657 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3658 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3659 return false;
3660 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003661 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003662 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003663 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003664 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003665 Parser.Lex(); // Eat '='
3666 const MCExpr *SubExprVal;
3667 if (getParser().parseExpression(SubExprVal))
3668 return true;
3669
David Peixottoae5ba762014-07-18 16:05:14 +00003670 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003671 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003672 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003673
3674 bool IsXReg =
3675 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3676 Operands[1]->getReg());
3677
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003678 MCContext& Ctx = getContext();
3679 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3680 // 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 +00003681 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003682 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3683 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3684 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3685 ShiftAmt += 16;
3686 Imm >>= 16;
3687 }
3688 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3689 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3690 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003691 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003692 if (ShiftAmt)
3693 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3694 ShiftAmt, true, S, E, Ctx));
3695 return false;
3696 }
David Peixottoae5ba762014-07-18 16:05:14 +00003697 APInt Simm = APInt(64, Imm << ShiftAmt);
3698 // check if the immediate is an unsigned or signed 32-bit int for W regs
3699 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3700 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003701 }
3702 // 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 +00003703 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003704 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003705 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3706 return false;
3707 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003708 }
3709}
3710
Sander de Smalen0325e302018-07-02 07:34:52 +00003711bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3712 const MCParsedAsmOperand &Op2) const {
3713 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3714 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3715 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3716 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3717 return MCTargetAsmParser::regsEqual(Op1, Op2);
3718
3719 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3720 "Testing equality of non-scalar registers not supported");
3721
3722 // Check if a registers match their sub/super register classes.
3723 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3724 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3725 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3726 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3727 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3728 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3729 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3730 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3731
3732 return false;
3733}
3734
Tim Northover3b0846e2014-05-24 12:50:23 +00003735/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3736/// operands.
3737bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3738 StringRef Name, SMLoc NameLoc,
3739 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003740 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003741 Name = StringSwitch<StringRef>(Name.lower())
3742 .Case("beq", "b.eq")
3743 .Case("bne", "b.ne")
3744 .Case("bhs", "b.hs")
3745 .Case("bcs", "b.cs")
3746 .Case("blo", "b.lo")
3747 .Case("bcc", "b.cc")
3748 .Case("bmi", "b.mi")
3749 .Case("bpl", "b.pl")
3750 .Case("bvs", "b.vs")
3751 .Case("bvc", "b.vc")
3752 .Case("bhi", "b.hi")
3753 .Case("bls", "b.ls")
3754 .Case("bge", "b.ge")
3755 .Case("blt", "b.lt")
3756 .Case("bgt", "b.gt")
3757 .Case("ble", "b.le")
3758 .Case("bal", "b.al")
3759 .Case("bnv", "b.nv")
3760 .Default(Name);
3761
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003762 // First check for the AArch64-specific .req directive.
3763 if (Parser.getTok().is(AsmToken::Identifier) &&
3764 Parser.getTok().getIdentifier() == ".req") {
3765 parseDirectiveReq(Name, NameLoc);
3766 // We always return 'error' for this, as we're done with this
3767 // statement and don't need to match the 'instruction."
3768 return true;
3769 }
3770
Tim Northover3b0846e2014-05-24 12:50:23 +00003771 // Create the leading tokens for the mnemonic, split by '.' characters.
3772 size_t Start = 0, Next = Name.find('.');
3773 StringRef Head = Name.slice(Start, Next);
3774
Oliver Stannard224428c2018-09-27 13:47:40 +00003775 // IC, DC, AT, TLBI and Prediction invalidation instructions are aliases for
3776 // the SYS instruction.
3777 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi" ||
3778 Head == "cfp" || Head == "dvp" || Head == "cpp")
Nirav Davee833c6c2016-11-08 18:31:04 +00003779 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003780
3781 Operands.push_back(
3782 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3783 Mnemonic = Head;
3784
3785 // Handle condition codes for a branch mnemonic
3786 if (Head == "b" && Next != StringRef::npos) {
3787 Start = Next;
3788 Next = Name.find('.', Start + 1);
3789 Head = Name.slice(Start + 1, Next);
3790
3791 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3792 (Head.data() - Name.data()));
3793 AArch64CC::CondCode CC = parseCondCodeString(Head);
3794 if (CC == AArch64CC::Invalid)
3795 return Error(SuffixLoc, "invalid condition code");
3796 Operands.push_back(
3797 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3798 Operands.push_back(
3799 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3800 }
3801
3802 // Add the remaining tokens in the mnemonic.
3803 while (Next != StringRef::npos) {
3804 Start = Next;
3805 Next = Name.find('.', Start + 1);
3806 Head = Name.slice(Start, Next);
3807 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3808 (Head.data() - Name.data()) + 1);
3809 Operands.push_back(
3810 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3811 }
3812
3813 // Conditional compare instructions have a Condition Code operand, which needs
3814 // to be parsed and an immediate operand created.
3815 bool condCodeFourthOperand =
3816 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3817 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3818 Head == "csinc" || Head == "csinv" || Head == "csneg");
3819
3820 // These instructions are aliases to some of the conditional select
3821 // instructions. However, the condition code is inverted in the aliased
3822 // instruction.
3823 //
3824 // FIXME: Is this the correct way to handle these? Or should the parser
3825 // generate the aliased instructions directly?
3826 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3827 bool condCodeThirdOperand =
3828 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3829
3830 // Read the remaining operands.
3831 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003832
Oliver Stannardc4190282018-10-02 10:04:39 +00003833 unsigned N = 1;
3834 do {
Tim Northover3b0846e2014-05-24 12:50:23 +00003835 // Parse and remember the operand.
3836 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3837 (N == 3 && condCodeThirdOperand) ||
3838 (N == 2 && condCodeSecondOperand),
3839 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003840 return true;
3841 }
3842
3843 // After successfully parsing some operands there are two special cases to
3844 // consider (i.e. notional operands not separated by commas). Both are due
3845 // to memory specifiers:
3846 // + An RBrac will end an address for load/store/prefetch
3847 // + An '!' will indicate a pre-indexed operation.
3848 //
3849 // It's someone else's responsibility to make sure these tokens are sane
3850 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003851
Nirav Davee833c6c2016-11-08 18:31:04 +00003852 SMLoc RLoc = Parser.getTok().getLoc();
3853 if (parseOptionalToken(AsmToken::RBrac))
3854 Operands.push_back(
3855 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3856 SMLoc ELoc = Parser.getTok().getLoc();
3857 if (parseOptionalToken(AsmToken::Exclaim))
3858 Operands.push_back(
3859 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003860
3861 ++N;
Oliver Stannardc4190282018-10-02 10:04:39 +00003862 } while (parseOptionalToken(AsmToken::Comma));
Tim Northover3b0846e2014-05-24 12:50:23 +00003863 }
3864
Nirav Davee833c6c2016-11-08 18:31:04 +00003865 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3866 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003867
Tim Northover3b0846e2014-05-24 12:50:23 +00003868 return false;
3869}
3870
Sander de Smalen9b333092018-07-30 15:42:46 +00003871static inline bool isMatchingOrAlias(unsigned ZReg, unsigned Reg) {
3872 assert((ZReg >= AArch64::Z0) && (ZReg <= AArch64::Z31));
3873 return (ZReg == ((Reg - AArch64::B0) + AArch64::Z0)) ||
3874 (ZReg == ((Reg - AArch64::H0) + AArch64::Z0)) ||
3875 (ZReg == ((Reg - AArch64::S0) + AArch64::Z0)) ||
3876 (ZReg == ((Reg - AArch64::D0) + AArch64::Z0)) ||
3877 (ZReg == ((Reg - AArch64::Q0) + AArch64::Z0)) ||
3878 (ZReg == ((Reg - AArch64::Z0) + AArch64::Z0));
3879}
3880
Tim Northover3b0846e2014-05-24 12:50:23 +00003881// FIXME: This entire function is a giant hack to provide us with decent
3882// operand range validation/diagnostics until TableGen/MC can be extended
3883// to support autogeneration of this kind of validation.
Sander de Smalen9b333092018-07-30 15:42:46 +00003884bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
3885 SmallVectorImpl<SMLoc> &Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003886 const MCRegisterInfo *RI = getContext().getRegisterInfo();
Sander de Smalen9b333092018-07-30 15:42:46 +00003887 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
3888
3889 // A prefix only applies to the instruction following it. Here we extract
3890 // prefix information for the next instruction before validating the current
3891 // one so that in the case of failure we don't erronously continue using the
3892 // current prefix.
3893 PrefixInfo Prefix = NextPrefix;
3894 NextPrefix = PrefixInfo::CreateFromInst(Inst, MCID.TSFlags);
3895
3896 // Before validating the instruction in isolation we run through the rules
3897 // applicable when it follows a prefix instruction.
3898 // NOTE: brk & hlt can be prefixed but require no additional validation.
3899 if (Prefix.isActive() &&
3900 (Inst.getOpcode() != AArch64::BRK) &&
3901 (Inst.getOpcode() != AArch64::HLT)) {
3902
3903 // Prefixed intructions must have a destructive operand.
3904 if ((MCID.TSFlags & AArch64::DestructiveInstTypeMask) ==
3905 AArch64::NotDestructive)
3906 return Error(IDLoc, "instruction is unpredictable when following a"
3907 " movprfx, suggest replacing movprfx with mov");
3908
3909 // Destination operands must match.
3910 if (Inst.getOperand(0).getReg() != Prefix.getDstReg())
3911 return Error(Loc[0], "instruction is unpredictable when following a"
3912 " movprfx writing to a different destination");
3913
3914 // Destination operand must not be used in any other location.
3915 for (unsigned i = 1; i < Inst.getNumOperands(); ++i) {
3916 if (Inst.getOperand(i).isReg() &&
3917 (MCID.getOperandConstraint(i, MCOI::TIED_TO) == -1) &&
3918 isMatchingOrAlias(Prefix.getDstReg(), Inst.getOperand(i).getReg()))
3919 return Error(Loc[0], "instruction is unpredictable when following a"
3920 " movprfx and destination also used as non-destructive"
3921 " source");
3922 }
3923
3924 auto PPRRegClass = AArch64MCRegisterClasses[AArch64::PPRRegClassID];
3925 if (Prefix.isPredicated()) {
3926 int PgIdx = -1;
3927
3928 // Find the instructions general predicate.
3929 for (unsigned i = 1; i < Inst.getNumOperands(); ++i)
3930 if (Inst.getOperand(i).isReg() &&
3931 PPRRegClass.contains(Inst.getOperand(i).getReg())) {
3932 PgIdx = i;
3933 break;
3934 }
3935
3936 // Instruction must be predicated if the movprfx is predicated.
3937 if (PgIdx == -1 ||
3938 (MCID.TSFlags & AArch64::ElementSizeMask) == AArch64::ElementSizeNone)
3939 return Error(IDLoc, "instruction is unpredictable when following a"
3940 " predicated movprfx, suggest using unpredicated movprfx");
3941
3942 // Instruction must use same general predicate as the movprfx.
3943 if (Inst.getOperand(PgIdx).getReg() != Prefix.getPgReg())
3944 return Error(IDLoc, "instruction is unpredictable when following a"
3945 " predicated movprfx using a different general predicate");
3946
3947 // Instruction element type must match the movprfx.
3948 if ((MCID.TSFlags & AArch64::ElementSizeMask) != Prefix.getElementSize())
3949 return Error(IDLoc, "instruction is unpredictable when following a"
3950 " predicated movprfx with a different element size");
3951 }
3952 }
3953
Tim Northover3b0846e2014-05-24 12:50:23 +00003954 // Check for indexed addressing modes w/ the base register being the
3955 // same as a destination/source register or pair load where
3956 // the Rt == Rt2. All of those are undefined behaviour.
3957 switch (Inst.getOpcode()) {
3958 case AArch64::LDPSWpre:
3959 case AArch64::LDPWpost:
3960 case AArch64::LDPWpre:
3961 case AArch64::LDPXpost:
3962 case AArch64::LDPXpre: {
3963 unsigned Rt = Inst.getOperand(1).getReg();
3964 unsigned Rt2 = Inst.getOperand(2).getReg();
3965 unsigned Rn = Inst.getOperand(3).getReg();
3966 if (RI->isSubRegisterEq(Rn, Rt))
3967 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3968 "is also a destination");
3969 if (RI->isSubRegisterEq(Rn, Rt2))
3970 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3971 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003972 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003973 }
3974 case AArch64::LDPDi:
3975 case AArch64::LDPQi:
3976 case AArch64::LDPSi:
3977 case AArch64::LDPSWi:
3978 case AArch64::LDPWi:
3979 case AArch64::LDPXi: {
3980 unsigned Rt = Inst.getOperand(0).getReg();
3981 unsigned Rt2 = Inst.getOperand(1).getReg();
3982 if (Rt == Rt2)
3983 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3984 break;
3985 }
3986 case AArch64::LDPDpost:
3987 case AArch64::LDPDpre:
3988 case AArch64::LDPQpost:
3989 case AArch64::LDPQpre:
3990 case AArch64::LDPSpost:
3991 case AArch64::LDPSpre:
3992 case AArch64::LDPSWpost: {
3993 unsigned Rt = Inst.getOperand(1).getReg();
3994 unsigned Rt2 = Inst.getOperand(2).getReg();
3995 if (Rt == Rt2)
3996 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3997 break;
3998 }
3999 case AArch64::STPDpost:
4000 case AArch64::STPDpre:
4001 case AArch64::STPQpost:
4002 case AArch64::STPQpre:
4003 case AArch64::STPSpost:
4004 case AArch64::STPSpre:
4005 case AArch64::STPWpost:
4006 case AArch64::STPWpre:
4007 case AArch64::STPXpost:
4008 case AArch64::STPXpre: {
4009 unsigned Rt = Inst.getOperand(1).getReg();
4010 unsigned Rt2 = Inst.getOperand(2).getReg();
4011 unsigned Rn = Inst.getOperand(3).getReg();
4012 if (RI->isSubRegisterEq(Rn, Rt))
4013 return Error(Loc[0], "unpredictable STP instruction, writeback base "
4014 "is also a source");
4015 if (RI->isSubRegisterEq(Rn, Rt2))
4016 return Error(Loc[1], "unpredictable STP instruction, writeback base "
4017 "is also a source");
4018 break;
4019 }
4020 case AArch64::LDRBBpre:
4021 case AArch64::LDRBpre:
4022 case AArch64::LDRHHpre:
4023 case AArch64::LDRHpre:
4024 case AArch64::LDRSBWpre:
4025 case AArch64::LDRSBXpre:
4026 case AArch64::LDRSHWpre:
4027 case AArch64::LDRSHXpre:
4028 case AArch64::LDRSWpre:
4029 case AArch64::LDRWpre:
4030 case AArch64::LDRXpre:
4031 case AArch64::LDRBBpost:
4032 case AArch64::LDRBpost:
4033 case AArch64::LDRHHpost:
4034 case AArch64::LDRHpost:
4035 case AArch64::LDRSBWpost:
4036 case AArch64::LDRSBXpost:
4037 case AArch64::LDRSHWpost:
4038 case AArch64::LDRSHXpost:
4039 case AArch64::LDRSWpost:
4040 case AArch64::LDRWpost:
4041 case AArch64::LDRXpost: {
4042 unsigned Rt = Inst.getOperand(1).getReg();
4043 unsigned Rn = Inst.getOperand(2).getReg();
4044 if (RI->isSubRegisterEq(Rn, Rt))
4045 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
4046 "is also a source");
4047 break;
4048 }
4049 case AArch64::STRBBpost:
4050 case AArch64::STRBpost:
4051 case AArch64::STRHHpost:
4052 case AArch64::STRHpost:
4053 case AArch64::STRWpost:
4054 case AArch64::STRXpost:
4055 case AArch64::STRBBpre:
4056 case AArch64::STRBpre:
4057 case AArch64::STRHHpre:
4058 case AArch64::STRHpre:
4059 case AArch64::STRWpre:
4060 case AArch64::STRXpre: {
4061 unsigned Rt = Inst.getOperand(1).getReg();
4062 unsigned Rn = Inst.getOperand(2).getReg();
4063 if (RI->isSubRegisterEq(Rn, Rt))
4064 return Error(Loc[0], "unpredictable STR instruction, writeback base "
4065 "is also a source");
4066 break;
4067 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004068 case AArch64::STXRB:
4069 case AArch64::STXRH:
4070 case AArch64::STXRW:
4071 case AArch64::STXRX:
4072 case AArch64::STLXRB:
4073 case AArch64::STLXRH:
4074 case AArch64::STLXRW:
4075 case AArch64::STLXRX: {
4076 unsigned Rs = Inst.getOperand(0).getReg();
4077 unsigned Rt = Inst.getOperand(1).getReg();
4078 unsigned Rn = Inst.getOperand(2).getReg();
4079 if (RI->isSubRegisterEq(Rt, Rs) ||
4080 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
4081 return Error(Loc[0],
4082 "unpredictable STXR instruction, status is also a source");
4083 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00004084 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004085 case AArch64::STXPW:
4086 case AArch64::STXPX:
4087 case AArch64::STLXPW:
4088 case AArch64::STLXPX: {
4089 unsigned Rs = Inst.getOperand(0).getReg();
4090 unsigned Rt1 = Inst.getOperand(1).getReg();
4091 unsigned Rt2 = Inst.getOperand(2).getReg();
4092 unsigned Rn = Inst.getOperand(3).getReg();
4093 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
4094 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
4095 return Error(Loc[0],
4096 "unpredictable STXP instruction, status is also a source");
4097 break;
4098 }
Oliver Stannardc4190282018-10-02 10:04:39 +00004099 case AArch64::LDGV: {
4100 unsigned Rt = Inst.getOperand(0).getReg();
4101 unsigned Rn = Inst.getOperand(1).getReg();
4102 if (RI->isSubRegisterEq(Rt, Rn)) {
4103 return Error(Loc[0],
4104 "unpredictable LDGV instruction, writeback register is also "
4105 "the target register");
4106 }
4107 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004108 }
4109
Tim Northover3b0846e2014-05-24 12:50:23 +00004110
4111 // Now check immediate ranges. Separate from the above as there is overlap
4112 // in the instructions being checked and this keeps the nested conditionals
4113 // to a minimum.
4114 switch (Inst.getOpcode()) {
4115 case AArch64::ADDSWri:
4116 case AArch64::ADDSXri:
4117 case AArch64::ADDWri:
4118 case AArch64::ADDXri:
4119 case AArch64::SUBSWri:
4120 case AArch64::SUBSXri:
4121 case AArch64::SUBWri:
4122 case AArch64::SUBXri: {
4123 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
4124 // some slight duplication here.
4125 if (Inst.getOperand(2).isExpr()) {
4126 const MCExpr *Expr = Inst.getOperand(2).getExpr();
4127 AArch64MCExpr::VariantKind ELFRefKind;
4128 MCSymbolRefExpr::VariantKind DarwinRefKind;
4129 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00004130 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
4131
4132 // Only allow these with ADDXri.
4133 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
4134 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
4135 Inst.getOpcode() == AArch64::ADDXri)
4136 return false;
4137
4138 // Only allow these with ADDXri/ADDWri
4139 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
4140 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
4141 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
4142 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
4143 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
4144 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
4145 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00004146 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
4147 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
4148 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00004149 (Inst.getOpcode() == AArch64::ADDXri ||
4150 Inst.getOpcode() == AArch64::ADDWri))
4151 return false;
4152
4153 // Don't allow symbol refs in the immediate field otherwise
4154 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
4155 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
4156 // 'cmp w0, 'borked')
4157 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00004158 }
Diana Picusc93518d2016-10-11 09:17:47 +00004159 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00004160 }
4161 return false;
4162 }
4163 default:
4164 return false;
4165 }
4166}
4167
Craig Topper05515562017-10-26 06:46:41 +00004168static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
4169 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004170
4171bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
Sander de Smalen0325e302018-07-02 07:34:52 +00004172 uint64_t ErrorInfo,
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004173 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004174 switch (ErrCode) {
Sander de Smalen0325e302018-07-02 07:34:52 +00004175 case Match_InvalidTiedOperand: {
4176 RegConstraintEqualityTy EqTy =
4177 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
4178 .getRegEqualityTy();
4179 switch (EqTy) {
4180 case RegConstraintEqualityTy::EqualsSubReg:
4181 return Error(Loc, "operand must be 64-bit form of destination register");
4182 case RegConstraintEqualityTy::EqualsSuperReg:
4183 return Error(Loc, "operand must be 32-bit form of destination register");
4184 case RegConstraintEqualityTy::EqualsReg:
4185 return Error(Loc, "operand must match destination register");
4186 }
Simon Pilgrim6dc45e62018-07-05 09:48:01 +00004187 llvm_unreachable("Unknown RegConstraintEqualityTy");
Sander de Smalen0325e302018-07-02 07:34:52 +00004188 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004189 case Match_MissingFeature:
4190 return Error(Loc,
4191 "instruction requires a CPU feature not currently enabled");
4192 case Match_InvalidOperand:
4193 return Error(Loc, "invalid operand for instruction");
4194 case Match_InvalidSuffix:
4195 return Error(Loc, "invalid type suffix for instruction");
4196 case Match_InvalidCondCode:
4197 return Error(Loc, "expected AArch64 condition code");
4198 case Match_AddSubRegExtendSmall:
4199 return Error(Loc,
4200 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
4201 case Match_AddSubRegExtendLarge:
4202 return Error(Loc,
4203 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
4204 case Match_AddSubSecondSource:
4205 return Error(Loc,
4206 "expected compatible register, symbol or integer in range [0, 4095]");
4207 case Match_LogicalSecondSource:
4208 return Error(Loc, "expected compatible register or logical immediate");
4209 case Match_InvalidMovImm32Shift:
4210 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
4211 case Match_InvalidMovImm64Shift:
4212 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
4213 case Match_AddSubRegShift32:
4214 return Error(Loc,
4215 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
4216 case Match_AddSubRegShift64:
4217 return Error(Loc,
4218 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
4219 case Match_InvalidFPImm:
4220 return Error(Loc,
4221 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00004222 case Match_InvalidMemoryIndexedSImm6:
4223 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00004224 case Match_InvalidMemoryIndexedSImm5:
4225 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00004226 case Match_InvalidMemoryIndexed1SImm4:
4227 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00004228 case Match_InvalidMemoryIndexed2SImm4:
4229 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00004230 case Match_InvalidMemoryIndexed3SImm4:
4231 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00004232 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00004233 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004234 case Match_InvalidMemoryIndexed16SImm4:
4235 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00004236 case Match_InvalidMemoryIndexed1SImm6:
4237 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen592718f2018-07-05 07:54:10 +00004238 case Match_InvalidMemoryIndexedSImm8:
4239 return Error(Loc, "index must be an integer in range [-128, 127].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004240 case Match_InvalidMemoryIndexedSImm9:
4241 return Error(Loc, "index must be an integer in range [-256, 255].");
Oliver Stannardc4190282018-10-02 10:04:39 +00004242 case Match_InvalidMemoryIndexed16SImm9:
4243 return Error(Loc, "index must be a multiple of 16 in range [-4096, 4080].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004244 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00004245 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004246 case Match_InvalidMemoryIndexed4SImm7:
4247 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
4248 case Match_InvalidMemoryIndexed8SImm7:
4249 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
4250 case Match_InvalidMemoryIndexed16SImm7:
4251 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00004252 case Match_InvalidMemoryIndexed8UImm5:
4253 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
4254 case Match_InvalidMemoryIndexed4UImm5:
4255 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
4256 case Match_InvalidMemoryIndexed2UImm5:
4257 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00004258 case Match_InvalidMemoryIndexed8UImm6:
4259 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
Oliver Stannardc4190282018-10-02 10:04:39 +00004260 case Match_InvalidMemoryIndexed16UImm6:
4261 return Error(Loc, "index must be a multiple of 16 in range [0, 1008].");
Sander de Smalend8e76492018-05-08 10:46:55 +00004262 case Match_InvalidMemoryIndexed4UImm6:
4263 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
4264 case Match_InvalidMemoryIndexed2UImm6:
4265 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
4266 case Match_InvalidMemoryIndexed1UImm6:
4267 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004268 case Match_InvalidMemoryWExtend8:
4269 return Error(Loc,
4270 "expected 'uxtw' or 'sxtw' with optional shift of #0");
4271 case Match_InvalidMemoryWExtend16:
4272 return Error(Loc,
4273 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
4274 case Match_InvalidMemoryWExtend32:
4275 return Error(Loc,
4276 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
4277 case Match_InvalidMemoryWExtend64:
4278 return Error(Loc,
4279 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
4280 case Match_InvalidMemoryWExtend128:
4281 return Error(Loc,
4282 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
4283 case Match_InvalidMemoryXExtend8:
4284 return Error(Loc,
4285 "expected 'lsl' or 'sxtx' with optional shift of #0");
4286 case Match_InvalidMemoryXExtend16:
4287 return Error(Loc,
4288 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
4289 case Match_InvalidMemoryXExtend32:
4290 return Error(Loc,
4291 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
4292 case Match_InvalidMemoryXExtend64:
4293 return Error(Loc,
4294 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
4295 case Match_InvalidMemoryXExtend128:
4296 return Error(Loc,
4297 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
4298 case Match_InvalidMemoryIndexed1:
4299 return Error(Loc, "index must be an integer in range [0, 4095].");
4300 case Match_InvalidMemoryIndexed2:
4301 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
4302 case Match_InvalidMemoryIndexed4:
4303 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
4304 case Match_InvalidMemoryIndexed8:
4305 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
4306 case Match_InvalidMemoryIndexed16:
4307 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004308 case Match_InvalidImm0_1:
4309 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004310 case Match_InvalidImm0_7:
4311 return Error(Loc, "immediate must be an integer in range [0, 7].");
4312 case Match_InvalidImm0_15:
4313 return Error(Loc, "immediate must be an integer in range [0, 15].");
4314 case Match_InvalidImm0_31:
4315 return Error(Loc, "immediate must be an integer in range [0, 31].");
4316 case Match_InvalidImm0_63:
4317 return Error(Loc, "immediate must be an integer in range [0, 63].");
4318 case Match_InvalidImm0_127:
4319 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004320 case Match_InvalidImm0_255:
4321 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004322 case Match_InvalidImm0_65535:
4323 return Error(Loc, "immediate must be an integer in range [0, 65535].");
4324 case Match_InvalidImm1_8:
4325 return Error(Loc, "immediate must be an integer in range [1, 8].");
4326 case Match_InvalidImm1_16:
4327 return Error(Loc, "immediate must be an integer in range [1, 16].");
4328 case Match_InvalidImm1_32:
4329 return Error(Loc, "immediate must be an integer in range [1, 32].");
4330 case Match_InvalidImm1_64:
4331 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00004332 case Match_InvalidSVEAddSubImm8:
4333 return Error(Loc, "immediate must be an integer in range [0, 255]"
4334 " with a shift amount of 0");
4335 case Match_InvalidSVEAddSubImm16:
4336 case Match_InvalidSVEAddSubImm32:
4337 case Match_InvalidSVEAddSubImm64:
4338 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
4339 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004340 case Match_InvalidSVECpyImm8:
4341 return Error(Loc, "immediate must be an integer in range [-128, 255]"
4342 " with a shift amount of 0");
4343 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00004344 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4345 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004346 case Match_InvalidSVECpyImm32:
4347 case Match_InvalidSVECpyImm64:
4348 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4349 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004350 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004351 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004352 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00004353 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004354 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00004355 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004356 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004357 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004358 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004359 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004360 case Match_InvalidSVEIndexRange0_63:
4361 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4362 case Match_InvalidSVEIndexRange0_31:
4363 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4364 case Match_InvalidSVEIndexRange0_15:
4365 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4366 case Match_InvalidSVEIndexRange0_7:
4367 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4368 case Match_InvalidSVEIndexRange0_3:
4369 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004370 case Match_InvalidLabel:
4371 return Error(Loc, "expected label or encodable integer pc offset");
4372 case Match_MRS:
4373 return Error(Loc, "expected readable system register");
4374 case Match_MSR:
4375 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00004376 case Match_InvalidComplexRotationEven:
4377 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4378 case Match_InvalidComplexRotationOdd:
4379 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004380 case Match_MnemonicFail: {
4381 std::string Suggestion = AArch64MnemonicSpellCheck(
4382 ((AArch64Operand &)*Operands[0]).getToken(),
4383 ComputeAvailableFeatures(STI->getFeatureBits()));
4384 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4385 }
Sander de Smalen367694b2018-04-20 08:54:49 +00004386 case Match_InvalidGPR64shifted8:
4387 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4388 case Match_InvalidGPR64shifted16:
4389 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4390 case Match_InvalidGPR64shifted32:
4391 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4392 case Match_InvalidGPR64shifted64:
4393 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4394 case Match_InvalidGPR64NoXZRshifted8:
4395 return Error(Loc, "register must be x0..x30 without shift");
4396 case Match_InvalidGPR64NoXZRshifted16:
4397 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4398 case Match_InvalidGPR64NoXZRshifted32:
4399 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4400 case Match_InvalidGPR64NoXZRshifted64:
4401 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004402 case Match_InvalidZPR32UXTW8:
4403 case Match_InvalidZPR32SXTW8:
4404 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4405 case Match_InvalidZPR32UXTW16:
4406 case Match_InvalidZPR32SXTW16:
4407 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4408 case Match_InvalidZPR32UXTW32:
4409 case Match_InvalidZPR32SXTW32:
4410 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4411 case Match_InvalidZPR32UXTW64:
4412 case Match_InvalidZPR32SXTW64:
4413 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4414 case Match_InvalidZPR64UXTW8:
4415 case Match_InvalidZPR64SXTW8:
4416 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4417 case Match_InvalidZPR64UXTW16:
4418 case Match_InvalidZPR64SXTW16:
4419 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4420 case Match_InvalidZPR64UXTW32:
4421 case Match_InvalidZPR64SXTW32:
4422 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4423 case Match_InvalidZPR64UXTW64:
4424 case Match_InvalidZPR64SXTW64:
4425 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
Sander de Smalenc69944c2018-07-09 09:58:24 +00004426 case Match_InvalidZPR32LSL8:
4427 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s'");
4428 case Match_InvalidZPR32LSL16:
4429 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #1'");
4430 case Match_InvalidZPR32LSL32:
4431 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #2'");
4432 case Match_InvalidZPR32LSL64:
4433 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004434 case Match_InvalidZPR64LSL8:
4435 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4436 case Match_InvalidZPR64LSL16:
4437 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4438 case Match_InvalidZPR64LSL32:
4439 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4440 case Match_InvalidZPR64LSL64:
4441 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00004442 case Match_InvalidZPR0:
4443 return Error(Loc, "expected register without element width sufix");
4444 case Match_InvalidZPR8:
4445 case Match_InvalidZPR16:
4446 case Match_InvalidZPR32:
4447 case Match_InvalidZPR64:
4448 case Match_InvalidZPR128:
4449 return Error(Loc, "invalid element width");
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004450 case Match_InvalidZPR_3b8:
4451 return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b");
4452 case Match_InvalidZPR_3b16:
4453 return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h");
4454 case Match_InvalidZPR_3b32:
4455 return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s");
4456 case Match_InvalidZPR_4b16:
4457 return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h");
4458 case Match_InvalidZPR_4b32:
4459 return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s");
4460 case Match_InvalidZPR_4b64:
4461 return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004462 case Match_InvalidSVEPattern:
4463 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004464 case Match_InvalidSVEPredicateAnyReg:
4465 case Match_InvalidSVEPredicateBReg:
4466 case Match_InvalidSVEPredicateHReg:
4467 case Match_InvalidSVEPredicateSReg:
4468 case Match_InvalidSVEPredicateDReg:
4469 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004470 case Match_InvalidSVEPredicate3bAnyReg:
4471 case Match_InvalidSVEPredicate3bBReg:
4472 case Match_InvalidSVEPredicate3bHReg:
4473 case Match_InvalidSVEPredicate3bSReg:
4474 case Match_InvalidSVEPredicate3bDReg:
4475 return Error(Loc, "restricted predicate has range [0, 7].");
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004476 case Match_InvalidSVEExactFPImmOperandHalfOne:
4477 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4478 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4479 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4480 case Match_InvalidSVEExactFPImmOperandZeroOne:
4481 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004482 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004483 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004484 }
4485}
4486
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004487static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004488
4489bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4490 OperandVector &Operands,
4491 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004492 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004493 bool MatchingInlineAsm) {
4494 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004495 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4496 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004497
David Blaikie960ea3f2014-06-08 16:18:35 +00004498 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004499 unsigned NumOperands = Operands.size();
4500
4501 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004502 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4503 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004504 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004505 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004506 if (Op3CE) {
4507 uint64_t Op3Val = Op3CE->getValue();
4508 uint64_t NewOp3Val = 0;
4509 uint64_t NewOp4Val = 0;
4510 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004511 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004512 NewOp3Val = (32 - Op3Val) & 0x1f;
4513 NewOp4Val = 31 - Op3Val;
4514 } else {
4515 NewOp3Val = (64 - Op3Val) & 0x3f;
4516 NewOp4Val = 63 - Op3Val;
4517 }
4518
Jim Grosbach13760bd2015-05-30 01:25:56 +00004519 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4520 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004521
4522 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004523 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004524 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004525 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4526 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4527 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004528 }
4529 }
Tim Northover03b99f62015-04-30 18:28:58 +00004530 } else if (NumOperands == 4 && Tok == "bfc") {
4531 // FIXME: Horrible hack to handle BFC->BFM alias.
4532 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4533 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4534 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4535
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004536 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004537 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4538 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4539
4540 if (LSBCE && WidthCE) {
4541 uint64_t LSB = LSBCE->getValue();
4542 uint64_t Width = WidthCE->getValue();
4543
4544 uint64_t RegWidth = 0;
4545 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4546 Op1.getReg()))
4547 RegWidth = 64;
4548 else
4549 RegWidth = 32;
4550
4551 if (LSB >= RegWidth)
4552 return Error(LSBOp.getStartLoc(),
4553 "expected integer in range [0, 31]");
4554 if (Width < 1 || Width > RegWidth)
4555 return Error(WidthOp.getStartLoc(),
4556 "expected integer in range [1, 32]");
4557
4558 uint64_t ImmR = 0;
4559 if (RegWidth == 32)
4560 ImmR = (32 - LSB) & 0x1f;
4561 else
4562 ImmR = (64 - LSB) & 0x3f;
4563
4564 uint64_t ImmS = Width - 1;
4565
4566 if (ImmR != 0 && ImmS >= ImmR)
4567 return Error(WidthOp.getStartLoc(),
4568 "requested insert overflows register");
4569
Jim Grosbach13760bd2015-05-30 01:25:56 +00004570 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4571 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004572 Operands[0] = AArch64Operand::CreateToken(
4573 "bfm", false, Op.getStartLoc(), getContext());
4574 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004575 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4576 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004577 Operands[3] = AArch64Operand::CreateImm(
4578 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4579 Operands.emplace_back(
4580 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4581 WidthOp.getEndLoc(), getContext()));
4582 }
4583 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004584 } else if (NumOperands == 5) {
4585 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4586 // UBFIZ -> UBFM aliases.
4587 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004588 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4589 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4590 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004591
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004592 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004593 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4594 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004595
4596 if (Op3CE && Op4CE) {
4597 uint64_t Op3Val = Op3CE->getValue();
4598 uint64_t Op4Val = Op4CE->getValue();
4599
4600 uint64_t RegWidth = 0;
4601 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004602 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004603 RegWidth = 64;
4604 else
4605 RegWidth = 32;
4606
4607 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004608 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004609 "expected integer in range [0, 31]");
4610 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004611 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004612 "expected integer in range [1, 32]");
4613
4614 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004615 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004616 NewOp3Val = (32 - Op3Val) & 0x1f;
4617 else
4618 NewOp3Val = (64 - Op3Val) & 0x3f;
4619
4620 uint64_t NewOp4Val = Op4Val - 1;
4621
4622 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004623 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004624 "requested insert overflows register");
4625
4626 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004627 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004628 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004629 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004630 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004631 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004632 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004633 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004634 if (Tok == "bfi")
4635 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004636 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004637 else if (Tok == "sbfiz")
4638 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004639 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004640 else if (Tok == "ubfiz")
4641 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004642 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004643 else
4644 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004645 }
4646 }
4647
4648 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4649 // UBFX -> UBFM aliases.
4650 } else if (NumOperands == 5 &&
4651 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004652 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4653 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4654 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004655
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004656 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004657 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4658 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004659
4660 if (Op3CE && Op4CE) {
4661 uint64_t Op3Val = Op3CE->getValue();
4662 uint64_t Op4Val = Op4CE->getValue();
4663
4664 uint64_t RegWidth = 0;
4665 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004666 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004667 RegWidth = 64;
4668 else
4669 RegWidth = 32;
4670
4671 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004672 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004673 "expected integer in range [0, 31]");
4674 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004675 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004676 "expected integer in range [1, 32]");
4677
4678 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4679
4680 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004681 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004682 "requested extract overflows register");
4683
4684 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004685 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004686 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004687 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004688 if (Tok == "bfxil")
4689 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004690 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004691 else if (Tok == "sbfx")
4692 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004693 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004694 else if (Tok == "ubfx")
4695 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004696 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004697 else
4698 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004699 }
4700 }
4701 }
4702 }
Tim Northover9097a072017-12-18 10:36:00 +00004703
4704 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4705 // instruction for FP registers correctly in some rare circumstances. Convert
4706 // it to a safe instruction and warn (because silently changing someone's
4707 // assembly is rude).
4708 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4709 NumOperands == 4 && Tok == "movi") {
4710 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4711 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4712 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4713 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4714 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4715 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4716 if (Suffix.lower() == ".2d" &&
4717 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4718 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4719 " correctly on this CPU, converting to equivalent movi.16b");
4720 // Switch the suffix to .16b.
4721 unsigned Idx = Op1.isToken() ? 1 : 2;
4722 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4723 getContext());
4724 }
4725 }
4726 }
4727
Tim Northover3b0846e2014-05-24 12:50:23 +00004728 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4729 // InstAlias can't quite handle this since the reg classes aren't
4730 // subclasses.
4731 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4732 // The source register can be Wn here, but the matcher expects a
4733 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004734 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004735 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004736 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004737 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4738 Op.getStartLoc(), Op.getEndLoc(),
4739 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004740 }
4741 }
4742 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4743 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004744 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004745 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004746 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004747 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004748 // The source register can be Wn here, but the matcher expects a
4749 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004750 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004751 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004752 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004753 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4754 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004755 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004756 }
4757 }
4758 }
4759 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4760 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004761 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004762 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004763 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004764 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004765 // The source register can be Wn here, but the matcher expects a
4766 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004767 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004768 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004769 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004770 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4771 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004772 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004773 }
4774 }
4775 }
4776
Tim Northover3b0846e2014-05-24 12:50:23 +00004777 MCInst Inst;
4778 // First try to match against the secondary set of tables containing the
4779 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4780 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004781 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004782
4783 // If that fails, try against the alternate table containing long-form NEON:
4784 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004785 if (MatchResult != Match_Success) {
4786 // But first, save the short-form match result: we can use it in case the
4787 // long-form match also fails.
4788 auto ShortFormNEONErrorInfo = ErrorInfo;
4789 auto ShortFormNEONMatchResult = MatchResult;
4790
Tim Northover3b0846e2014-05-24 12:50:23 +00004791 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004792 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004793
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004794 // Now, both matches failed, and the long-form match failed on the mnemonic
4795 // suffix token operand. The short-form match failure is probably more
4796 // relevant: use it instead.
4797 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004798 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004799 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4800 MatchResult = ShortFormNEONMatchResult;
4801 ErrorInfo = ShortFormNEONErrorInfo;
4802 }
4803 }
4804
Tim Northover3b0846e2014-05-24 12:50:23 +00004805 switch (MatchResult) {
4806 case Match_Success: {
4807 // Perform range checking and other semantic validations
4808 SmallVector<SMLoc, 8> OperandLocs;
4809 NumOperands = Operands.size();
4810 for (unsigned i = 1; i < NumOperands; ++i)
4811 OperandLocs.push_back(Operands[i]->getStartLoc());
Sander de Smalen9b333092018-07-30 15:42:46 +00004812 if (validateInstruction(Inst, IDLoc, OperandLocs))
Tim Northover3b0846e2014-05-24 12:50:23 +00004813 return true;
4814
4815 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004816 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004817 return false;
4818 }
4819 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004820 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004821 // Special case the error message for the very common case where only
4822 // a single subtarget feature is missing (neon, e.g.).
4823 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004824 uint64_t Mask = 1;
4825 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4826 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004827 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004828 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004829 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004830 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004831 }
4832 return Error(IDLoc, Msg);
4833 }
4834 case Match_MnemonicFail:
Sander de Smalen0325e302018-07-02 07:34:52 +00004835 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004836 case Match_InvalidOperand: {
4837 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004838
Tim Northover26bb14e2014-08-18 11:49:42 +00004839 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004840 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004841 return Error(IDLoc, "too few operands for instruction",
4842 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004843
David Blaikie960ea3f2014-06-08 16:18:35 +00004844 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004845 if (ErrorLoc == SMLoc())
4846 ErrorLoc = IDLoc;
4847 }
4848 // If the match failed on a suffix token operand, tweak the diagnostic
4849 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004850 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4851 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004852 MatchResult = Match_InvalidSuffix;
4853
Sander de Smalen0325e302018-07-02 07:34:52 +00004854 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004855 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004856 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004857 case Match_InvalidMemoryIndexed1:
4858 case Match_InvalidMemoryIndexed2:
4859 case Match_InvalidMemoryIndexed4:
4860 case Match_InvalidMemoryIndexed8:
4861 case Match_InvalidMemoryIndexed16:
4862 case Match_InvalidCondCode:
4863 case Match_AddSubRegExtendSmall:
4864 case Match_AddSubRegExtendLarge:
4865 case Match_AddSubSecondSource:
4866 case Match_LogicalSecondSource:
4867 case Match_AddSubRegShift32:
4868 case Match_AddSubRegShift64:
4869 case Match_InvalidMovImm32Shift:
4870 case Match_InvalidMovImm64Shift:
4871 case Match_InvalidFPImm:
4872 case Match_InvalidMemoryWExtend8:
4873 case Match_InvalidMemoryWExtend16:
4874 case Match_InvalidMemoryWExtend32:
4875 case Match_InvalidMemoryWExtend64:
4876 case Match_InvalidMemoryWExtend128:
4877 case Match_InvalidMemoryXExtend8:
4878 case Match_InvalidMemoryXExtend16:
4879 case Match_InvalidMemoryXExtend32:
4880 case Match_InvalidMemoryXExtend64:
4881 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004882 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004883 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004884 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004885 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004886 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004887 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004888 case Match_InvalidMemoryIndexed4SImm7:
4889 case Match_InvalidMemoryIndexed8SImm7:
4890 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004891 case Match_InvalidMemoryIndexed8UImm5:
4892 case Match_InvalidMemoryIndexed4UImm5:
4893 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004894 case Match_InvalidMemoryIndexed1UImm6:
4895 case Match_InvalidMemoryIndexed2UImm6:
4896 case Match_InvalidMemoryIndexed4UImm6:
4897 case Match_InvalidMemoryIndexed8UImm6:
Oliver Stannardc4190282018-10-02 10:04:39 +00004898 case Match_InvalidMemoryIndexed16UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004899 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004900 case Match_InvalidMemoryIndexedSImm5:
Sander de Smalen592718f2018-07-05 07:54:10 +00004901 case Match_InvalidMemoryIndexedSImm8:
Tim Northover3b0846e2014-05-24 12:50:23 +00004902 case Match_InvalidMemoryIndexedSImm9:
Oliver Stannardc4190282018-10-02 10:04:39 +00004903 case Match_InvalidMemoryIndexed16SImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004904 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004905 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004906 case Match_InvalidImm0_7:
4907 case Match_InvalidImm0_15:
4908 case Match_InvalidImm0_31:
4909 case Match_InvalidImm0_63:
4910 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004911 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004912 case Match_InvalidImm0_65535:
4913 case Match_InvalidImm1_8:
4914 case Match_InvalidImm1_16:
4915 case Match_InvalidImm1_32:
4916 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004917 case Match_InvalidSVEAddSubImm8:
4918 case Match_InvalidSVEAddSubImm16:
4919 case Match_InvalidSVEAddSubImm32:
4920 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004921 case Match_InvalidSVECpyImm8:
4922 case Match_InvalidSVECpyImm16:
4923 case Match_InvalidSVECpyImm32:
4924 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004925 case Match_InvalidIndexRange1_1:
4926 case Match_InvalidIndexRange0_15:
4927 case Match_InvalidIndexRange0_7:
4928 case Match_InvalidIndexRange0_3:
4929 case Match_InvalidIndexRange0_1:
4930 case Match_InvalidSVEIndexRange0_63:
4931 case Match_InvalidSVEIndexRange0_31:
4932 case Match_InvalidSVEIndexRange0_15:
4933 case Match_InvalidSVEIndexRange0_7:
4934 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004935 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004936 case Match_InvalidComplexRotationEven:
4937 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004938 case Match_InvalidGPR64shifted8:
4939 case Match_InvalidGPR64shifted16:
4940 case Match_InvalidGPR64shifted32:
4941 case Match_InvalidGPR64shifted64:
4942 case Match_InvalidGPR64NoXZRshifted8:
4943 case Match_InvalidGPR64NoXZRshifted16:
4944 case Match_InvalidGPR64NoXZRshifted32:
4945 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004946 case Match_InvalidZPR32UXTW8:
4947 case Match_InvalidZPR32UXTW16:
4948 case Match_InvalidZPR32UXTW32:
4949 case Match_InvalidZPR32UXTW64:
4950 case Match_InvalidZPR32SXTW8:
4951 case Match_InvalidZPR32SXTW16:
4952 case Match_InvalidZPR32SXTW32:
4953 case Match_InvalidZPR32SXTW64:
4954 case Match_InvalidZPR64UXTW8:
4955 case Match_InvalidZPR64SXTW8:
4956 case Match_InvalidZPR64UXTW16:
4957 case Match_InvalidZPR64SXTW16:
4958 case Match_InvalidZPR64UXTW32:
4959 case Match_InvalidZPR64SXTW32:
4960 case Match_InvalidZPR64UXTW64:
4961 case Match_InvalidZPR64SXTW64:
Sander de Smalenc69944c2018-07-09 09:58:24 +00004962 case Match_InvalidZPR32LSL8:
4963 case Match_InvalidZPR32LSL16:
4964 case Match_InvalidZPR32LSL32:
4965 case Match_InvalidZPR32LSL64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004966 case Match_InvalidZPR64LSL8:
4967 case Match_InvalidZPR64LSL16:
4968 case Match_InvalidZPR64LSL32:
4969 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004970 case Match_InvalidZPR0:
4971 case Match_InvalidZPR8:
4972 case Match_InvalidZPR16:
4973 case Match_InvalidZPR32:
4974 case Match_InvalidZPR64:
4975 case Match_InvalidZPR128:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004976 case Match_InvalidZPR_3b8:
4977 case Match_InvalidZPR_3b16:
4978 case Match_InvalidZPR_3b32:
4979 case Match_InvalidZPR_4b16:
4980 case Match_InvalidZPR_4b32:
4981 case Match_InvalidZPR_4b64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004982 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004983 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004984 case Match_InvalidSVEPredicateBReg:
4985 case Match_InvalidSVEPredicateHReg:
4986 case Match_InvalidSVEPredicateSReg:
4987 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004988 case Match_InvalidSVEPredicate3bAnyReg:
4989 case Match_InvalidSVEPredicate3bBReg:
4990 case Match_InvalidSVEPredicate3bHReg:
4991 case Match_InvalidSVEPredicate3bSReg:
4992 case Match_InvalidSVEPredicate3bDReg:
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004993 case Match_InvalidSVEExactFPImmOperandHalfOne:
4994 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4995 case Match_InvalidSVEExactFPImmOperandZeroOne:
Tim Northover3b0846e2014-05-24 12:50:23 +00004996 case Match_MSR:
4997 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004998 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004999 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00005000 // Any time we get here, there's nothing fancy to do. Just get the
5001 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00005002 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00005003 if (ErrorLoc == SMLoc())
5004 ErrorLoc = IDLoc;
Sander de Smalen0325e302018-07-02 07:34:52 +00005005 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00005006 }
5007 }
5008
5009 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00005010}
5011
5012/// ParseDirective parses the arm specific directives
5013bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00005014 const MCObjectFileInfo::Environment Format =
5015 getContext().getObjectFileInfo()->getObjectFileType();
5016 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005017
Tim Northover3b0846e2014-05-24 12:50:23 +00005018 StringRef IDVal = DirectiveID.getIdentifier();
5019 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005020 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00005021 parseDirectiveArch(Loc);
5022 else if (IDVal == ".cpu")
5023 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00005024 else if (IDVal == ".tlsdesccall")
5025 parseDirectiveTLSDescCall(Loc);
5026 else if (IDVal == ".ltorg" || IDVal == ".pool")
5027 parseDirectiveLtorg(Loc);
5028 else if (IDVal == ".unreq")
5029 parseDirectiveUnreq(Loc);
Martin Storsjo3e3d39d2018-07-31 09:26:52 +00005030 else if (IDVal == ".inst")
5031 parseDirectiveInst(Loc);
Luke Cheesemanf57d7d82018-12-18 10:37:42 +00005032 else if (IDVal == ".cfi_negate_ra_state")
5033 parseDirectiveCFINegateRAState();
Luke Cheeseman41a9e532018-12-21 10:45:08 +00005034 else if (IDVal == ".cfi_b_key_frame")
5035 parseDirectiveCFIBKeyFrame();
Martin Storsjod4590c32018-08-01 06:50:18 +00005036 else if (IsMachO) {
5037 if (IDVal == MCLOHDirectiveName())
5038 parseDirectiveLOH(IDVal, Loc);
5039 else
5040 return true;
5041 } else
Nirav Davee833c6c2016-11-08 18:31:04 +00005042 return true;
5043 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00005044}
5045
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005046static void ExpandCryptoAEK(AArch64::ArchKind ArchKind,
5047 SmallVector<StringRef, 4> &RequestedExtensions) {
5048 const bool NoCrypto =
5049 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
5050 "nocrypto") != std::end(RequestedExtensions));
5051 const bool Crypto =
5052 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
5053 "crypto") != std::end(RequestedExtensions));
5054
5055 if (!NoCrypto && Crypto) {
5056 switch (ArchKind) {
5057 default:
5058 // Map 'generic' (and others) to sha2 and aes, because
5059 // that was the traditional meaning of crypto.
5060 case AArch64::ArchKind::ARMV8_1A:
5061 case AArch64::ArchKind::ARMV8_2A:
5062 case AArch64::ArchKind::ARMV8_3A:
5063 RequestedExtensions.push_back("sha2");
5064 RequestedExtensions.push_back("aes");
5065 break;
5066 case AArch64::ArchKind::ARMV8_4A:
Oliver Stannard7c3c4ba2018-09-26 12:48:21 +00005067 case AArch64::ArchKind::ARMV8_5A:
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005068 RequestedExtensions.push_back("sm4");
5069 RequestedExtensions.push_back("sha3");
5070 RequestedExtensions.push_back("sha2");
5071 RequestedExtensions.push_back("aes");
5072 break;
5073 }
5074 } else if (NoCrypto) {
5075 switch (ArchKind) {
5076 default:
5077 // Map 'generic' (and others) to sha2 and aes, because
5078 // that was the traditional meaning of crypto.
5079 case AArch64::ArchKind::ARMV8_1A:
5080 case AArch64::ArchKind::ARMV8_2A:
5081 case AArch64::ArchKind::ARMV8_3A:
5082 RequestedExtensions.push_back("nosha2");
5083 RequestedExtensions.push_back("noaes");
5084 break;
5085 case AArch64::ArchKind::ARMV8_4A:
Oliver Stannard7c3c4ba2018-09-26 12:48:21 +00005086 case AArch64::ArchKind::ARMV8_5A:
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005087 RequestedExtensions.push_back("nosm4");
5088 RequestedExtensions.push_back("nosha3");
5089 RequestedExtensions.push_back("nosha2");
5090 RequestedExtensions.push_back("noaes");
5091 break;
5092 }
5093 }
5094}
5095
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005096/// parseDirectiveArch
5097/// ::= .arch token
5098bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
5099 SMLoc ArchLoc = getLoc();
5100
5101 StringRef Arch, ExtensionString;
5102 std::tie(Arch, ExtensionString) =
5103 getParser().parseStringToEndOfStatement().trim().split('+');
5104
Florian Hahn67ddd1d2017-07-27 16:27:56 +00005105 AArch64::ArchKind ID = AArch64::parseArch(Arch);
5106 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00005107 return Error(ArchLoc, "unknown arch name");
5108
5109 if (parseToken(AsmToken::EndOfStatement))
5110 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005111
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005112 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00005113 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005114 AArch64::getArchFeatures(ID, AArch64Features);
5115 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
5116 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005117
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005118 MCSubtargetInfo &STI = copySTI();
5119 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
5120 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
5121
5122 SmallVector<StringRef, 4> RequestedExtensions;
5123 if (!ExtensionString.empty())
5124 ExtensionString.split(RequestedExtensions, '+');
5125
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005126 ExpandCryptoAEK(ID, RequestedExtensions);
5127
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005128 FeatureBitset Features = STI.getFeatureBits();
5129 for (auto Name : RequestedExtensions) {
5130 bool EnableFeature = true;
5131
5132 if (Name.startswith_lower("no")) {
5133 EnableFeature = false;
5134 Name = Name.substr(2);
5135 }
5136
5137 for (const auto &Extension : ExtensionMap) {
5138 if (Extension.Name != Name)
5139 continue;
5140
5141 if (Extension.Features.none())
5142 report_fatal_error("unsupported architectural extension: " + Name);
5143
5144 FeatureBitset ToggleFeatures = EnableFeature
5145 ? (~Features & Extension.Features)
5146 : ( Features & Extension.Features);
5147 uint64_t Features =
5148 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5149 setAvailableFeatures(Features);
5150 break;
5151 }
5152 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005153 return false;
5154}
5155
Tim Northover8b96c7e2017-05-15 19:42:15 +00005156static SMLoc incrementLoc(SMLoc L, int Offset) {
5157 return SMLoc::getFromPointer(L.getPointer() + Offset);
5158}
5159
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005160/// parseDirectiveCPU
5161/// ::= .cpu id
5162bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005163 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005164
5165 StringRef CPU, ExtensionString;
5166 std::tie(CPU, ExtensionString) =
5167 getParser().parseStringToEndOfStatement().trim().split('+');
5168
Nirav Davee833c6c2016-11-08 18:31:04 +00005169 if (parseToken(AsmToken::EndOfStatement))
5170 return true;
5171
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005172 SmallVector<StringRef, 4> RequestedExtensions;
5173 if (!ExtensionString.empty())
5174 ExtensionString.split(RequestedExtensions, '+');
5175
5176 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
5177 // once that is tablegen'ed
5178 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005179 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005180 return false;
5181 }
5182
5183 MCSubtargetInfo &STI = copySTI();
5184 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00005185 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005186
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005187 ExpandCryptoAEK(llvm::AArch64::getCPUArchKind(CPU), RequestedExtensions);
5188
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005189 FeatureBitset Features = STI.getFeatureBits();
5190 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005191 // Advance source location past '+'.
5192 CurLoc = incrementLoc(CurLoc, 1);
5193
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005194 bool EnableFeature = true;
5195
5196 if (Name.startswith_lower("no")) {
5197 EnableFeature = false;
5198 Name = Name.substr(2);
5199 }
5200
Tim Northover8b96c7e2017-05-15 19:42:15 +00005201 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005202 for (const auto &Extension : ExtensionMap) {
5203 if (Extension.Name != Name)
5204 continue;
5205
5206 if (Extension.Features.none())
5207 report_fatal_error("unsupported architectural extension: " + Name);
5208
5209 FeatureBitset ToggleFeatures = EnableFeature
5210 ? (~Features & Extension.Features)
5211 : ( Features & Extension.Features);
5212 uint64_t Features =
5213 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5214 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00005215 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005216
5217 break;
5218 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00005219
5220 if (!FoundExtension)
5221 Error(CurLoc, "unsupported architectural extension");
5222
5223 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005224 }
5225 return false;
5226}
5227
Chad Rosierdcd2a302014-10-22 20:35:57 +00005228/// parseDirectiveInst
5229/// ::= .inst opcode [, ...]
5230bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005231 if (getLexer().is(AsmToken::EndOfStatement))
5232 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005233
Nirav Davee833c6c2016-11-08 18:31:04 +00005234 auto parseOp = [&]() -> bool {
5235 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00005236 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00005237 if (check(getParser().parseExpression(Expr), L, "expected expression"))
5238 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005239 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00005240 if (check(!Value, L, "expected constant expression"))
5241 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005242 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00005243 return false;
5244 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00005245
Nirav Davee833c6c2016-11-08 18:31:04 +00005246 if (parseMany(parseOp))
5247 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005248 return false;
5249}
5250
Tim Northover3b0846e2014-05-24 12:50:23 +00005251// parseDirectiveTLSDescCall:
5252// ::= .tlsdesccall symbol
5253bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
5254 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00005255 if (check(getParser().parseIdentifier(Name), L,
5256 "expected symbol after directive") ||
5257 parseToken(AsmToken::EndOfStatement))
5258 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005259
Jim Grosbach6f482002015-05-18 18:43:14 +00005260 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00005261 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
5262 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00005263
5264 MCInst Inst;
5265 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00005266 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00005267
Akira Hatanakabd9fc282015-11-14 05:20:05 +00005268 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00005269 return false;
5270}
5271
5272/// ::= .loh <lohName | lohId> label1, ..., labelN
5273/// The number of arguments depends on the loh identifier.
5274bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00005275 MCLOHType Kind;
5276 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5277 if (getParser().getTok().isNot(AsmToken::Integer))
5278 return TokError("expected an identifier or a number in directive");
5279 // We successfully get a numeric value for the identifier.
5280 // Check if it is valid.
5281 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00005282 if (Id <= -1U && !isValidMCLOHType(Id))
5283 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00005284 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00005285 } else {
5286 StringRef Name = getTok().getIdentifier();
5287 // We successfully parse an identifier.
5288 // Check if it is a recognized one.
5289 int Id = MCLOHNameToId(Name);
5290
5291 if (Id == -1)
5292 return TokError("invalid identifier in directive");
5293 Kind = (MCLOHType)Id;
5294 }
5295 // Consume the identifier.
5296 Lex();
5297 // Get the number of arguments of this LOH.
5298 int NbArgs = MCLOHIdToNbArgs(Kind);
5299
5300 assert(NbArgs != -1 && "Invalid number of arguments");
5301
5302 SmallVector<MCSymbol *, 3> Args;
5303 for (int Idx = 0; Idx < NbArgs; ++Idx) {
5304 StringRef Name;
5305 if (getParser().parseIdentifier(Name))
5306 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00005307 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00005308
5309 if (Idx + 1 == NbArgs)
5310 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00005311 if (parseToken(AsmToken::Comma,
5312 "unexpected token in '" + Twine(IDVal) + "' directive"))
5313 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005314 }
Nirav Davee833c6c2016-11-08 18:31:04 +00005315 if (parseToken(AsmToken::EndOfStatement,
5316 "unexpected token in '" + Twine(IDVal) + "' directive"))
5317 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005318
5319 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
5320 return false;
5321}
5322
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005323/// parseDirectiveLtorg
5324/// ::= .ltorg | .pool
5325bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005326 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5327 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005328 getTargetStreamer().emitCurrentConstantPool();
5329 return false;
5330}
5331
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005332/// parseDirectiveReq
5333/// ::= name .req registername
5334bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005335 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005336 Parser.Lex(); // Eat the '.req' token.
5337 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00005338 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00005339 unsigned RegNum;
5340 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005341
Sander de Smalen50d87022018-04-19 07:35:08 +00005342 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005343 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00005344 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005345 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00005346
Sander de Smalen50d87022018-04-19 07:35:08 +00005347 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00005348 return true;
5349
Sander de Smalen50d87022018-04-19 07:35:08 +00005350 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00005351 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005352 }
5353
Sander de Smalen50d87022018-04-19 07:35:08 +00005354 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005355 StringRef Kind;
5356 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005357 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00005358 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005359
Sander de Smalen50d87022018-04-19 07:35:08 +00005360 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00005361 return true;
5362
Sander de Smalen50d87022018-04-19 07:35:08 +00005363 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00005364 return Error(SRegLoc,
5365 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00005366 }
5367
Sander de Smalen50d87022018-04-19 07:35:08 +00005368 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00005369 StringRef Kind;
5370 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005371 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00005372
Sander de Smalen50d87022018-04-19 07:35:08 +00005373 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00005374 return true;
5375
Sander de Smalen50d87022018-04-19 07:35:08 +00005376 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00005377 return Error(SRegLoc,
5378 "sve predicate register without type specifier expected");
5379 }
5380
Sander de Smalen50d87022018-04-19 07:35:08 +00005381 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00005382 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005383
5384 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00005385 if (parseToken(AsmToken::EndOfStatement,
5386 "unexpected input in .req directive"))
5387 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005388
Sander de Smalen8e607342017-11-15 15:44:43 +00005389 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00005390 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005391 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
5392
Nirav Dave2364748a2016-09-16 18:30:20 +00005393 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005394}
5395
5396/// parseDirectiveUneq
5397/// ::= .unreq registername
5398bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005399 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00005400 if (getTok().isNot(AsmToken::Identifier))
5401 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005402 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
5403 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00005404 if (parseToken(AsmToken::EndOfStatement))
5405 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005406 return false;
5407}
5408
Luke Cheesemanf57d7d82018-12-18 10:37:42 +00005409bool AArch64AsmParser::parseDirectiveCFINegateRAState() {
5410 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5411 return true;
5412 getStreamer().EmitCFINegateRAState();
5413 return false;
5414}
5415
Luke Cheeseman41a9e532018-12-21 10:45:08 +00005416/// parseDirectiveCFIBKeyFrame
5417/// ::= .cfi_b_key
5418bool AArch64AsmParser::parseDirectiveCFIBKeyFrame() {
5419 if (parseToken(AsmToken::EndOfStatement,
5420 "unexpected token in '.cfi_b_key_frame'"))
5421 return true;
5422 getStreamer().EmitCFIBKeyFrame();
5423 return false;
5424}
5425
Tim Northover3b0846e2014-05-24 12:50:23 +00005426bool
5427AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
5428 AArch64MCExpr::VariantKind &ELFRefKind,
5429 MCSymbolRefExpr::VariantKind &DarwinRefKind,
5430 int64_t &Addend) {
5431 ELFRefKind = AArch64MCExpr::VK_INVALID;
5432 DarwinRefKind = MCSymbolRefExpr::VK_None;
5433 Addend = 0;
5434
5435 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5436 ELFRefKind = AE->getKind();
5437 Expr = AE->getSubExpr();
5438 }
5439
5440 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5441 if (SE) {
5442 // It's a simple symbol reference with no addend.
5443 DarwinRefKind = SE->getKind();
5444 return true;
5445 }
5446
David Green85d6a552018-09-18 09:44:53 +00005447 // Check that it looks like a symbol + an addend
5448 MCValue Res;
5449 bool Relocatable = Expr->evaluateAsRelocatable(Res, nullptr, nullptr);
Eli Friedman48397102018-12-20 19:46:14 +00005450 if (!Relocatable || Res.getSymB())
Tim Northover3b0846e2014-05-24 12:50:23 +00005451 return false;
5452
Eli Friedman48397102018-12-20 19:46:14 +00005453 // Treat expressions with an ELFRefKind (like ":abs_g1:3", or
5454 // ":abs_g1:x" where x is constant) as symbolic even if there is no symbol.
5455 if (!Res.getSymA() && ELFRefKind == AArch64MCExpr::VK_INVALID)
5456 return false;
5457
5458 if (Res.getSymA())
5459 DarwinRefKind = Res.getSymA()->getKind();
David Green85d6a552018-09-18 09:44:53 +00005460 Addend = Res.getConstant();
Tim Northover3b0846e2014-05-24 12:50:23 +00005461
5462 // It's some symbol reference + a constant addend, but really
5463 // shouldn't use both Darwin and ELF syntax.
5464 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5465 DarwinRefKind == MCSymbolRefExpr::VK_None;
5466}
5467
5468/// Force static initialization.
5469extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00005470 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5471 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5472 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00005473}
5474
5475#define GET_REGISTER_MATCHER
5476#define GET_SUBTARGET_FEATURE_NAME
5477#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00005478#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00005479#include "AArch64GenAsmMatcher.inc"
5480
5481// Define this matcher function after the auto-generated include so we
5482// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00005483unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00005484 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005485 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00005486 // If the kind is a token for a literal immediate, check if our asm
5487 // operand matches. This is for InstAliases which have a fixed-value
5488 // immediate in the syntax.
5489 int64_t ExpectedVal;
5490 switch (Kind) {
5491 default:
5492 return Match_InvalidOperand;
5493 case MCK__35_0:
5494 ExpectedVal = 0;
5495 break;
5496 case MCK__35_1:
5497 ExpectedVal = 1;
5498 break;
5499 case MCK__35_12:
5500 ExpectedVal = 12;
5501 break;
5502 case MCK__35_16:
5503 ExpectedVal = 16;
5504 break;
5505 case MCK__35_2:
5506 ExpectedVal = 2;
5507 break;
5508 case MCK__35_24:
5509 ExpectedVal = 24;
5510 break;
5511 case MCK__35_3:
5512 ExpectedVal = 3;
5513 break;
5514 case MCK__35_32:
5515 ExpectedVal = 32;
5516 break;
5517 case MCK__35_4:
5518 ExpectedVal = 4;
5519 break;
5520 case MCK__35_48:
5521 ExpectedVal = 48;
5522 break;
5523 case MCK__35_6:
5524 ExpectedVal = 6;
5525 break;
5526 case MCK__35_64:
5527 ExpectedVal = 64;
5528 break;
5529 case MCK__35_8:
5530 ExpectedVal = 8;
5531 break;
5532 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005533 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005534 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005535 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005536 if (!CE)
5537 return Match_InvalidOperand;
5538 if (CE->getValue() == ExpectedVal)
5539 return Match_Success;
5540 return Match_InvalidOperand;
5541}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005542
Alex Bradbury58eba092016-11-01 16:32:05 +00005543OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005544AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5545
5546 SMLoc S = getLoc();
5547
5548 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5549 Error(S, "expected register");
5550 return MatchOperand_ParseFail;
5551 }
5552
Sander de Smalen50d87022018-04-19 07:35:08 +00005553 unsigned FirstReg;
5554 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5555 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005556 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005557
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005558 const MCRegisterClass &WRegClass =
5559 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5560 const MCRegisterClass &XRegClass =
5561 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5562
5563 bool isXReg = XRegClass.contains(FirstReg),
5564 isWReg = WRegClass.contains(FirstReg);
5565 if (!isXReg && !isWReg) {
5566 Error(S, "expected first even register of a "
5567 "consecutive same-size even/odd register pair");
5568 return MatchOperand_ParseFail;
5569 }
5570
5571 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5572 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5573
5574 if (FirstEncoding & 0x1) {
5575 Error(S, "expected first even register of a "
5576 "consecutive same-size even/odd register pair");
5577 return MatchOperand_ParseFail;
5578 }
5579
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005580 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005581 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005582 return MatchOperand_ParseFail;
5583 }
5584 // Eat the comma
5585 getParser().Lex();
5586
5587 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005588 unsigned SecondReg;
5589 Res = tryParseScalarRegister(SecondReg);
5590 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005591 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005592
Eugene Zelenko049b0172017-01-06 00:30:53 +00005593 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005594 (isXReg && !XRegClass.contains(SecondReg)) ||
5595 (isWReg && !WRegClass.contains(SecondReg))) {
5596 Error(E,"expected second odd register of a "
5597 "consecutive same-size even/odd register pair");
5598 return MatchOperand_ParseFail;
5599 }
Joel Jones504bf332016-10-24 13:37:13 +00005600
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005601 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005602 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005603 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5604 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5605 } else {
5606 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5607 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5608 }
5609
Florian Hahnc4422242017-11-07 13:07:50 +00005610 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5611 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005612
5613 return MatchOperand_Success;
5614}
Florian Hahn91f11e52017-11-07 16:45:48 +00005615
Sander de Smaleneb896b12018-04-25 09:26:47 +00005616template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005617OperandMatchResultTy
5618AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005619 const SMLoc S = getLoc();
5620 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005621 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005622 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005623
Sander de Smalen8e607342017-11-15 15:44:43 +00005624 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005625 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005626
5627 if (Res != MatchOperand_Success)
5628 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005629
5630 if (ParseSuffix && Kind.empty())
5631 return MatchOperand_NoMatch;
5632
Sander de Smalen73937b72018-04-11 07:36:10 +00005633 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5634 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005635 return MatchOperand_NoMatch;
5636
Sander de Smalen73937b72018-04-11 07:36:10 +00005637 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005638
5639 // No shift/extend is the default.
5640 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5641 Operands.push_back(AArch64Operand::CreateVectorReg(
5642 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5643
Sander de Smalenc33d6682018-06-04 06:40:55 +00005644 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5645 if (Res == MatchOperand_ParseFail)
5646 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005647 return MatchOperand_Success;
5648 }
5649
5650 // Eat the comma
5651 getParser().Lex();
5652
5653 // Match the shift
5654 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5655 Res = tryParseOptionalShiftExtend(ExtOpnd);
5656 if (Res != MatchOperand_Success)
5657 return Res;
5658
5659 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005660 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005661 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5662 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5663 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005664
5665 return MatchOperand_Success;
5666}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005667
5668OperandMatchResultTy
5669AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5670 MCAsmParser &Parser = getParser();
5671
5672 SMLoc SS = getLoc();
5673 const AsmToken &TokE = Parser.getTok();
5674 bool IsHash = TokE.is(AsmToken::Hash);
5675
5676 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5677 return MatchOperand_NoMatch;
5678
5679 int64_t Pattern;
5680 if (IsHash) {
5681 Parser.Lex(); // Eat hash
5682
5683 // Parse the immediate operand.
5684 const MCExpr *ImmVal;
5685 SS = getLoc();
5686 if (Parser.parseExpression(ImmVal))
5687 return MatchOperand_ParseFail;
5688
5689 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5690 if (!MCE)
5691 return MatchOperand_ParseFail;
5692
5693 Pattern = MCE->getValue();
5694 } else {
5695 // Parse the pattern
5696 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5697 if (!Pat)
5698 return MatchOperand_NoMatch;
5699
5700 Parser.Lex();
5701 Pattern = Pat->Encoding;
5702 assert(Pattern >= 0 && Pattern < 32);
5703 }
5704
5705 Operands.push_back(
5706 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5707 SS, getLoc(), getContext()));
5708
5709 return MatchOperand_Success;
5710}