blob: edf361bc399cce8321b1b0d985f1f1563c44c082 [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();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000179
Sander de Smalen9b333092018-07-30 15:42:46 +0000180 bool validateInstruction(MCInst &Inst, SMLoc &IDLoc,
181 SmallVectorImpl<SMLoc> &Loc);
Tim Northover3b0846e2014-05-24 12:50:23 +0000182 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
183 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000184 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000185 bool MatchingInlineAsm) override;
186/// @name Auto-generated Match Functions
187/// {
188
189#define GET_ASSEMBLER_HEADER
190#include "AArch64GenAsmMatcher.inc"
191
192 /// }
193
Sander de Smalen50d87022018-04-19 07:35:08 +0000194 OperandMatchResultTy tryParseScalarRegister(unsigned &Reg);
195 OperandMatchResultTy tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +0000196 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000197 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
198 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
199 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
200 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
201 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
Sander de Smalen93380372018-05-14 11:54:41 +0000202 template <bool IsSVEPrefetch = false>
Tim Northover3b0846e2014-05-24 12:50:23 +0000203 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000204 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000205 OperandMatchResultTy tryParseBTIHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000206 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
207 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000208 template<bool AddFPZeroAsLiteral>
Tim Northover3b0846e2014-05-24 12:50:23 +0000209 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
Sander de Smalen62770792018-05-25 09:47:52 +0000210 OperandMatchResultTy tryParseImmWithOptionalShift(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000211 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000212 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000213 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000214 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Sander de Smalen0325e302018-07-02 07:34:52 +0000215 template <bool ParseShiftExtend,
216 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg>
Sander de Smalen149916d2018-04-20 07:24:20 +0000217 OperandMatchResultTy tryParseGPROperand(OperandVector &Operands);
Sander de Smaleneb896b12018-04-25 09:26:47 +0000218 template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +0000219 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000220 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000221 template <RegKind VectorKind>
222 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
223 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000224 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000225
226public:
227 enum AArch64MatchResultTy {
228 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
229#define GET_OPERAND_DIAGNOSTIC_TYPES
230#include "AArch64GenAsmMatcher.inc"
231 };
Joel Jones504bf332016-10-24 13:37:13 +0000232 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000233
Akira Hatanakab11ef082015-11-14 06:35:56 +0000234 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000235 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000236 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000237 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000238 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000239 MCStreamer &S = getParser().getStreamer();
240 if (S.getTargetStreamer() == nullptr)
241 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000242
Alex Bradbury0a59f182018-05-23 11:17:20 +0000243 // Alias .hword/.word/xword to the target-independent .2byte/.4byte/.8byte
244 // directives as they have the same form and semantics:
245 /// ::= (.hword | .word | .xword ) [ expression (, expression)* ]
246 Parser.addAliasForDirective(".hword", ".2byte");
247 Parser.addAliasForDirective(".word", ".4byte");
248 Parser.addAliasForDirective(".xword", ".8byte");
249
Tim Northover3b0846e2014-05-24 12:50:23 +0000250 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000251 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000252 }
253
Sander de Smalen0325e302018-07-02 07:34:52 +0000254 bool regsEqual(const MCParsedAsmOperand &Op1,
255 const MCParsedAsmOperand &Op2) const override;
Tim Northover3b0846e2014-05-24 12:50:23 +0000256 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
257 SMLoc NameLoc, OperandVector &Operands) override;
258 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
259 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000260 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000261 unsigned Kind) override;
262
263 static bool classifySymbolRef(const MCExpr *Expr,
264 AArch64MCExpr::VariantKind &ELFRefKind,
265 MCSymbolRefExpr::VariantKind &DarwinRefKind,
266 int64_t &Addend);
267};
Tim Northover3b0846e2014-05-24 12:50:23 +0000268
269/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
270/// instruction.
271class AArch64Operand : public MCParsedAsmOperand {
272private:
273 enum KindTy {
274 k_Immediate,
275 k_ShiftedImm,
276 k_CondCode,
277 k_Register,
278 k_VectorList,
279 k_VectorIndex,
280 k_Token,
281 k_SysReg,
282 k_SysCR,
283 k_Prefetch,
284 k_ShiftExtend,
285 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000286 k_Barrier,
287 k_PSBHint,
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000288 k_BTIHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000289 } Kind;
290
291 SMLoc StartLoc, EndLoc;
292
293 struct TokOp {
294 const char *Data;
295 unsigned Length;
296 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
297 };
298
Sander de Smalen149916d2018-04-20 07:24:20 +0000299 // Separate shift/extend operand.
300 struct ShiftExtendOp {
301 AArch64_AM::ShiftExtendType Type;
302 unsigned Amount;
303 bool HasExplicitAmount;
304 };
305
Tim Northover3b0846e2014-05-24 12:50:23 +0000306 struct RegOp {
307 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000308 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000309 int ElementWidth;
Sander de Smalen149916d2018-04-20 07:24:20 +0000310
Sander de Smalen0325e302018-07-02 07:34:52 +0000311 // The register may be allowed as a different register class,
312 // e.g. for GPR64as32 or GPR32as64.
313 RegConstraintEqualityTy EqualityTy;
314
Sander de Smalen149916d2018-04-20 07:24:20 +0000315 // In some cases the shift/extend needs to be explicitly parsed together
316 // with the register, rather than as a separate operand. This is needed
317 // for addressing modes where the instruction as a whole dictates the
318 // scaling/extend, rather than specific bits in the instruction.
319 // By parsing them as a single operand, we avoid the need to pass an
320 // extra operand in all CodeGen patterns (because all operands need to
321 // have an associated value), and we avoid the need to update TableGen to
322 // accept operands that have no associated bits in the instruction.
323 //
324 // An added benefit of parsing them together is that the assembler
325 // can give a sensible diagnostic if the scaling is not correct.
326 //
327 // The default is 'lsl #0' (HasExplicitAmount = false) if no
328 // ShiftExtend is specified.
329 ShiftExtendOp ShiftExtend;
Tim Northover3b0846e2014-05-24 12:50:23 +0000330 };
331
332 struct VectorListOp {
333 unsigned RegNum;
334 unsigned Count;
335 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000336 unsigned ElementWidth;
337 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000338 };
339
340 struct VectorIndexOp {
341 unsigned Val;
342 };
343
344 struct ImmOp {
345 const MCExpr *Val;
346 };
347
348 struct ShiftedImmOp {
349 const MCExpr *Val;
350 unsigned ShiftAmount;
351 };
352
353 struct CondCodeOp {
354 AArch64CC::CondCode Code;
355 };
356
357 struct FPImmOp {
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000358 uint64_t Val; // APFloat value bitcasted to uint64_t.
359 bool IsExact; // describes whether parsed value was exact.
Tim Northover3b0846e2014-05-24 12:50:23 +0000360 };
361
362 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000363 const char *Data;
364 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000365 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000366 };
367
368 struct SysRegOp {
369 const char *Data;
370 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000371 uint32_t MRSReg;
372 uint32_t MSRReg;
373 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000374 };
375
376 struct SysCRImmOp {
377 unsigned Val;
378 };
379
380 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000381 const char *Data;
382 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000383 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000384 };
385
Oliver Stannarda34e4702015-12-01 10:48:51 +0000386 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000387 const char *Data;
388 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000389 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000390 };
391
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000392 struct BTIHintOp {
393 const char *Data;
394 unsigned Length;
395 unsigned Val;
396 };
397
Tim Northover3b0846e2014-05-24 12:50:23 +0000398 struct ExtendOp {
399 unsigned Val;
400 };
401
402 union {
403 struct TokOp Tok;
404 struct RegOp Reg;
405 struct VectorListOp VectorList;
406 struct VectorIndexOp VectorIndex;
407 struct ImmOp Imm;
408 struct ShiftedImmOp ShiftedImm;
409 struct CondCodeOp CondCode;
410 struct FPImmOp FPImm;
411 struct BarrierOp Barrier;
412 struct SysRegOp SysReg;
413 struct SysCRImmOp SysCRImm;
414 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000415 struct PSBHintOp PSBHint;
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000416 struct BTIHintOp BTIHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000417 struct ShiftExtendOp ShiftExtend;
418 };
419
420 // Keep the MCContext around as the MCExprs may need manipulated during
421 // the add<>Operands() calls.
422 MCContext &Ctx;
423
David Blaikie960ea3f2014-06-08 16:18:35 +0000424public:
David Blaikie9f380a32015-03-16 18:06:57 +0000425 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000426
Tim Northover3b0846e2014-05-24 12:50:23 +0000427 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
428 Kind = o.Kind;
429 StartLoc = o.StartLoc;
430 EndLoc = o.EndLoc;
431 switch (Kind) {
432 case k_Token:
433 Tok = o.Tok;
434 break;
435 case k_Immediate:
436 Imm = o.Imm;
437 break;
438 case k_ShiftedImm:
439 ShiftedImm = o.ShiftedImm;
440 break;
441 case k_CondCode:
442 CondCode = o.CondCode;
443 break;
444 case k_FPImm:
445 FPImm = o.FPImm;
446 break;
447 case k_Barrier:
448 Barrier = o.Barrier;
449 break;
450 case k_Register:
451 Reg = o.Reg;
452 break;
453 case k_VectorList:
454 VectorList = o.VectorList;
455 break;
456 case k_VectorIndex:
457 VectorIndex = o.VectorIndex;
458 break;
459 case k_SysReg:
460 SysReg = o.SysReg;
461 break;
462 case k_SysCR:
463 SysCRImm = o.SysCRImm;
464 break;
465 case k_Prefetch:
466 Prefetch = o.Prefetch;
467 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000468 case k_PSBHint:
469 PSBHint = o.PSBHint;
470 break;
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000471 case k_BTIHint:
472 BTIHint = o.BTIHint;
473 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000474 case k_ShiftExtend:
475 ShiftExtend = o.ShiftExtend;
476 break;
477 }
478 }
479
480 /// getStartLoc - Get the location of the first token of this operand.
481 SMLoc getStartLoc() const override { return StartLoc; }
482 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000483 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000484
485 StringRef getToken() const {
486 assert(Kind == k_Token && "Invalid access!");
487 return StringRef(Tok.Data, Tok.Length);
488 }
489
490 bool isTokenSuffix() const {
491 assert(Kind == k_Token && "Invalid access!");
492 return Tok.IsSuffix;
493 }
494
495 const MCExpr *getImm() const {
496 assert(Kind == k_Immediate && "Invalid access!");
497 return Imm.Val;
498 }
499
500 const MCExpr *getShiftedImmVal() const {
501 assert(Kind == k_ShiftedImm && "Invalid access!");
502 return ShiftedImm.Val;
503 }
504
505 unsigned getShiftedImmShift() const {
506 assert(Kind == k_ShiftedImm && "Invalid access!");
507 return ShiftedImm.ShiftAmount;
508 }
509
510 AArch64CC::CondCode getCondCode() const {
511 assert(Kind == k_CondCode && "Invalid access!");
512 return CondCode.Code;
513 }
514
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000515 APFloat getFPImm() const {
516 assert (Kind == k_FPImm && "Invalid access!");
517 return APFloat(APFloat::IEEEdouble(), APInt(64, FPImm.Val, true));
518 }
519
520 bool getFPImmIsExact() const {
521 assert (Kind == k_FPImm && "Invalid access!");
522 return FPImm.IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +0000523 }
524
525 unsigned getBarrier() const {
526 assert(Kind == k_Barrier && "Invalid access!");
527 return Barrier.Val;
528 }
529
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000530 StringRef getBarrierName() const {
531 assert(Kind == k_Barrier && "Invalid access!");
532 return StringRef(Barrier.Data, Barrier.Length);
533 }
534
Tim Northover3b0846e2014-05-24 12:50:23 +0000535 unsigned getReg() const override {
536 assert(Kind == k_Register && "Invalid access!");
537 return Reg.RegNum;
538 }
539
Sander de Smalen0325e302018-07-02 07:34:52 +0000540 RegConstraintEqualityTy getRegEqualityTy() const {
541 assert(Kind == k_Register && "Invalid access!");
542 return Reg.EqualityTy;
543 }
544
Tim Northover3b0846e2014-05-24 12:50:23 +0000545 unsigned getVectorListStart() const {
546 assert(Kind == k_VectorList && "Invalid access!");
547 return VectorList.RegNum;
548 }
549
550 unsigned getVectorListCount() const {
551 assert(Kind == k_VectorList && "Invalid access!");
552 return VectorList.Count;
553 }
554
555 unsigned getVectorIndex() const {
556 assert(Kind == k_VectorIndex && "Invalid access!");
557 return VectorIndex.Val;
558 }
559
560 StringRef getSysReg() const {
561 assert(Kind == k_SysReg && "Invalid access!");
562 return StringRef(SysReg.Data, SysReg.Length);
563 }
564
Tim Northover3b0846e2014-05-24 12:50:23 +0000565 unsigned getSysCR() const {
566 assert(Kind == k_SysCR && "Invalid access!");
567 return SysCRImm.Val;
568 }
569
570 unsigned getPrefetch() const {
571 assert(Kind == k_Prefetch && "Invalid access!");
572 return Prefetch.Val;
573 }
574
Oliver Stannarda34e4702015-12-01 10:48:51 +0000575 unsigned getPSBHint() const {
576 assert(Kind == k_PSBHint && "Invalid access!");
577 return PSBHint.Val;
578 }
579
580 StringRef getPSBHintName() const {
581 assert(Kind == k_PSBHint && "Invalid access!");
582 return StringRef(PSBHint.Data, PSBHint.Length);
583 }
584
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000585 unsigned getBTIHint() const {
586 assert(Kind == k_BTIHint && "Invalid access!");
587 return BTIHint.Val;
588 }
589
590 StringRef getBTIHintName() const {
591 assert(Kind == k_BTIHint && "Invalid access!");
592 return StringRef(BTIHint.Data, BTIHint.Length);
593 }
594
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000595 StringRef getPrefetchName() const {
596 assert(Kind == k_Prefetch && "Invalid access!");
597 return StringRef(Prefetch.Data, Prefetch.Length);
598 }
599
Tim Northover3b0846e2014-05-24 12:50:23 +0000600 AArch64_AM::ShiftExtendType getShiftExtendType() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000601 if (Kind == k_ShiftExtend)
602 return ShiftExtend.Type;
603 if (Kind == k_Register)
604 return Reg.ShiftExtend.Type;
605 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000606 }
607
608 unsigned getShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000609 if (Kind == k_ShiftExtend)
610 return ShiftExtend.Amount;
611 if (Kind == k_Register)
612 return Reg.ShiftExtend.Amount;
613 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000614 }
615
616 bool hasShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000617 if (Kind == k_ShiftExtend)
618 return ShiftExtend.HasExplicitAmount;
619 if (Kind == k_Register)
620 return Reg.ShiftExtend.HasExplicitAmount;
621 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000622 }
623
624 bool isImm() const override { return Kind == k_Immediate; }
625 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000626
Sjoerd Meijera3dad802018-07-06 12:32:33 +0000627 bool isUImm6() const {
628 if (!isImm())
629 return false;
630 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
631 if (!MCE)
632 return false;
633 int64_t Val = MCE->getValue();
634 return (Val >= 0 && Val < 64);
635 }
636
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000637 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
638
Sander de Smalen50ded902018-04-29 17:33:38 +0000639 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
640 return isImmScaled<Bits, Scale>(true);
641 }
642
643 template <int Bits, int Scale> DiagnosticPredicate isUImmScaled() const {
644 return isImmScaled<Bits, Scale>(false);
645 }
646
Sander de Smalenfe17a782018-04-26 12:54:42 +0000647 template <int Bits, int Scale>
Sander de Smalen50ded902018-04-29 17:33:38 +0000648 DiagnosticPredicate isImmScaled(bool Signed) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000649 if (!isImm())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000650 return DiagnosticPredicateTy::NoMatch;
651
Tim Northover3b0846e2014-05-24 12:50:23 +0000652 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
653 if (!MCE)
Sander de Smalenfe17a782018-04-26 12:54:42 +0000654 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000655
Sander de Smalen50ded902018-04-29 17:33:38 +0000656 int64_t MinVal, MaxVal;
657 if (Signed) {
658 int64_t Shift = Bits - 1;
659 MinVal = (int64_t(1) << Shift) * -Scale;
660 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
661 } else {
662 MinVal = 0;
663 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
664 }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000665
Tim Northover3b0846e2014-05-24 12:50:23 +0000666 int64_t Val = MCE->getValue();
Sander de Smalenfe17a782018-04-26 12:54:42 +0000667 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
668 return DiagnosticPredicateTy::Match;
669
670 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +0000671 }
672
Sander de Smalen0325e302018-07-02 07:34:52 +0000673 DiagnosticPredicate isSVEPattern() const {
Sander de Smalen245e0e62018-01-22 10:46:00 +0000674 if (!isImm())
Sander de Smalen0325e302018-07-02 07:34:52 +0000675 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000676 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
677 if (!MCE)
Sander de Smalen0325e302018-07-02 07:34:52 +0000678 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000679 int64_t Val = MCE->getValue();
Sander de Smalen0325e302018-07-02 07:34:52 +0000680 if (Val >= 0 && Val < 32)
681 return DiagnosticPredicateTy::Match;
682 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000683 }
684
David Green85d6a552018-09-18 09:44:53 +0000685 bool isSymbolicUImm12Offset(const MCExpr *Expr) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000686 AArch64MCExpr::VariantKind ELFRefKind;
687 MCSymbolRefExpr::VariantKind DarwinRefKind;
688 int64_t Addend;
689 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
690 Addend)) {
691 // If we don't understand the expression, assume the best and
692 // let the fixup and relocation code deal with it.
693 return true;
694 }
695
696 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
697 ELFRefKind == AArch64MCExpr::VK_LO12 ||
698 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
699 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
700 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
701 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
702 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
703 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000704 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
705 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
706 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000707 // Note that we don't range-check the addend. It's adjusted modulo page
708 // size when converted, so there is no "out of range" condition when using
709 // @pageoff.
David Green85d6a552018-09-18 09:44:53 +0000710 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000711 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
712 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
713 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
714 return Addend == 0;
715 }
716
717 return false;
718 }
719
720 template <int Scale> bool isUImm12Offset() const {
721 if (!isImm())
722 return false;
723
724 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
725 if (!MCE)
David Green85d6a552018-09-18 09:44:53 +0000726 return isSymbolicUImm12Offset(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +0000727
728 int64_t Val = MCE->getValue();
729 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
730 }
731
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000732 template <int N, int M>
733 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000734 if (!isImm())
735 return false;
736 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
737 if (!MCE)
738 return false;
739 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000740 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000741 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000742
Sander de Smalena1c259c2018-01-29 13:05:38 +0000743 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
744 // a logical immediate can always be represented when inverted.
745 template <typename T>
746 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000747 if (!isImm())
748 return false;
749 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
750 if (!MCE)
751 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000752
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000753 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000754 int64_t SVal = typename std::make_signed<T>::type(Val);
755 int64_t UVal = typename std::make_unsigned<T>::type(Val);
756 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000757 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000758
Sander de Smalena1c259c2018-01-29 13:05:38 +0000759 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000760 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000761
Tim Northover3b0846e2014-05-24 12:50:23 +0000762 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000763
Sander de Smalen62770792018-05-25 09:47:52 +0000764 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
765 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
766 /// immediate that can be shifted by 'Shift'.
767 template <unsigned Width>
768 Optional<std::pair<int64_t, unsigned> > getShiftedVal() const {
769 if (isShiftedImm() && Width == getShiftedImmShift())
770 if (auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
771 return std::make_pair(CE->getValue(), Width);
772
773 if (isImm())
774 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
775 int64_t Val = CE->getValue();
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000776 if ((Val != 0) && (uint64_t(Val >> Width) << Width) == uint64_t(Val))
Sander de Smalen62770792018-05-25 09:47:52 +0000777 return std::make_pair(Val >> Width, Width);
778 else
779 return std::make_pair(Val, 0u);
780 }
781
782 return {};
783 }
784
Tim Northover3b0846e2014-05-24 12:50:23 +0000785 bool isAddSubImm() const {
786 if (!isShiftedImm() && !isImm())
787 return false;
788
789 const MCExpr *Expr;
790
791 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
792 if (isShiftedImm()) {
793 unsigned Shift = ShiftedImm.ShiftAmount;
794 Expr = ShiftedImm.Val;
795 if (Shift != 0 && Shift != 12)
796 return false;
797 } else {
798 Expr = getImm();
799 }
800
801 AArch64MCExpr::VariantKind ELFRefKind;
802 MCSymbolRefExpr::VariantKind DarwinRefKind;
803 int64_t Addend;
804 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
805 DarwinRefKind, Addend)) {
806 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
807 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
808 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
809 || ELFRefKind == AArch64MCExpr::VK_LO12
810 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
811 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
812 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
813 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
814 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
815 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000816 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
817 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
818 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000819 }
820
Sander de Smalen98686c62018-05-29 10:39:49 +0000821 // If it's a constant, it should be a real immediate in range.
Sander de Smalen62770792018-05-25 09:47:52 +0000822 if (auto ShiftedVal = getShiftedVal<12>())
823 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
Diana Picusc93518d2016-10-11 09:17:47 +0000824
825 // If it's an expression, we hope for the best and let the fixup/relocation
826 // code deal with it.
827 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000828 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000829
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000830 bool isAddSubImmNeg() const {
831 if (!isShiftedImm() && !isImm())
832 return false;
833
Sander de Smalen98686c62018-05-29 10:39:49 +0000834 // Otherwise it should be a real negative immediate in range.
835 if (auto ShiftedVal = getShiftedVal<12>())
836 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000837
Sander de Smalen98686c62018-05-29 10:39:49 +0000838 return false;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000839 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000840
Sander de Smalen62770792018-05-25 09:47:52 +0000841 // Signed value in the range -128 to +127. For element widths of
842 // 16 bits or higher it may also be a signed multiple of 256 in the
843 // range -32768 to +32512.
844 // For element-width of 8 bits a range of -128 to 255 is accepted,
845 // since a copy of a byte can be either signed/unsigned.
846 template <typename T>
847 DiagnosticPredicate isSVECpyImm() const {
848 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
849 return DiagnosticPredicateTy::NoMatch;
850
851 bool IsByte =
852 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
853 if (auto ShiftedImm = getShiftedVal<8>())
854 if (!(IsByte && ShiftedImm->second) &&
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000855 AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
856 << ShiftedImm->second))
Sander de Smalen62770792018-05-25 09:47:52 +0000857 return DiagnosticPredicateTy::Match;
858
859 return DiagnosticPredicateTy::NearMatch;
860 }
861
Sander de Smalen98686c62018-05-29 10:39:49 +0000862 // Unsigned value in the range 0 to 255. For element widths of
863 // 16 bits or higher it may also be a signed multiple of 256 in the
864 // range 0 to 65280.
865 template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
866 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
867 return DiagnosticPredicateTy::NoMatch;
868
869 bool IsByte =
870 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
871 if (auto ShiftedImm = getShiftedVal<8>())
872 if (!(IsByte && ShiftedImm->second) &&
873 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
874 << ShiftedImm->second))
875 return DiagnosticPredicateTy::Match;
876
877 return DiagnosticPredicateTy::NearMatch;
878 }
879
Sander de Smalen97ca6b92018-06-01 07:25:46 +0000880 template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
881 if (isLogicalImm<T>() && !isSVECpyImm<T>())
882 return DiagnosticPredicateTy::Match;
883 return DiagnosticPredicateTy::NoMatch;
884 }
885
Tim Northover3b0846e2014-05-24 12:50:23 +0000886 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000887
Tim Northover3b0846e2014-05-24 12:50:23 +0000888 bool isSIMDImmType10() const {
889 if (!isImm())
890 return false;
891 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
892 if (!MCE)
893 return false;
894 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
895 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000896
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000897 template<int N>
898 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000899 if (!isImm())
900 return false;
901 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
902 if (!MCE)
903 return true;
904 int64_t Val = MCE->getValue();
905 if (Val & 0x3)
906 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000907 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
908 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000909 }
910
911 bool
912 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
913 if (!isImm())
914 return false;
915
916 AArch64MCExpr::VariantKind ELFRefKind;
917 MCSymbolRefExpr::VariantKind DarwinRefKind;
918 int64_t Addend;
919 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
920 DarwinRefKind, Addend)) {
921 return false;
922 }
923 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
924 return false;
925
926 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
927 if (ELFRefKind == AllowedModifiers[i])
David Green85d6a552018-09-18 09:44:53 +0000928 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000929 }
930
931 return false;
932 }
933
934 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000935 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000936 }
937
938 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000939 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
940 AArch64MCExpr::VK_TPREL_G2,
941 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000942 }
943
944 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000945 return isMovWSymbol({
946 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000947 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
948 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000949 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000950 }
951
952 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000953 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
954 AArch64MCExpr::VK_TPREL_G0,
955 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000956 }
957
958 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000959 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000960 }
961
962 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000963 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000964 }
965
966 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000967 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
968 AArch64MCExpr::VK_TPREL_G1_NC,
969 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000970 }
971
972 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000973 return isMovWSymbol(
974 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
975 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000976 }
977
978 template<int RegWidth, int Shift>
979 bool isMOVZMovAlias() const {
980 if (!isImm()) return false;
981
982 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
983 if (!CE) return false;
984 uint64_t Value = CE->getValue();
985
Tim Northoverdaa1c012016-06-16 01:42:25 +0000986 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000987 }
988
989 template<int RegWidth, int Shift>
990 bool isMOVNMovAlias() const {
991 if (!isImm()) return false;
992
993 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
994 if (!CE) return false;
995 uint64_t Value = CE->getValue();
996
Tim Northoverdaa1c012016-06-16 01:42:25 +0000997 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000998 }
999
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001000 bool isFPImm() const {
1001 return Kind == k_FPImm &&
1002 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt()) != -1;
1003 }
1004
Tim Northover3b0846e2014-05-24 12:50:23 +00001005 bool isBarrier() const { return Kind == k_Barrier; }
1006 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001007
Tim Northover3b0846e2014-05-24 12:50:23 +00001008 bool isMRSSystemRegister() const {
1009 if (!isSysReg()) return false;
1010
Tim Northover7cd58932015-01-22 17:23:04 +00001011 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +00001012 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001013
Tim Northover3b0846e2014-05-24 12:50:23 +00001014 bool isMSRSystemRegister() const {
1015 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +00001016 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +00001017 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001018
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001019 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001020 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +00001021 return (SysReg.PStateField == AArch64PState::PAN ||
Sjoerd Meijer173b7f02018-07-03 12:09:20 +00001022 SysReg.PStateField == AArch64PState::DIT ||
Oliver Stannard8459d342018-09-27 14:05:46 +00001023 SysReg.PStateField == AArch64PState::UAO ||
1024 SysReg.PStateField == AArch64PState::SSBS);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001025 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001026
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001027 bool isSystemPStateFieldWithImm0_15() const {
1028 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +00001029 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +00001030 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001031
Florian Hahnc4422242017-11-07 13:07:50 +00001032 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00001033 return Kind == k_Register;
1034 }
1035
1036 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001037 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
1038 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001039
Florian Hahnc4422242017-11-07 13:07:50 +00001040 bool isNeonVectorReg() const {
1041 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
1042 }
1043
1044 bool isNeonVectorRegLo() const {
1045 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001046 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
1047 Reg.RegNum);
1048 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001049
Sander de Smalencd6be962017-12-20 11:02:42 +00001050 template <unsigned Class> bool isSVEVectorReg() const {
1051 RegKind RK;
1052 switch (Class) {
1053 case AArch64::ZPRRegClassID:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00001054 case AArch64::ZPR_3bRegClassID:
1055 case AArch64::ZPR_4bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +00001056 RK = RegKind::SVEDataVector;
1057 break;
1058 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +00001059 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +00001060 RK = RegKind::SVEPredicateVector;
1061 break;
1062 default:
1063 llvm_unreachable("Unsupport register class");
1064 }
1065
1066 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +00001067 AArch64MCRegisterClasses[Class].contains(getReg());
1068 }
1069
Sander de Smalenfd54a782018-06-04 07:07:35 +00001070 template <unsigned Class> bool isFPRasZPR() const {
1071 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1072 AArch64MCRegisterClasses[Class].contains(getReg());
1073 }
1074
Sander de Smalencd6be962017-12-20 11:02:42 +00001075 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +00001076 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
1077 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
1078 return DiagnosticPredicateTy::NoMatch;
1079
1080 if (isSVEVectorReg<Class>() &&
1081 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
1082 return DiagnosticPredicateTy::Match;
1083
1084 return DiagnosticPredicateTy::NearMatch;
1085 }
1086
1087 template <int ElementWidth, unsigned Class>
1088 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
1089 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
1090 return DiagnosticPredicateTy::NoMatch;
1091
1092 if (isSVEVectorReg<Class>() &&
1093 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
1094 return DiagnosticPredicateTy::Match;
1095
1096 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00001097 }
1098
Sander de Smaleneb896b12018-04-25 09:26:47 +00001099 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +00001100 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
1101 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +00001102 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
1103 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
1104 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001105 return DiagnosticPredicateTy::NoMatch;
1106
Sander de Smalen5861c262018-04-30 07:24:38 +00001107 // Give a more specific diagnostic when the user has explicitly typed in
1108 // a shift-amount that does not match what is expected, but for which
1109 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
1110 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
1111 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
1112 ShiftExtendTy == AArch64_AM::SXTW) &&
1113 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
1114 return DiagnosticPredicateTy::NoMatch;
1115
1116 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001117 return DiagnosticPredicateTy::Match;
1118
1119 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +00001120 }
1121
Tim Northover3b0846e2014-05-24 12:50:23 +00001122 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001123 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001124 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
1125 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001126
Sander de Smalen0325e302018-07-02 07:34:52 +00001127 bool isGPR64as32() const {
1128 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1129 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(Reg.RegNum);
1130 }
1131
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001132 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001133 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001134 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
1135 Reg.RegNum);
1136 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001137
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001138 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001139 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001140 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1141 Reg.RegNum);
1142 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001143
Sam Parker5f934642017-08-31 09:27:04 +00001144 template<int64_t Angle, int64_t Remainder>
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001145 DiagnosticPredicate isComplexRotation() const {
1146 if (!isImm()) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001147
1148 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001149 if (!CE) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001150 uint64_t Value = CE->getValue();
1151
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001152 if (Value % Angle == Remainder && Value <= 270)
1153 return DiagnosticPredicateTy::Match;
1154 return DiagnosticPredicateTy::NearMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001155 }
1156
Sander de Smalen149916d2018-04-20 07:24:20 +00001157 template <unsigned RegClassID> bool isGPR64() const {
1158 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1159 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1160 }
1161
1162 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001163 DiagnosticPredicate isGPR64WithShiftExtend() const {
1164 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1165 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001166
Sander de Smalenfe17a782018-04-26 12:54:42 +00001167 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1168 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1169 return DiagnosticPredicateTy::Match;
1170 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001171 }
1172
Tim Northover3b0846e2014-05-24 12:50:23 +00001173 /// Is this a vector list with the type implicit (presumably attached to the
1174 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001175 template <RegKind VectorKind, unsigned NumRegs>
1176 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001177 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001178 VectorList.NumElements == 0 &&
1179 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001180 }
1181
Sander de Smalen650234b2018-04-12 11:40:52 +00001182 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1183 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001184 bool isTypedVectorList() const {
1185 if (Kind != k_VectorList)
1186 return false;
1187 if (VectorList.Count != NumRegs)
1188 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001189 if (VectorList.RegisterKind != VectorKind)
1190 return false;
1191 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001192 return false;
1193 return VectorList.NumElements == NumElements;
1194 }
1195
Sander de Smalenc33d6682018-06-04 06:40:55 +00001196 template <int Min, int Max>
1197 DiagnosticPredicate isVectorIndex() const {
1198 if (Kind != k_VectorIndex)
1199 return DiagnosticPredicateTy::NoMatch;
1200 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1201 return DiagnosticPredicateTy::Match;
1202 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001203 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001204
Tim Northover3b0846e2014-05-24 12:50:23 +00001205 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001206
Tim Northover3b0846e2014-05-24 12:50:23 +00001207 bool isTokenEqual(StringRef Str) const {
1208 return Kind == k_Token && getToken() == Str;
1209 }
1210 bool isSysCR() const { return Kind == k_SysCR; }
1211 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001212 bool isPSBHint() const { return Kind == k_PSBHint; }
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001213 bool isBTIHint() const { return Kind == k_BTIHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001214 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1215 bool isShifter() const {
1216 if (!isShiftExtend())
1217 return false;
1218
1219 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1220 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1221 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1222 ST == AArch64_AM::MSL);
1223 }
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001224
1225 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1226 if (Kind != k_FPImm)
1227 return DiagnosticPredicateTy::NoMatch;
1228
1229 if (getFPImmIsExact()) {
1230 // Lookup the immediate from table of supported immediates.
1231 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1232 assert(Desc && "Unknown enum value");
1233
1234 // Calculate its FP value.
1235 APFloat RealVal(APFloat::IEEEdouble());
1236 if (RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero) !=
1237 APFloat::opOK)
1238 llvm_unreachable("FP immediate is not exact");
1239
1240 if (getFPImm().bitwiseIsEqual(RealVal))
1241 return DiagnosticPredicateTy::Match;
1242 }
1243
1244 return DiagnosticPredicateTy::NearMatch;
1245 }
1246
1247 template <unsigned ImmA, unsigned ImmB>
1248 DiagnosticPredicate isExactFPImm() const {
1249 DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1250 if ((Res = isExactFPImm<ImmA>()))
1251 return DiagnosticPredicateTy::Match;
1252 if ((Res = isExactFPImm<ImmB>()))
1253 return DiagnosticPredicateTy::Match;
1254 return Res;
1255 }
1256
Tim Northover3b0846e2014-05-24 12:50:23 +00001257 bool isExtend() const {
1258 if (!isShiftExtend())
1259 return false;
1260
1261 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1262 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1263 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1264 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1265 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1266 ET == AArch64_AM::LSL) &&
1267 getShiftExtendAmount() <= 4;
1268 }
1269
1270 bool isExtend64() const {
1271 if (!isExtend())
1272 return false;
1273 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1274 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1275 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1276 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001277
Tim Northover3b0846e2014-05-24 12:50:23 +00001278 bool isExtendLSL64() const {
1279 if (!isExtend())
1280 return false;
1281 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1282 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1283 ET == AArch64_AM::LSL) &&
1284 getShiftExtendAmount() <= 4;
1285 }
1286
1287 template<int Width> bool isMemXExtend() const {
1288 if (!isExtend())
1289 return false;
1290 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1291 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1292 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1293 getShiftExtendAmount() == 0);
1294 }
1295
1296 template<int Width> bool isMemWExtend() const {
1297 if (!isExtend())
1298 return false;
1299 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1300 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1301 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1302 getShiftExtendAmount() == 0);
1303 }
1304
1305 template <unsigned width>
1306 bool isArithmeticShifter() const {
1307 if (!isShifter())
1308 return false;
1309
1310 // An arithmetic shifter is LSL, LSR, or ASR.
1311 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1312 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1313 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1314 }
1315
1316 template <unsigned width>
1317 bool isLogicalShifter() const {
1318 if (!isShifter())
1319 return false;
1320
1321 // A logical shifter is LSL, LSR, ASR or ROR.
1322 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1323 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1324 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1325 getShiftExtendAmount() < width;
1326 }
1327
1328 bool isMovImm32Shifter() const {
1329 if (!isShifter())
1330 return false;
1331
1332 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1333 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1334 if (ST != AArch64_AM::LSL)
1335 return false;
1336 uint64_t Val = getShiftExtendAmount();
1337 return (Val == 0 || Val == 16);
1338 }
1339
1340 bool isMovImm64Shifter() const {
1341 if (!isShifter())
1342 return false;
1343
1344 // A MOVi shifter is LSL of 0 or 16.
1345 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1346 if (ST != AArch64_AM::LSL)
1347 return false;
1348 uint64_t Val = getShiftExtendAmount();
1349 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1350 }
1351
1352 bool isLogicalVecShifter() const {
1353 if (!isShifter())
1354 return false;
1355
1356 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1357 unsigned Shift = getShiftExtendAmount();
1358 return getShiftExtendType() == AArch64_AM::LSL &&
1359 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1360 }
1361
1362 bool isLogicalVecHalfWordShifter() const {
1363 if (!isLogicalVecShifter())
1364 return false;
1365
1366 // A logical vector shifter is a left shift by 0 or 8.
1367 unsigned Shift = getShiftExtendAmount();
1368 return getShiftExtendType() == AArch64_AM::LSL &&
1369 (Shift == 0 || Shift == 8);
1370 }
1371
1372 bool isMoveVecShifter() const {
1373 if (!isShiftExtend())
1374 return false;
1375
1376 // A logical vector shifter is a left shift by 8 or 16.
1377 unsigned Shift = getShiftExtendAmount();
1378 return getShiftExtendType() == AArch64_AM::MSL &&
1379 (Shift == 8 || Shift == 16);
1380 }
1381
1382 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1383 // to LDUR/STUR when the offset is not legal for the former but is for
1384 // the latter. As such, in addition to checking for being a legal unscaled
1385 // address, also check that it is not a legal scaled address. This avoids
1386 // ambiguity in the matcher.
1387 template<int Width>
1388 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001389 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001390 }
1391
1392 bool isAdrpLabel() const {
1393 // Validation was handled during parsing, so we just sanity check that
1394 // something didn't go haywire.
1395 if (!isImm())
1396 return false;
1397
1398 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1399 int64_t Val = CE->getValue();
1400 int64_t Min = - (4096 * (1LL << (21 - 1)));
1401 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1402 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1403 }
1404
1405 return true;
1406 }
1407
1408 bool isAdrLabel() const {
1409 // Validation was handled during parsing, so we just sanity check that
1410 // something didn't go haywire.
1411 if (!isImm())
1412 return false;
1413
1414 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1415 int64_t Val = CE->getValue();
1416 int64_t Min = - (1LL << (21 - 1));
1417 int64_t Max = ((1LL << (21 - 1)) - 1);
1418 return Val >= Min && Val <= Max;
1419 }
1420
1421 return true;
1422 }
1423
1424 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1425 // Add as immediates when possible. Null MCExpr = 0.
1426 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001427 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001428 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001429 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001430 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001431 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001432 }
1433
1434 void addRegOperands(MCInst &Inst, unsigned N) const {
1435 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001436 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001437 }
1438
1439 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1440 assert(N == 1 && "Invalid number of operands!");
1441 assert(
1442 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1443
1444 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1445 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1446 RI->getEncodingValue(getReg()));
1447
Jim Grosbache9119e42015-05-13 18:37:00 +00001448 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001449 }
1450
Sander de Smalen0325e302018-07-02 07:34:52 +00001451 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1452 assert(N == 1 && "Invalid number of operands!");
1453 assert(
1454 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(getReg()));
1455
1456 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1457 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID).getRegister(
1458 RI->getEncodingValue(getReg()));
1459
1460 Inst.addOperand(MCOperand::createReg(Reg));
1461 }
1462
Sander de Smalenfd54a782018-06-04 07:07:35 +00001463 template <int Width>
1464 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1465 unsigned Base;
1466 switch (Width) {
1467 case 8: Base = AArch64::B0; break;
1468 case 16: Base = AArch64::H0; break;
1469 case 32: Base = AArch64::S0; break;
1470 case 64: Base = AArch64::D0; break;
1471 case 128: Base = AArch64::Q0; break;
1472 default:
1473 llvm_unreachable("Unsupported width");
1474 }
1475 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1476 }
1477
Tim Northover3b0846e2014-05-24 12:50:23 +00001478 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1479 assert(N == 1 && "Invalid number of operands!");
1480 assert(
1481 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001482 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001483 }
1484
1485 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1486 assert(N == 1 && "Invalid number of operands!");
1487 assert(
1488 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001489 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001490 }
1491
1492 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1493 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001494 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001495 }
1496
Sander de Smalen525e3222018-04-12 13:19:32 +00001497 enum VecListIndexType {
1498 VecListIdx_DReg = 0,
1499 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001500 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001501 };
1502
1503 template <VecListIndexType RegTy, unsigned NumRegs>
1504 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001505 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001506 static const unsigned FirstRegs[][5] = {
1507 /* DReg */ { AArch64::Q0,
1508 AArch64::D0, AArch64::D0_D1,
1509 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1510 /* QReg */ { AArch64::Q0,
1511 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001512 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1513 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001514 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001515 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001516 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001517
Sander de Smalen7a210db2018-04-16 10:46:18 +00001518 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1519 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001520
Sander de Smalen525e3222018-04-12 13:19:32 +00001521 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1522 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1523 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001524 }
1525
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001526 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001527 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001528 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001529 }
1530
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001531 template <unsigned ImmIs0, unsigned ImmIs1>
1532 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1533 assert(N == 1 && "Invalid number of operands!");
1534 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1535 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1536 }
1537
Tim Northover3b0846e2014-05-24 12:50:23 +00001538 void addImmOperands(MCInst &Inst, unsigned N) const {
1539 assert(N == 1 && "Invalid number of operands!");
1540 // If this is a pageoff symrefexpr with an addend, adjust the addend
1541 // to be only the page-offset portion. Otherwise, just add the expr
1542 // as-is.
1543 addExpr(Inst, getImm());
1544 }
1545
Sander de Smalen62770792018-05-25 09:47:52 +00001546 template <int Shift>
1547 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001548 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001549 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1550 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1551 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1552 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001553 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001554 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001555 } else {
1556 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001557 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001558 }
1559 }
1560
Sander de Smalen62770792018-05-25 09:47:52 +00001561 template <int Shift>
1562 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001563 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001564 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1565 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1566 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1567 } else
1568 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001569 }
1570
Tim Northover3b0846e2014-05-24 12:50:23 +00001571 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1572 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001573 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001574 }
1575
1576 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1577 assert(N == 1 && "Invalid number of operands!");
1578 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1579 if (!MCE)
1580 addExpr(Inst, getImm());
1581 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001582 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001583 }
1584
1585 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1586 addImmOperands(Inst, N);
1587 }
1588
1589 template<int Scale>
1590 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1591 assert(N == 1 && "Invalid number of operands!");
1592 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1593
1594 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001595 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001596 return;
1597 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001598 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001599 }
1600
Sjoerd Meijera3dad802018-07-06 12:32:33 +00001601 void addUImm6Operands(MCInst &Inst, unsigned N) const {
1602 assert(N == 1 && "Invalid number of operands!");
1603 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1604 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1605 }
1606
Sander de Smalen5c625982018-04-13 12:56:14 +00001607 template <int Scale>
1608 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1609 assert(N == 1 && "Invalid number of operands!");
1610 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1611 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1612 }
1613
Sander de Smalena1c259c2018-01-29 13:05:38 +00001614 template <typename T>
1615 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001616 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001617 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001618 typename std::make_unsigned<T>::type Val = MCE->getValue();
1619 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001620 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001621 }
1622
Sander de Smalena1c259c2018-01-29 13:05:38 +00001623 template <typename T>
1624 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001625 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001626 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001627 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1628 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001629 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001630 }
1631
Tim Northover3b0846e2014-05-24 12:50:23 +00001632 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1633 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001634 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001635 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001636 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001637 }
1638
1639 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1640 // Branch operands don't encode the low bits, so shift them off
1641 // here. If it's a label, however, just put it on directly as there's
1642 // not enough information now to do anything.
1643 assert(N == 1 && "Invalid number of operands!");
1644 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1645 if (!MCE) {
1646 addExpr(Inst, getImm());
1647 return;
1648 }
1649 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001650 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001651 }
1652
1653 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1654 // Branch operands don't encode the low bits, so shift them off
1655 // here. If it's a label, however, just put it on directly as there's
1656 // not enough information now to do anything.
1657 assert(N == 1 && "Invalid number of operands!");
1658 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1659 if (!MCE) {
1660 addExpr(Inst, getImm());
1661 return;
1662 }
1663 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001664 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001665 }
1666
1667 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1668 // Branch operands don't encode the low bits, so shift them off
1669 // here. If it's a label, however, just put it on directly as there's
1670 // not enough information now to do anything.
1671 assert(N == 1 && "Invalid number of operands!");
1672 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1673 if (!MCE) {
1674 addExpr(Inst, getImm());
1675 return;
1676 }
1677 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001678 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001679 }
1680
1681 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1682 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001683 Inst.addOperand(MCOperand::createImm(
1684 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
Tim Northover3b0846e2014-05-24 12:50:23 +00001685 }
1686
1687 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1688 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001689 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001690 }
1691
1692 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1693 assert(N == 1 && "Invalid number of operands!");
1694
Jim Grosbache9119e42015-05-13 18:37:00 +00001695 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001696 }
1697
1698 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1699 assert(N == 1 && "Invalid number of operands!");
1700
Jim Grosbache9119e42015-05-13 18:37:00 +00001701 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001702 }
1703
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001704 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1705 assert(N == 1 && "Invalid number of operands!");
1706
1707 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1708 }
1709
1710 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001711 assert(N == 1 && "Invalid number of operands!");
1712
Jim Grosbache9119e42015-05-13 18:37:00 +00001713 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001714 }
1715
1716 void addSysCROperands(MCInst &Inst, unsigned N) const {
1717 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001718 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001719 }
1720
1721 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1722 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001723 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001724 }
1725
Oliver Stannarda34e4702015-12-01 10:48:51 +00001726 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1727 assert(N == 1 && "Invalid number of operands!");
1728 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1729 }
1730
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001731 void addBTIHintOperands(MCInst &Inst, unsigned N) const {
1732 assert(N == 1 && "Invalid number of operands!");
1733 Inst.addOperand(MCOperand::createImm(getBTIHint()));
1734 }
1735
Tim Northover3b0846e2014-05-24 12:50:23 +00001736 void addShifterOperands(MCInst &Inst, unsigned N) const {
1737 assert(N == 1 && "Invalid number of operands!");
1738 unsigned Imm =
1739 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001740 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001741 }
1742
1743 void addExtendOperands(MCInst &Inst, unsigned N) const {
1744 assert(N == 1 && "Invalid number of operands!");
1745 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1746 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1747 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001748 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001749 }
1750
1751 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1752 assert(N == 1 && "Invalid number of operands!");
1753 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1754 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1755 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001756 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001757 }
1758
1759 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1760 assert(N == 2 && "Invalid number of operands!");
1761 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1762 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001763 Inst.addOperand(MCOperand::createImm(IsSigned));
1764 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001765 }
1766
1767 // For 8-bit load/store instructions with a register offset, both the
1768 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1769 // they're disambiguated by whether the shift was explicit or implicit rather
1770 // than its size.
1771 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1772 assert(N == 2 && "Invalid number of operands!");
1773 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1774 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001775 Inst.addOperand(MCOperand::createImm(IsSigned));
1776 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001777 }
1778
1779 template<int Shift>
1780 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1781 assert(N == 1 && "Invalid number of operands!");
1782
1783 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1784 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001785 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001786 }
1787
1788 template<int Shift>
1789 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1790 assert(N == 1 && "Invalid number of operands!");
1791
1792 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1793 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001794 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001795 }
1796
Sam Parker5f934642017-08-31 09:27:04 +00001797 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1798 assert(N == 1 && "Invalid number of operands!");
1799 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1800 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1801 }
1802
1803 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1804 assert(N == 1 && "Invalid number of operands!");
1805 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1806 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1807 }
1808
Tim Northover3b0846e2014-05-24 12:50:23 +00001809 void print(raw_ostream &OS) const override;
1810
David Blaikie960ea3f2014-06-08 16:18:35 +00001811 static std::unique_ptr<AArch64Operand>
1812 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1813 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001814 Op->Tok.Data = Str.data();
1815 Op->Tok.Length = Str.size();
1816 Op->Tok.IsSuffix = IsSuffix;
1817 Op->StartLoc = S;
1818 Op->EndLoc = S;
1819 return Op;
1820 }
1821
David Blaikie960ea3f2014-06-08 16:18:35 +00001822 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001823 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
Sander de Smalen0325e302018-07-02 07:34:52 +00001824 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
Sander de Smalen149916d2018-04-20 07:24:20 +00001825 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1826 unsigned ShiftAmount = 0,
1827 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001828 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001829 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001830 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001831 Op->Reg.ElementWidth = 0;
Sander de Smalen0325e302018-07-02 07:34:52 +00001832 Op->Reg.EqualityTy = EqTy;
Sander de Smalen149916d2018-04-20 07:24:20 +00001833 Op->Reg.ShiftExtend.Type = ExtTy;
1834 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1835 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001836 Op->StartLoc = S;
1837 Op->EndLoc = E;
1838 return Op;
1839 }
1840
David Blaikie960ea3f2014-06-08 16:18:35 +00001841 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001842 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001843 SMLoc S, SMLoc E, MCContext &Ctx,
1844 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1845 unsigned ShiftAmount = 0,
1846 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001847 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1848 Kind == RegKind::SVEPredicateVector) &&
1849 "Invalid vector kind");
Sander de Smalen0325e302018-07-02 07:34:52 +00001850 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
Sander de Smalen149916d2018-04-20 07:24:20 +00001851 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001852 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001853 return Op;
1854 }
1855
1856 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001857 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001858 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1859 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001860 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001861 Op->VectorList.RegNum = RegNum;
1862 Op->VectorList.Count = Count;
1863 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001864 Op->VectorList.ElementWidth = ElementWidth;
1865 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001866 Op->StartLoc = S;
1867 Op->EndLoc = E;
1868 return Op;
1869 }
1870
David Blaikie960ea3f2014-06-08 16:18:35 +00001871 static std::unique_ptr<AArch64Operand>
1872 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1873 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001874 Op->VectorIndex.Val = Idx;
1875 Op->StartLoc = S;
1876 Op->EndLoc = E;
1877 return Op;
1878 }
1879
David Blaikie960ea3f2014-06-08 16:18:35 +00001880 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1881 SMLoc E, MCContext &Ctx) {
1882 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001883 Op->Imm.Val = Val;
1884 Op->StartLoc = S;
1885 Op->EndLoc = E;
1886 return Op;
1887 }
1888
David Blaikie960ea3f2014-06-08 16:18:35 +00001889 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1890 unsigned ShiftAmount,
1891 SMLoc S, SMLoc E,
1892 MCContext &Ctx) {
1893 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001894 Op->ShiftedImm .Val = Val;
1895 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1896 Op->StartLoc = S;
1897 Op->EndLoc = E;
1898 return Op;
1899 }
1900
David Blaikie960ea3f2014-06-08 16:18:35 +00001901 static std::unique_ptr<AArch64Operand>
1902 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1903 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001904 Op->CondCode.Code = Code;
1905 Op->StartLoc = S;
1906 Op->EndLoc = E;
1907 return Op;
1908 }
1909
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001910 static std::unique_ptr<AArch64Operand>
1911 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001912 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001913 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
1914 Op->FPImm.IsExact = IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +00001915 Op->StartLoc = S;
1916 Op->EndLoc = S;
1917 return Op;
1918 }
1919
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001920 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1921 StringRef Str,
1922 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001923 MCContext &Ctx) {
1924 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001925 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001926 Op->Barrier.Data = Str.data();
1927 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001928 Op->StartLoc = S;
1929 Op->EndLoc = S;
1930 return Op;
1931 }
1932
Tim Northover7cd58932015-01-22 17:23:04 +00001933 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1934 uint32_t MRSReg,
1935 uint32_t MSRReg,
1936 uint32_t PStateField,
1937 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001938 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001939 Op->SysReg.Data = Str.data();
1940 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001941 Op->SysReg.MRSReg = MRSReg;
1942 Op->SysReg.MSRReg = MSRReg;
1943 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001944 Op->StartLoc = S;
1945 Op->EndLoc = S;
1946 return Op;
1947 }
1948
David Blaikie960ea3f2014-06-08 16:18:35 +00001949 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1950 SMLoc E, MCContext &Ctx) {
1951 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001952 Op->SysCRImm.Val = Val;
1953 Op->StartLoc = S;
1954 Op->EndLoc = E;
1955 return Op;
1956 }
1957
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001958 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1959 StringRef Str,
1960 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001961 MCContext &Ctx) {
1962 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001963 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001964 Op->Barrier.Data = Str.data();
1965 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001966 Op->StartLoc = S;
1967 Op->EndLoc = S;
1968 return Op;
1969 }
1970
Oliver Stannarda34e4702015-12-01 10:48:51 +00001971 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1972 StringRef Str,
1973 SMLoc S,
1974 MCContext &Ctx) {
1975 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1976 Op->PSBHint.Val = Val;
1977 Op->PSBHint.Data = Str.data();
1978 Op->PSBHint.Length = Str.size();
1979 Op->StartLoc = S;
1980 Op->EndLoc = S;
1981 return Op;
1982 }
1983
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001984 static std::unique_ptr<AArch64Operand> CreateBTIHint(unsigned Val,
1985 StringRef Str,
1986 SMLoc S,
1987 MCContext &Ctx) {
1988 auto Op = make_unique<AArch64Operand>(k_BTIHint, Ctx);
1989 Op->BTIHint.Val = Val << 1 | 32;
1990 Op->BTIHint.Data = Str.data();
1991 Op->BTIHint.Length = Str.size();
1992 Op->StartLoc = S;
1993 Op->EndLoc = S;
1994 return Op;
1995 }
1996
David Blaikie960ea3f2014-06-08 16:18:35 +00001997 static std::unique_ptr<AArch64Operand>
1998 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1999 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
2000 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00002001 Op->ShiftExtend.Type = ShOp;
2002 Op->ShiftExtend.Amount = Val;
2003 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
2004 Op->StartLoc = S;
2005 Op->EndLoc = E;
2006 return Op;
2007 }
2008};
2009
2010} // end anonymous namespace.
2011
2012void AArch64Operand::print(raw_ostream &OS) const {
2013 switch (Kind) {
2014 case k_FPImm:
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002015 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
2016 if (!getFPImmIsExact())
2017 OS << " (inexact)";
2018 OS << ">";
Tim Northover3b0846e2014-05-24 12:50:23 +00002019 break;
2020 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00002021 StringRef Name = getBarrierName();
2022 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00002023 OS << "<barrier " << Name << ">";
2024 else
2025 OS << "<barrier invalid #" << getBarrier() << ">";
2026 break;
2027 }
2028 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00002029 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00002030 break;
2031 case k_ShiftedImm: {
2032 unsigned Shift = getShiftedImmShift();
2033 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00002034 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00002035 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
2036 break;
2037 }
2038 case k_CondCode:
2039 OS << "<condcode " << getCondCode() << ">";
2040 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00002041 case k_VectorList: {
2042 OS << "<vectorlist ";
2043 unsigned Reg = getVectorListStart();
2044 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
2045 OS << Reg + i << " ";
2046 OS << ">";
2047 break;
2048 }
2049 case k_VectorIndex:
2050 OS << "<vectorindex " << getVectorIndex() << ">";
2051 break;
2052 case k_SysReg:
2053 OS << "<sysreg: " << getSysReg() << '>';
2054 break;
2055 case k_Token:
2056 OS << "'" << getToken() << "'";
2057 break;
2058 case k_SysCR:
2059 OS << "c" << getSysCR();
2060 break;
2061 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00002062 StringRef Name = getPrefetchName();
2063 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00002064 OS << "<prfop " << Name << ">";
2065 else
2066 OS << "<prfop invalid #" << getPrefetch() << ">";
2067 break;
2068 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00002069 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00002070 OS << getPSBHintName();
2071 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00002072 case k_Register:
2073 OS << "<register " << getReg() << ">";
2074 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
2075 break;
2076 LLVM_FALLTHROUGH;
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00002077 case k_BTIHint:
2078 OS << getBTIHintName();
2079 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00002080 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00002081 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
2082 << getShiftExtendAmount();
2083 if (!hasShiftExtendAmount())
2084 OS << "<imp>";
2085 OS << '>';
2086 break;
2087 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002088}
2089
2090/// @name Auto-generated Match Functions
2091/// {
2092
2093static unsigned MatchRegisterName(StringRef Name);
2094
2095/// }
2096
Florian Hahnc4422242017-11-07 13:07:50 +00002097static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00002098 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00002099 .Case("v0", AArch64::Q0)
2100 .Case("v1", AArch64::Q1)
2101 .Case("v2", AArch64::Q2)
2102 .Case("v3", AArch64::Q3)
2103 .Case("v4", AArch64::Q4)
2104 .Case("v5", AArch64::Q5)
2105 .Case("v6", AArch64::Q6)
2106 .Case("v7", AArch64::Q7)
2107 .Case("v8", AArch64::Q8)
2108 .Case("v9", AArch64::Q9)
2109 .Case("v10", AArch64::Q10)
2110 .Case("v11", AArch64::Q11)
2111 .Case("v12", AArch64::Q12)
2112 .Case("v13", AArch64::Q13)
2113 .Case("v14", AArch64::Q14)
2114 .Case("v15", AArch64::Q15)
2115 .Case("v16", AArch64::Q16)
2116 .Case("v17", AArch64::Q17)
2117 .Case("v18", AArch64::Q18)
2118 .Case("v19", AArch64::Q19)
2119 .Case("v20", AArch64::Q20)
2120 .Case("v21", AArch64::Q21)
2121 .Case("v22", AArch64::Q22)
2122 .Case("v23", AArch64::Q23)
2123 .Case("v24", AArch64::Q24)
2124 .Case("v25", AArch64::Q25)
2125 .Case("v26", AArch64::Q26)
2126 .Case("v27", AArch64::Q27)
2127 .Case("v28", AArch64::Q28)
2128 .Case("v29", AArch64::Q29)
2129 .Case("v30", AArch64::Q30)
2130 .Case("v31", AArch64::Q31)
2131 .Default(0);
2132}
2133
Sander de Smalen73937b72018-04-11 07:36:10 +00002134/// Returns an optional pair of (#elements, element-width) if Suffix
2135/// is a valid vector kind. Where the number of elements in a vector
2136/// or the vector width is implicit or explicitly unknown (but still a
2137/// valid suffix kind), 0 is used.
2138static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2139 RegKind VectorKind) {
2140 std::pair<int, int> Res = {-1, -1};
2141
2142 switch (VectorKind) {
2143 case RegKind::NeonVector:
2144 Res =
2145 StringSwitch<std::pair<int, int>>(Suffix.lower())
2146 .Case("", {0, 0})
2147 .Case(".1d", {1, 64})
2148 .Case(".1q", {1, 128})
2149 // '.2h' needed for fp16 scalar pairwise reductions
2150 .Case(".2h", {2, 16})
2151 .Case(".2s", {2, 32})
2152 .Case(".2d", {2, 64})
2153 // '.4b' is another special case for the ARMv8.2a dot product
2154 // operand
2155 .Case(".4b", {4, 8})
2156 .Case(".4h", {4, 16})
2157 .Case(".4s", {4, 32})
2158 .Case(".8b", {8, 8})
2159 .Case(".8h", {8, 16})
2160 .Case(".16b", {16, 8})
2161 // Accept the width neutral ones, too, for verbose syntax. If those
2162 // aren't used in the right places, the token operand won't match so
2163 // all will work out.
2164 .Case(".b", {0, 8})
2165 .Case(".h", {0, 16})
2166 .Case(".s", {0, 32})
2167 .Case(".d", {0, 64})
2168 .Default({-1, -1});
2169 break;
2170 case RegKind::SVEPredicateVector:
2171 case RegKind::SVEDataVector:
2172 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2173 .Case("", {0, 0})
2174 .Case(".b", {0, 8})
2175 .Case(".h", {0, 16})
2176 .Case(".s", {0, 32})
2177 .Case(".d", {0, 64})
2178 .Case(".q", {0, 128})
2179 .Default({-1, -1});
2180 break;
2181 default:
2182 llvm_unreachable("Unsupported RegKind");
2183 }
2184
2185 if (Res == std::make_pair(-1, -1))
2186 return Optional<std::pair<int, int>>();
2187
2188 return Optional<std::pair<int, int>>(Res);
2189}
2190
2191static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2192 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002193}
2194
Florian Hahn91f11e52017-11-07 16:45:48 +00002195static unsigned matchSVEDataVectorRegName(StringRef Name) {
2196 return StringSwitch<unsigned>(Name.lower())
2197 .Case("z0", AArch64::Z0)
2198 .Case("z1", AArch64::Z1)
2199 .Case("z2", AArch64::Z2)
2200 .Case("z3", AArch64::Z3)
2201 .Case("z4", AArch64::Z4)
2202 .Case("z5", AArch64::Z5)
2203 .Case("z6", AArch64::Z6)
2204 .Case("z7", AArch64::Z7)
2205 .Case("z8", AArch64::Z8)
2206 .Case("z9", AArch64::Z9)
2207 .Case("z10", AArch64::Z10)
2208 .Case("z11", AArch64::Z11)
2209 .Case("z12", AArch64::Z12)
2210 .Case("z13", AArch64::Z13)
2211 .Case("z14", AArch64::Z14)
2212 .Case("z15", AArch64::Z15)
2213 .Case("z16", AArch64::Z16)
2214 .Case("z17", AArch64::Z17)
2215 .Case("z18", AArch64::Z18)
2216 .Case("z19", AArch64::Z19)
2217 .Case("z20", AArch64::Z20)
2218 .Case("z21", AArch64::Z21)
2219 .Case("z22", AArch64::Z22)
2220 .Case("z23", AArch64::Z23)
2221 .Case("z24", AArch64::Z24)
2222 .Case("z25", AArch64::Z25)
2223 .Case("z26", AArch64::Z26)
2224 .Case("z27", AArch64::Z27)
2225 .Case("z28", AArch64::Z28)
2226 .Case("z29", AArch64::Z29)
2227 .Case("z30", AArch64::Z30)
2228 .Case("z31", AArch64::Z31)
2229 .Default(0);
2230}
2231
Sander de Smalencd6be962017-12-20 11:02:42 +00002232static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2233 return StringSwitch<unsigned>(Name.lower())
2234 .Case("p0", AArch64::P0)
2235 .Case("p1", AArch64::P1)
2236 .Case("p2", AArch64::P2)
2237 .Case("p3", AArch64::P3)
2238 .Case("p4", AArch64::P4)
2239 .Case("p5", AArch64::P5)
2240 .Case("p6", AArch64::P6)
2241 .Case("p7", AArch64::P7)
2242 .Case("p8", AArch64::P8)
2243 .Case("p9", AArch64::P9)
2244 .Case("p10", AArch64::P10)
2245 .Case("p11", AArch64::P11)
2246 .Case("p12", AArch64::P12)
2247 .Case("p13", AArch64::P13)
2248 .Case("p14", AArch64::P14)
2249 .Case("p15", AArch64::P15)
2250 .Default(0);
2251}
2252
Tim Northover3b0846e2014-05-24 12:50:23 +00002253bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2254 SMLoc &EndLoc) {
2255 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002256 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002257 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002258 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002259}
2260
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002261// Matches a register name or register alias previously defined by '.req'
2262unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002263 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002264 unsigned RegNum = 0;
2265 if ((RegNum = matchSVEDataVectorRegName(Name)))
2266 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2267
Sander de Smalencd6be962017-12-20 11:02:42 +00002268 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2269 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2270
Sander de Smalenc067c302017-12-20 09:45:45 +00002271 if ((RegNum = MatchNeonVectorRegName(Name)))
2272 return Kind == RegKind::NeonVector ? RegNum : 0;
2273
2274 // The parsed register must be of RegKind Scalar
2275 if ((RegNum = MatchRegisterName(Name)))
2276 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002277
Florian Hahnc4422242017-11-07 13:07:50 +00002278 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002279 // Handle a few common aliases of registers.
2280 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2281 .Case("fp", AArch64::FP)
2282 .Case("lr", AArch64::LR)
2283 .Case("x31", AArch64::XZR)
2284 .Case("w31", AArch64::WZR)
2285 .Default(0))
2286 return Kind == RegKind::Scalar ? RegNum : 0;
2287
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002288 // Check for aliases registered via .req. Canonicalize to lower case.
2289 // That's more consistent since register names are case insensitive, and
2290 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2291 auto Entry = RegisterReqs.find(Name.lower());
2292 if (Entry == RegisterReqs.end())
2293 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002294
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002295 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002296 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002297 RegNum = Entry->getValue().second;
2298 }
2299 return RegNum;
2300}
2301
Sander de Smalen50d87022018-04-19 07:35:08 +00002302/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002303/// Identifier when called, and if it is a register name the token is eaten and
2304/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002305OperandMatchResultTy
2306AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002307 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002308 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002309 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002310 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002311
2312 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002313 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2314 if (Reg == 0)
2315 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002316
Sander de Smalen50d87022018-04-19 07:35:08 +00002317 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002318 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002319 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002320}
2321
Tim Northover3b0846e2014-05-24 12:50:23 +00002322/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002323OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002324AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002325 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002326 SMLoc S = getLoc();
2327
2328 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2329 Error(S, "Expected cN operand where 0 <= N <= 15");
2330 return MatchOperand_ParseFail;
2331 }
2332
2333 StringRef Tok = Parser.getTok().getIdentifier();
2334 if (Tok[0] != 'c' && Tok[0] != 'C') {
2335 Error(S, "Expected cN operand where 0 <= N <= 15");
2336 return MatchOperand_ParseFail;
2337 }
2338
2339 uint32_t CRNum;
2340 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2341 if (BadNum || CRNum > 15) {
2342 Error(S, "Expected cN operand where 0 <= N <= 15");
2343 return MatchOperand_ParseFail;
2344 }
2345
2346 Parser.Lex(); // Eat identifier token.
2347 Operands.push_back(
2348 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2349 return MatchOperand_Success;
2350}
2351
2352/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002353template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002354OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002355AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002356 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002357 SMLoc S = getLoc();
2358 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002359
2360 auto LookupByName = [](StringRef N) {
2361 if (IsSVEPrefetch) {
2362 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2363 return Optional<unsigned>(Res->Encoding);
2364 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2365 return Optional<unsigned>(Res->Encoding);
2366 return Optional<unsigned>();
2367 };
2368
2369 auto LookupByEncoding = [](unsigned E) {
2370 if (IsSVEPrefetch) {
2371 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2372 return Optional<StringRef>(Res->Name);
2373 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2374 return Optional<StringRef>(Res->Name);
2375 return Optional<StringRef>();
2376 };
2377 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2378
Tim Northover3b0846e2014-05-24 12:50:23 +00002379 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002380 // Eat optional hash.
2381 if (parseOptionalToken(AsmToken::Hash) ||
2382 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002383 const MCExpr *ImmVal;
2384 if (getParser().parseExpression(ImmVal))
2385 return MatchOperand_ParseFail;
2386
2387 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2388 if (!MCE) {
2389 TokError("immediate value expected for prefetch operand");
2390 return MatchOperand_ParseFail;
2391 }
2392 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002393 if (prfop > MaxVal) {
2394 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2395 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002396 return MatchOperand_ParseFail;
2397 }
2398
Sander de Smalen93380372018-05-14 11:54:41 +00002399 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002400 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002401 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002402 return MatchOperand_Success;
2403 }
2404
2405 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002406 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002407 return MatchOperand_ParseFail;
2408 }
2409
Sander de Smalen93380372018-05-14 11:54:41 +00002410 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002411 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002412 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002413 return MatchOperand_ParseFail;
2414 }
2415
2416 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002417 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002418 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002419 return MatchOperand_Success;
2420}
2421
Oliver Stannarda34e4702015-12-01 10:48:51 +00002422/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002423OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002424AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2425 MCAsmParser &Parser = getParser();
2426 SMLoc S = getLoc();
2427 const AsmToken &Tok = Parser.getTok();
2428 if (Tok.isNot(AsmToken::Identifier)) {
2429 TokError("invalid operand for instruction");
2430 return MatchOperand_ParseFail;
2431 }
2432
Tim Northovere6ae6762016-07-05 21:23:04 +00002433 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2434 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002435 TokError("invalid operand for instruction");
2436 return MatchOperand_ParseFail;
2437 }
2438
2439 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002440 Operands.push_back(AArch64Operand::CreatePSBHint(
2441 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002442 return MatchOperand_Success;
2443}
2444
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00002445/// tryParseBTIHint - Try to parse a BTI operand, mapped to Hint command
2446OperandMatchResultTy
2447AArch64AsmParser::tryParseBTIHint(OperandVector &Operands) {
2448 MCAsmParser &Parser = getParser();
2449 SMLoc S = getLoc();
2450 const AsmToken &Tok = Parser.getTok();
2451 if (Tok.isNot(AsmToken::Identifier)) {
2452 TokError("invalid operand for instruction");
2453 return MatchOperand_ParseFail;
2454 }
2455
2456 auto BTI = AArch64BTIHint::lookupBTIByName(Tok.getString());
2457 if (!BTI) {
2458 TokError("invalid operand for instruction");
2459 return MatchOperand_ParseFail;
2460 }
2461
2462 Parser.Lex(); // Eat identifier token.
2463 Operands.push_back(AArch64Operand::CreateBTIHint(
2464 BTI->Encoding, Tok.getString(), S, getContext()));
2465 return MatchOperand_Success;
2466}
2467
Tim Northover3b0846e2014-05-24 12:50:23 +00002468/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2469/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002470OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002471AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002472 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002473 SMLoc S = getLoc();
2474 const MCExpr *Expr;
2475
2476 if (Parser.getTok().is(AsmToken::Hash)) {
2477 Parser.Lex(); // Eat hash token.
2478 }
2479
2480 if (parseSymbolicImmVal(Expr))
2481 return MatchOperand_ParseFail;
2482
2483 AArch64MCExpr::VariantKind ELFRefKind;
2484 MCSymbolRefExpr::VariantKind DarwinRefKind;
2485 int64_t Addend;
2486 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2487 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2488 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2489 // No modifier was specified at all; this is the syntax for an ELF basic
2490 // ADRP relocation (unfortunately).
2491 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002492 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002493 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2494 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2495 Addend != 0) {
2496 Error(S, "gotpage label reference not allowed an addend");
2497 return MatchOperand_ParseFail;
2498 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2499 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2500 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2501 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2502 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2503 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2504 // The operand must be an @page or @gotpage qualified symbolref.
2505 Error(S, "page or gotpage label reference expected");
2506 return MatchOperand_ParseFail;
2507 }
2508 }
2509
2510 // We have either a label reference possibly with addend or an immediate. The
2511 // addend is a raw value here. The linker will adjust it to only reference the
2512 // page.
2513 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2514 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2515
2516 return MatchOperand_Success;
2517}
2518
2519/// tryParseAdrLabel - Parse and validate a source label for the ADR
2520/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002521OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002522AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2523 SMLoc S = getLoc();
2524 const MCExpr *Expr;
2525
David Green9dd1d452018-08-22 11:31:39 +00002526 // Leave anything with a bracket to the default for SVE
2527 if (getParser().getTok().is(AsmToken::LBrac))
2528 return MatchOperand_NoMatch;
2529
2530 if (getParser().getTok().is(AsmToken::Hash))
2531 getParser().Lex(); // Eat hash token.
2532
2533 if (parseSymbolicImmVal(Expr))
2534 return MatchOperand_ParseFail;
2535
2536 AArch64MCExpr::VariantKind ELFRefKind;
2537 MCSymbolRefExpr::VariantKind DarwinRefKind;
2538 int64_t Addend;
2539 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2540 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2541 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2542 // No modifier was specified at all; this is the syntax for an ELF basic
2543 // ADR relocation (unfortunately).
2544 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS, getContext());
2545 } else {
2546 Error(S, "unexpected adr label");
Sander de Smalenc69944c2018-07-09 09:58:24 +00002547 return MatchOperand_ParseFail;
David Green9dd1d452018-08-22 11:31:39 +00002548 }
Sander de Smalenc69944c2018-07-09 09:58:24 +00002549 }
David Green9dd1d452018-08-22 11:31:39 +00002550
2551 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2552 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2553 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002554}
2555
2556/// tryParseFPImm - A floating point immediate expression operand.
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002557template<bool AddFPZeroAsLiteral>
Alex Bradbury58eba092016-11-01 16:32:05 +00002558OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002559AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002560 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002561 SMLoc S = getLoc();
2562
Nirav Davee833c6c2016-11-08 18:31:04 +00002563 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002564
2565 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002566 bool isNegative = parseOptionalToken(AsmToken::Minus);
2567
Tim Northover3b0846e2014-05-24 12:50:23 +00002568 const AsmToken &Tok = Parser.getTok();
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002569 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2570 if (!Hash)
2571 return MatchOperand_NoMatch;
2572 TokError("invalid floating point immediate");
2573 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002574 }
2575
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002576 // Parse hexadecimal representation.
2577 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2578 if (Tok.getIntVal() > 255 || isNegative) {
2579 TokError("encoded floating point value out of range");
2580 return MatchOperand_ParseFail;
2581 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002582
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002583 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2584 Operands.push_back(
2585 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2586 } else {
2587 // Parse FP representation.
2588 APFloat RealVal(APFloat::IEEEdouble());
2589 auto Status =
2590 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2591 if (isNegative)
2592 RealVal.changeSign();
2593
2594 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2595 Operands.push_back(
2596 AArch64Operand::CreateToken("#0", false, S, getContext()));
2597 Operands.push_back(
2598 AArch64Operand::CreateToken(".0", false, S, getContext()));
2599 } else
2600 Operands.push_back(AArch64Operand::CreateFPImm(
2601 RealVal, Status == APFloat::opOK, S, getContext()));
2602 }
2603
2604 Parser.Lex(); // Eat the token.
2605
2606 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002607}
2608
Sander de Smalen62770792018-05-25 09:47:52 +00002609/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2610/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002611OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002612AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002613 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002614 SMLoc S = getLoc();
2615
2616 if (Parser.getTok().is(AsmToken::Hash))
2617 Parser.Lex(); // Eat '#'
2618 else if (Parser.getTok().isNot(AsmToken::Integer))
2619 // Operand should start from # or should be integer, emit error otherwise.
2620 return MatchOperand_NoMatch;
2621
2622 const MCExpr *Imm;
2623 if (parseSymbolicImmVal(Imm))
2624 return MatchOperand_ParseFail;
2625 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002626 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002627 Operands.push_back(
2628 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002629 return MatchOperand_Success;
2630 }
2631
2632 // Eat ','
2633 Parser.Lex();
2634
2635 // The optional operand must be "lsl #N" where N is non-negative.
2636 if (!Parser.getTok().is(AsmToken::Identifier) ||
2637 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2638 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2639 return MatchOperand_ParseFail;
2640 }
2641
2642 // Eat 'lsl'
2643 Parser.Lex();
2644
Nirav Davee833c6c2016-11-08 18:31:04 +00002645 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002646
2647 if (Parser.getTok().isNot(AsmToken::Integer)) {
2648 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2649 return MatchOperand_ParseFail;
2650 }
2651
2652 int64_t ShiftAmount = Parser.getTok().getIntVal();
2653
2654 if (ShiftAmount < 0) {
2655 Error(Parser.getTok().getLoc(), "positive shift amount required");
2656 return MatchOperand_ParseFail;
2657 }
2658 Parser.Lex(); // Eat the number
2659
Sander de Smalen62770792018-05-25 09:47:52 +00002660 // Just in case the optional lsl #0 is used for immediates other than zero.
2661 if (ShiftAmount == 0 && Imm != 0) {
2662 SMLoc E = Parser.getTok().getLoc();
2663 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2664 return MatchOperand_Success;
2665 }
2666
Tim Northover3b0846e2014-05-24 12:50:23 +00002667 SMLoc E = Parser.getTok().getLoc();
2668 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2669 S, E, getContext()));
2670 return MatchOperand_Success;
2671}
2672
2673/// parseCondCodeString - Parse a Condition Code string.
2674AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2675 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2676 .Case("eq", AArch64CC::EQ)
2677 .Case("ne", AArch64CC::NE)
2678 .Case("cs", AArch64CC::HS)
2679 .Case("hs", AArch64CC::HS)
2680 .Case("cc", AArch64CC::LO)
2681 .Case("lo", AArch64CC::LO)
2682 .Case("mi", AArch64CC::MI)
2683 .Case("pl", AArch64CC::PL)
2684 .Case("vs", AArch64CC::VS)
2685 .Case("vc", AArch64CC::VC)
2686 .Case("hi", AArch64CC::HI)
2687 .Case("ls", AArch64CC::LS)
2688 .Case("ge", AArch64CC::GE)
2689 .Case("lt", AArch64CC::LT)
2690 .Case("gt", AArch64CC::GT)
2691 .Case("le", AArch64CC::LE)
2692 .Case("al", AArch64CC::AL)
2693 .Case("nv", AArch64CC::NV)
2694 .Default(AArch64CC::Invalid);
Sander de Smalene31e6d42018-07-04 08:50:49 +00002695
2696 if (CC == AArch64CC::Invalid &&
2697 getSTI().getFeatureBits()[AArch64::FeatureSVE])
2698 CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2699 .Case("none", AArch64CC::EQ)
2700 .Case("any", AArch64CC::NE)
2701 .Case("nlast", AArch64CC::HS)
2702 .Case("last", AArch64CC::LO)
2703 .Case("first", AArch64CC::MI)
2704 .Case("nfrst", AArch64CC::PL)
2705 .Case("pmore", AArch64CC::HI)
2706 .Case("plast", AArch64CC::LS)
2707 .Case("tcont", AArch64CC::GE)
2708 .Case("tstop", AArch64CC::LT)
2709 .Default(AArch64CC::Invalid);
2710
Tim Northover3b0846e2014-05-24 12:50:23 +00002711 return CC;
2712}
2713
2714/// parseCondCode - Parse a Condition Code operand.
2715bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2716 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002717 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002718 SMLoc S = getLoc();
2719 const AsmToken &Tok = Parser.getTok();
2720 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2721
2722 StringRef Cond = Tok.getString();
2723 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2724 if (CC == AArch64CC::Invalid)
2725 return TokError("invalid condition code");
2726 Parser.Lex(); // Eat identifier token.
2727
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002728 if (invertCondCode) {
2729 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2730 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002731 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002732 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002733
2734 Operands.push_back(
2735 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2736 return false;
2737}
2738
2739/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2740/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002741OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002742AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002743 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002744 const AsmToken &Tok = Parser.getTok();
2745 std::string LowerID = Tok.getString().lower();
2746 AArch64_AM::ShiftExtendType ShOp =
2747 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2748 .Case("lsl", AArch64_AM::LSL)
2749 .Case("lsr", AArch64_AM::LSR)
2750 .Case("asr", AArch64_AM::ASR)
2751 .Case("ror", AArch64_AM::ROR)
2752 .Case("msl", AArch64_AM::MSL)
2753 .Case("uxtb", AArch64_AM::UXTB)
2754 .Case("uxth", AArch64_AM::UXTH)
2755 .Case("uxtw", AArch64_AM::UXTW)
2756 .Case("uxtx", AArch64_AM::UXTX)
2757 .Case("sxtb", AArch64_AM::SXTB)
2758 .Case("sxth", AArch64_AM::SXTH)
2759 .Case("sxtw", AArch64_AM::SXTW)
2760 .Case("sxtx", AArch64_AM::SXTX)
2761 .Default(AArch64_AM::InvalidShiftExtend);
2762
2763 if (ShOp == AArch64_AM::InvalidShiftExtend)
2764 return MatchOperand_NoMatch;
2765
2766 SMLoc S = Tok.getLoc();
2767 Parser.Lex();
2768
Nirav Davee833c6c2016-11-08 18:31:04 +00002769 bool Hash = parseOptionalToken(AsmToken::Hash);
2770
Tim Northover3b0846e2014-05-24 12:50:23 +00002771 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2772 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2773 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2774 ShOp == AArch64_AM::MSL) {
2775 // We expect a number here.
2776 TokError("expected #imm after shift specifier");
2777 return MatchOperand_ParseFail;
2778 }
2779
Chad Rosier2ff37b82016-12-27 16:58:09 +00002780 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002781 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2782 Operands.push_back(
2783 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2784 return MatchOperand_Success;
2785 }
2786
Chad Rosier2ff37b82016-12-27 16:58:09 +00002787 // Make sure we do actually have a number, identifier or a parenthesized
2788 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002789 SMLoc E = Parser.getTok().getLoc();
2790 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002791 !Parser.getTok().is(AsmToken::LParen) &&
2792 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002793 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002794 return MatchOperand_ParseFail;
2795 }
2796
2797 const MCExpr *ImmVal;
2798 if (getParser().parseExpression(ImmVal))
2799 return MatchOperand_ParseFail;
2800
2801 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2802 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002803 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002804 return MatchOperand_ParseFail;
2805 }
2806
Jim Grosbach57fd2622014-09-23 22:16:02 +00002807 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002808 Operands.push_back(AArch64Operand::CreateShiftExtend(
2809 ShOp, MCE->getValue(), true, S, E, getContext()));
2810 return MatchOperand_Success;
2811}
2812
Oliver Stannard89b16042018-09-26 13:52:27 +00002813static const struct Extension {
2814 const char *Name;
2815 const FeatureBitset Features;
2816} ExtensionMap[] = {
Diogo N. Sampaio9c906732018-12-06 15:39:17 +00002817 {"crc", {AArch64::FeatureCRC}},
2818 {"sm4", {AArch64::FeatureSM4}},
2819 {"sha3", {AArch64::FeatureSHA3}},
2820 {"sha2", {AArch64::FeatureSHA2}},
2821 {"aes", {AArch64::FeatureAES}},
2822 {"crypto", {AArch64::FeatureCrypto}},
2823 {"fp", {AArch64::FeatureFPARMv8}},
2824 {"simd", {AArch64::FeatureNEON}},
2825 {"ras", {AArch64::FeatureRAS}},
2826 {"lse", {AArch64::FeatureLSE}},
2827 {"predctrl", {AArch64::FeaturePredCtrl}},
2828 {"ccdp", {AArch64::FeatureCacheDeepPersist}},
2829 {"mte", {AArch64::FeatureMTE}},
2830 {"tlb-rmi", {AArch64::FeatureTLB_RMI}},
2831 {"pan-rwv", {AArch64::FeaturePAN_RWV}},
2832 {"ccpp", {AArch64::FeatureCCPP}},
2833 // FIXME: Unsupported extensions
2834 {"pan", {}},
2835 {"lor", {}},
2836 {"rdma", {}},
2837 {"profile", {}},
Oliver Stannard89b16042018-09-26 13:52:27 +00002838};
2839
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002840static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2841 if (FBS[AArch64::HasV8_1aOps])
2842 Str += "ARMv8.1a";
2843 else if (FBS[AArch64::HasV8_2aOps])
2844 Str += "ARMv8.2a";
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002845 else if (FBS[AArch64::HasV8_3aOps])
2846 Str += "ARMv8.3a";
2847 else if (FBS[AArch64::HasV8_4aOps])
2848 Str += "ARMv8.4a";
Oliver Stannard89b16042018-09-26 13:52:27 +00002849 else if (FBS[AArch64::HasV8_5aOps])
2850 Str += "ARMv8.5a";
2851 else {
2852 auto ext = std::find_if(std::begin(ExtensionMap),
2853 std::end(ExtensionMap),
2854 [&](const Extension& e)
2855 // Use & in case multiple features are enabled
2856 { return (FBS & e.Features) != FeatureBitset(); }
2857 );
2858
2859 Str += ext != std::end(ExtensionMap) ? ext->Name : "(unknown)";
2860 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002861}
2862
2863void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2864 SMLoc S) {
2865 const uint16_t Op2 = Encoding & 7;
2866 const uint16_t Cm = (Encoding & 0x78) >> 3;
2867 const uint16_t Cn = (Encoding & 0x780) >> 7;
2868 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2869
2870 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2871
2872 Operands.push_back(
2873 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2874 Operands.push_back(
2875 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2876 Operands.push_back(
2877 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2878 Expr = MCConstantExpr::create(Op2, getContext());
2879 Operands.push_back(
2880 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2881}
2882
Tim Northover3b0846e2014-05-24 12:50:23 +00002883/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2884/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2885bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2886 OperandVector &Operands) {
2887 if (Name.find('.') != StringRef::npos)
2888 return TokError("invalid operand");
2889
2890 Mnemonic = Name;
2891 Operands.push_back(
2892 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2893
Rafael Espindola961d4692014-11-11 05:18:41 +00002894 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002895 const AsmToken &Tok = Parser.getTok();
2896 StringRef Op = Tok.getString();
2897 SMLoc S = Tok.getLoc();
2898
Tim Northover3b0846e2014-05-24 12:50:23 +00002899 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002900 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2901 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002902 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002903 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2904 std::string Str("IC " + std::string(IC->Name) + " requires ");
2905 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2906 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002907 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002908 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002909 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002910 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2911 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002912 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002913 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2914 std::string Str("DC " + std::string(DC->Name) + " requires ");
2915 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2916 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002917 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002918 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002919 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002920 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2921 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002922 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002923 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2924 std::string Str("AT " + std::string(AT->Name) + " requires ");
2925 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2926 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002927 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002928 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002929 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002930 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2931 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002932 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002933 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2934 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2935 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2936 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002937 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002938 createSysAlias(TLBI->Encoding, Operands, S);
Oliver Stannard224428c2018-09-27 13:47:40 +00002939 } else if (Mnemonic == "cfp" || Mnemonic == "dvp" || Mnemonic == "cpp") {
2940 const AArch64PRCTX::PRCTX *PRCTX = AArch64PRCTX::lookupPRCTXByName(Op);
2941 if (!PRCTX)
2942 return TokError("invalid operand for prediction restriction instruction");
2943 else if (!PRCTX->haveFeatures(getSTI().getFeatureBits())) {
2944 std::string Str(
2945 Mnemonic.upper() + std::string(PRCTX->Name) + " requires ");
2946 setRequiredFeatureString(PRCTX->getRequiredFeatures(), Str);
2947 return TokError(Str.c_str());
2948 }
2949 uint16_t PRCTX_Op2 =
2950 Mnemonic == "cfp" ? 4 :
2951 Mnemonic == "dvp" ? 5 :
2952 Mnemonic == "cpp" ? 7 :
2953 0;
2954 assert(PRCTX_Op2 && "Invalid mnemonic for prediction restriction instruction");
2955 createSysAlias(PRCTX->Encoding << 3 | PRCTX_Op2 , Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002956 }
2957
Tim Northover3b0846e2014-05-24 12:50:23 +00002958 Parser.Lex(); // Eat operand.
2959
2960 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2961 bool HasRegister = false;
2962
2963 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002964 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002965 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2966 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002967 HasRegister = true;
2968 }
2969
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002970 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002971 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002972 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002973 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002974
Nirav Davee833c6c2016-11-08 18:31:04 +00002975 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2976 return true;
2977
Tim Northover3b0846e2014-05-24 12:50:23 +00002978 return false;
2979}
2980
Alex Bradbury58eba092016-11-01 16:32:05 +00002981OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002982AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002983 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002984 const AsmToken &Tok = Parser.getTok();
2985
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002986 if (Mnemonic == "tsb" && Tok.isNot(AsmToken::Identifier)) {
2987 TokError("'csync' operand expected");
2988 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002989 // Can be either a #imm style literal or an option name
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002990 } else if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002991 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002992 const MCExpr *ImmVal;
2993 SMLoc ExprLoc = getLoc();
2994 if (getParser().parseExpression(ImmVal))
2995 return MatchOperand_ParseFail;
2996 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2997 if (!MCE) {
2998 Error(ExprLoc, "immediate value expected for barrier operand");
2999 return MatchOperand_ParseFail;
3000 }
3001 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
3002 Error(ExprLoc, "barrier operand out of range");
3003 return MatchOperand_ParseFail;
3004 }
Tim Northovere6ae6762016-07-05 21:23:04 +00003005 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
3006 Operands.push_back(AArch64Operand::CreateBarrier(
3007 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003008 return MatchOperand_Success;
3009 }
3010
3011 if (Tok.isNot(AsmToken::Identifier)) {
3012 TokError("invalid operand for instruction");
3013 return MatchOperand_ParseFail;
3014 }
3015
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003016 auto TSB = AArch64TSB::lookupTSBByName(Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003017 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00003018 auto DB = AArch64DB::lookupDBByName(Tok.getString());
3019 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003020 TokError("'sy' or #imm operand expected");
3021 return MatchOperand_ParseFail;
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003022 // The only valid named option for TSB is 'csync'
3023 } else if (Mnemonic == "tsb" && (!TSB || TSB->Encoding != AArch64TSB::csync)) {
3024 TokError("'csync' operand expected");
3025 return MatchOperand_ParseFail;
3026 } else if (!DB && !TSB) {
Sjoerd Meijere5b85572017-04-24 08:22:20 +00003027 TokError("invalid barrier option name");
3028 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003029 }
3030
Tim Northovere6ae6762016-07-05 21:23:04 +00003031 Operands.push_back(AArch64Operand::CreateBarrier(
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003032 DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003033 Parser.Lex(); // Consume the option
3034
3035 return MatchOperand_Success;
3036}
3037
Alex Bradbury58eba092016-11-01 16:32:05 +00003038OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003039AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003040 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003041 const AsmToken &Tok = Parser.getTok();
3042
3043 if (Tok.isNot(AsmToken::Identifier))
3044 return MatchOperand_NoMatch;
3045
Tim Northovere6ae6762016-07-05 21:23:04 +00003046 int MRSReg, MSRReg;
3047 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
3048 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
3049 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
3050 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
3051 } else
3052 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00003053
Tim Northovere6ae6762016-07-05 21:23:04 +00003054 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
3055 unsigned PStateImm = -1;
3056 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
3057 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00003058
Tim Northovere6ae6762016-07-05 21:23:04 +00003059 Operands.push_back(
3060 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
3061 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003062 Parser.Lex(); // Eat identifier
3063
3064 return MatchOperand_Success;
3065}
3066
Florian Hahnc4422242017-11-07 13:07:50 +00003067/// tryParseNeonVectorRegister - Parse a vector register operand.
3068bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003069 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003070 if (Parser.getTok().isNot(AsmToken::Identifier))
3071 return true;
3072
3073 SMLoc S = getLoc();
3074 // Check for a vector register specifier first.
3075 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003076 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00003077 OperandMatchResultTy Res =
3078 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
3079 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00003080 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00003081
3082 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
3083 if (!KindRes)
3084 return true;
3085
3086 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00003087 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00003088 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
3089 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00003090
Tim Northover3b0846e2014-05-24 12:50:23 +00003091 // If there was an explicit qualifier, that goes on as a literal text
3092 // operand.
3093 if (!Kind.empty())
3094 Operands.push_back(
3095 AArch64Operand::CreateToken(Kind, false, S, getContext()));
3096
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003097 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3098}
3099
3100OperandMatchResultTy
3101AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00003102 SMLoc SIdx = getLoc();
3103 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003104 const MCExpr *ImmVal;
3105 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003106 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00003107 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3108 if (!MCE) {
3109 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003110 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00003111 }
3112
3113 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003114
Nirav Davee833c6c2016-11-08 18:31:04 +00003115 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003116 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00003117
3118 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
3119 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003120 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003121 }
3122
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003123 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00003124}
3125
Sander de Smalen73937b72018-04-11 07:36:10 +00003126// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00003127// optional kind specifier. If it is a register specifier, eat the token
3128// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00003129OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00003130AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00003131 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00003132 MCAsmParser &Parser = getParser();
3133 const AsmToken &Tok = Parser.getTok();
3134
Florian Hahn91f11e52017-11-07 16:45:48 +00003135 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00003136 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003137
3138 StringRef Name = Tok.getString();
3139 // If there is a kind specifier, it's separated from the register name by
3140 // a '.'.
3141 size_t Start = 0, Next = Name.find('.');
3142 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00003143 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00003144
3145 if (RegNum) {
3146 if (Next != StringRef::npos) {
3147 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00003148 if (!isValidVectorKind(Kind, MatchKind)) {
3149 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00003150 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00003151 }
3152 }
Sander de Smalen8e607342017-11-15 15:44:43 +00003153 Parser.Lex(); // Eat the register token.
3154
3155 Reg = RegNum;
3156 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00003157 }
3158
Sander de Smalen8e607342017-11-15 15:44:43 +00003159 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003160}
3161
Sander de Smalencd6be962017-12-20 11:02:42 +00003162/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
3163OperandMatchResultTy
3164AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
3165 // Check for a SVE predicate register specifier first.
3166 const SMLoc S = getLoc();
3167 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003168 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00003169 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00003170 if (Res != MatchOperand_Success)
3171 return Res;
3172
Sander de Smalen73937b72018-04-11 07:36:10 +00003173 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
3174 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00003175 return MatchOperand_NoMatch;
3176
Sander de Smalen73937b72018-04-11 07:36:10 +00003177 unsigned ElementWidth = KindRes->second;
3178 Operands.push_back(AArch64Operand::CreateVectorReg(
3179 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
3180 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00003181
Sander de Smalen7868e742018-01-09 11:17:06 +00003182 // Not all predicates are followed by a '/m' or '/z'.
3183 MCAsmParser &Parser = getParser();
3184 if (Parser.getTok().isNot(AsmToken::Slash))
3185 return MatchOperand_Success;
3186
3187 // But when they do they shouldn't have an element type suffix.
3188 if (!Kind.empty()) {
3189 Error(S, "not expecting size suffix");
3190 return MatchOperand_ParseFail;
3191 }
3192
3193 // Add a literal slash as operand
3194 Operands.push_back(
3195 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
3196
3197 Parser.Lex(); // Eat the slash.
3198
3199 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00003200 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00003201 if (Pred != "z" && Pred != "m") {
3202 Error(getLoc(), "expecting 'm' or 'z' predication");
3203 return MatchOperand_ParseFail;
3204 }
3205
3206 // Add zero/merge token.
3207 const char *ZM = Pred == "z" ? "z" : "m";
3208 Operands.push_back(
3209 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
3210
3211 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00003212 return MatchOperand_Success;
3213}
3214
Sander de Smalen50d87022018-04-19 07:35:08 +00003215/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00003216bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003217 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00003218 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00003219 return false;
3220
Sander de Smalen149916d2018-04-20 07:24:20 +00003221 // Otherwise try for a scalar register.
3222 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
3223 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003224
Sander de Smalen149916d2018-04-20 07:24:20 +00003225 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003226}
3227
3228bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003229 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003230 bool HasELFModifier = false;
3231 AArch64MCExpr::VariantKind RefKind;
3232
Nirav Davee833c6c2016-11-08 18:31:04 +00003233 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003234 HasELFModifier = true;
3235
Nirav Davee833c6c2016-11-08 18:31:04 +00003236 if (Parser.getTok().isNot(AsmToken::Identifier))
3237 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003238
3239 std::string LowerCase = Parser.getTok().getIdentifier().lower();
3240 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
3241 .Case("lo12", AArch64MCExpr::VK_LO12)
3242 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
3243 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
3244 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
3245 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
3246 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
3247 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
3248 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
3249 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
3250 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
3251 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
3252 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
3253 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
3254 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3255 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3256 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3257 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3258 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3259 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3260 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3261 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3262 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3263 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3264 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3265 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3266 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3267 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3268 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3269 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3270 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3271 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3272 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3273 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3274 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3275 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003276 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3277 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00003278 .Default(AArch64MCExpr::VK_INVALID);
3279
Nirav Davee833c6c2016-11-08 18:31:04 +00003280 if (RefKind == AArch64MCExpr::VK_INVALID)
3281 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003282
3283 Parser.Lex(); // Eat identifier
3284
Nirav Davee833c6c2016-11-08 18:31:04 +00003285 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003286 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003287 }
3288
3289 if (getParser().parseExpression(ImmVal))
3290 return true;
3291
3292 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003293 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003294
3295 return false;
3296}
3297
Sander de Smalen650234b2018-04-12 11:40:52 +00003298template <RegKind VectorKind>
3299OperandMatchResultTy
3300AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3301 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003302 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003303 if (!Parser.getTok().is(AsmToken::LCurly))
3304 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003305
3306 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003307 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003308 bool NoMatchIsError) {
3309 auto RegTok = Parser.getTok();
3310 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3311 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003312 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003313 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003314 llvm_unreachable("Expected a valid vector kind");
3315 }
3316
Sander de Smalen650234b2018-04-12 11:40:52 +00003317 if (RegTok.isNot(AsmToken::Identifier) ||
3318 ParseRes == MatchOperand_ParseFail ||
3319 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3320 Error(Loc, "vector register expected");
3321 return MatchOperand_ParseFail;
3322 }
3323
3324 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003325 };
3326
Tim Northover3b0846e2014-05-24 12:50:23 +00003327 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003328 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003329 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003330
Tim Northover3b0846e2014-05-24 12:50:23 +00003331 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003332 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003333 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3334
3335 // Put back the original left bracket if there was no match, so that
3336 // different types of list-operands can be matched (e.g. SVE, Neon).
3337 if (ParseRes == MatchOperand_NoMatch)
3338 Parser.getLexer().UnLex(LCurly);
3339
3340 if (ParseRes != MatchOperand_Success)
3341 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003342
Tim Northover3b0846e2014-05-24 12:50:23 +00003343 int64_t PrevReg = FirstReg;
3344 unsigned Count = 1;
3345
Nirav Davee833c6c2016-11-08 18:31:04 +00003346 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003347 SMLoc Loc = getLoc();
3348 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003349
Sander de Smalen50d87022018-04-19 07:35:08 +00003350 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003351 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3352 if (ParseRes != MatchOperand_Success)
3353 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003354
Tim Northover3b0846e2014-05-24 12:50:23 +00003355 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003356 if (Kind != NextKind) {
3357 Error(Loc, "mismatched register size suffix");
3358 return MatchOperand_ParseFail;
3359 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003360
3361 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3362
3363 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003364 Error(Loc, "invalid number of vectors");
3365 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003366 }
3367
3368 Count += Space;
3369 }
3370 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003371 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003372 SMLoc Loc = getLoc();
3373 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003374 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003375 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3376 if (ParseRes != MatchOperand_Success)
3377 return ParseRes;
3378
Tim Northover3b0846e2014-05-24 12:50:23 +00003379 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003380 if (Kind != NextKind) {
3381 Error(Loc, "mismatched register size suffix");
3382 return MatchOperand_ParseFail;
3383 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003384
3385 // Registers must be incremental (with wraparound at 31)
3386 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003387 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3388 Error(Loc, "registers must be sequential");
3389 return MatchOperand_ParseFail;
3390 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003391
3392 PrevReg = Reg;
3393 ++Count;
3394 }
3395 }
3396
Nirav Davee833c6c2016-11-08 18:31:04 +00003397 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003398 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003399
Sander de Smalen650234b2018-04-12 11:40:52 +00003400 if (Count > 4) {
3401 Error(S, "invalid number of vectors");
3402 return MatchOperand_ParseFail;
3403 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003404
3405 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003406 unsigned ElementWidth = 0;
3407 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003408 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003409 std::tie(NumElements, ElementWidth) = *VK;
3410 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003411
3412 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003413 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3414 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003415
Sander de Smalen650234b2018-04-12 11:40:52 +00003416 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003417}
3418
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003419/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3420bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003421 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3422 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003423 return true;
3424
3425 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3426}
3427
Alex Bradbury58eba092016-11-01 16:32:05 +00003428OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003429AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003430 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003431
Sander de Smalen50d87022018-04-19 07:35:08 +00003432 unsigned RegNum;
3433 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3434 if (Res != MatchOperand_Success)
3435 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003436
Nirav Davee833c6c2016-11-08 18:31:04 +00003437 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003438 Operands.push_back(AArch64Operand::CreateReg(
3439 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003440 return MatchOperand_Success;
3441 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003442
Nirav Davee833c6c2016-11-08 18:31:04 +00003443 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003444
Sander de Smalen50d87022018-04-19 07:35:08 +00003445 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003446 Error(getLoc(), "index must be absent or #0");
3447 return MatchOperand_ParseFail;
3448 }
3449
3450 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003451 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003452 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3453 Error(getLoc(), "index must be absent or #0");
3454 return MatchOperand_ParseFail;
3455 }
3456
Sander de Smalen50d87022018-04-19 07:35:08 +00003457 Operands.push_back(AArch64Operand::CreateReg(
3458 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003459 return MatchOperand_Success;
3460}
3461
Sander de Smalen0325e302018-07-02 07:34:52 +00003462template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
Sander de Smalen149916d2018-04-20 07:24:20 +00003463OperandMatchResultTy
3464AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3465 SMLoc StartLoc = getLoc();
3466
3467 unsigned RegNum;
3468 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3469 if (Res != MatchOperand_Success)
3470 return Res;
3471
3472 // No shift/extend is the default.
3473 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3474 Operands.push_back(AArch64Operand::CreateReg(
Sander de Smalen0325e302018-07-02 07:34:52 +00003475 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
Sander de Smalen149916d2018-04-20 07:24:20 +00003476 return MatchOperand_Success;
3477 }
3478
3479 // Eat the comma
3480 getParser().Lex();
3481
3482 // Match the shift
3483 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3484 Res = tryParseOptionalShiftExtend(ExtOpnd);
3485 if (Res != MatchOperand_Success)
3486 return Res;
3487
3488 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
Sander de Smalen0325e302018-07-02 07:34:52 +00003489 Operands.push_back(AArch64Operand::CreateReg(
3490 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3491 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3492 Ext->hasShiftExtendAmount()));
Sander de Smalen149916d2018-04-20 07:24:20 +00003493
3494 return MatchOperand_Success;
3495}
3496
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003497bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
Sander de Smalen5c625982018-04-13 12:56:14 +00003498 MCAsmParser &Parser = getParser();
3499
3500 // Some SVE instructions have a decoration after the immediate, i.e.
3501 // "mul vl". We parse them here and add tokens, which must be present in the
3502 // asm string in the tablegen instruction.
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003503 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3504 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
Sander de Smalen5c625982018-04-13 12:56:14 +00003505 if (!Parser.getTok().getString().equals_lower("mul") ||
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003506 !(NextIsVL || NextIsHash))
Sander de Smalen5c625982018-04-13 12:56:14 +00003507 return true;
3508
Sander de Smalen5c625982018-04-13 12:56:14 +00003509 Operands.push_back(
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003510 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
Sander de Smalen5c625982018-04-13 12:56:14 +00003511 Parser.Lex(); // Eat the "mul"
3512
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003513 if (NextIsVL) {
3514 Operands.push_back(
3515 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3516 Parser.Lex(); // Eat the "vl"
3517 return false;
3518 }
Sander de Smalen5c625982018-04-13 12:56:14 +00003519
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003520 if (NextIsHash) {
3521 Parser.Lex(); // Eat the #
3522 SMLoc S = getLoc();
3523
3524 // Parse immediate operand.
3525 const MCExpr *ImmVal;
3526 if (!Parser.parseExpression(ImmVal))
3527 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3528 Operands.push_back(AArch64Operand::CreateImm(
3529 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3530 getContext()));
3531 return MatchOperand_Success;
3532 }
3533 }
3534
3535 return Error(getLoc(), "expected 'vl' or '#<imm>'");
Sander de Smalen5c625982018-04-13 12:56:14 +00003536}
3537
Tim Northover3b0846e2014-05-24 12:50:23 +00003538/// parseOperand - Parse a arm instruction operand. For now this parses the
3539/// operand regardless of the mnemonic.
3540bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3541 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003542 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003543
3544 OperandMatchResultTy ResTy =
3545 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3546
Tim Northover3b0846e2014-05-24 12:50:23 +00003547 // Check if the current operand has a custom associated parser, if so, try to
3548 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003549 if (ResTy == MatchOperand_Success)
3550 return false;
3551 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3552 // there was a match, but an error occurred, in which case, just return that
3553 // the operand parsing failed.
3554 if (ResTy == MatchOperand_ParseFail)
3555 return true;
3556
3557 // Nothing custom, so do general case parsing.
3558 SMLoc S, E;
3559 switch (getLexer().getKind()) {
3560 default: {
3561 SMLoc S = getLoc();
3562 const MCExpr *Expr;
3563 if (parseSymbolicImmVal(Expr))
3564 return Error(S, "invalid operand");
3565
3566 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3567 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3568 return false;
3569 }
3570 case AsmToken::LBrac: {
3571 SMLoc Loc = Parser.getTok().getLoc();
3572 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3573 getContext()));
3574 Parser.Lex(); // Eat '['
3575
3576 // There's no comma after a '[', so we can parse the next operand
3577 // immediately.
3578 return parseOperand(Operands, false, false);
3579 }
3580 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003581 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003582 case AsmToken::Identifier: {
3583 // If we're expecting a Condition Code operand, then just parse that.
3584 if (isCondCode)
3585 return parseCondCode(Operands, invertCondCode);
3586
3587 // If it's a register name, parse it.
3588 if (!parseRegister(Operands))
3589 return false;
3590
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003591 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3592 // by SVE instructions.
3593 if (!parseOptionalMulOperand(Operands))
Sander de Smalen5c625982018-04-13 12:56:14 +00003594 return false;
3595
Tim Northover3b0846e2014-05-24 12:50:23 +00003596 // This could be an optional "shift" or "extend" operand.
3597 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3598 // We can only continue if no tokens were eaten.
3599 if (GotShift != MatchOperand_NoMatch)
3600 return GotShift;
3601
3602 // This was not a register so parse other operands that start with an
3603 // identifier (like labels) as expressions and create them as immediates.
3604 const MCExpr *IdVal;
3605 S = getLoc();
3606 if (getParser().parseExpression(IdVal))
3607 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003608 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3609 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3610 return false;
3611 }
3612 case AsmToken::Integer:
3613 case AsmToken::Real:
3614 case AsmToken::Hash: {
3615 // #42 -> immediate.
3616 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003617
3618 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003619
3620 // Parse a negative sign
3621 bool isNegative = false;
3622 if (Parser.getTok().is(AsmToken::Minus)) {
3623 isNegative = true;
3624 // We need to consume this token only when we have a Real, otherwise
3625 // we let parseSymbolicImmVal take care of it
3626 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3627 Parser.Lex();
3628 }
3629
3630 // The only Real that should come through here is a literal #0.0 for
3631 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3632 // so convert the value.
3633 const AsmToken &Tok = Parser.getTok();
3634 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003635 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003636 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3637 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3638 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
Sander de Smalen8fcc3f52018-07-03 09:07:23 +00003639 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
Tim Northover3b0846e2014-05-24 12:50:23 +00003640 return TokError("unexpected floating point literal");
3641 else if (IntVal != 0 || isNegative)
3642 return TokError("expected floating-point constant #0.0");
3643 Parser.Lex(); // Eat the token.
3644
3645 Operands.push_back(
3646 AArch64Operand::CreateToken("#0", false, S, getContext()));
3647 Operands.push_back(
3648 AArch64Operand::CreateToken(".0", false, S, getContext()));
3649 return false;
3650 }
3651
3652 const MCExpr *ImmVal;
3653 if (parseSymbolicImmVal(ImmVal))
3654 return true;
3655
3656 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3657 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3658 return false;
3659 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003660 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003661 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003662 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003663 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003664 Parser.Lex(); // Eat '='
3665 const MCExpr *SubExprVal;
3666 if (getParser().parseExpression(SubExprVal))
3667 return true;
3668
David Peixottoae5ba762014-07-18 16:05:14 +00003669 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003670 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003671 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003672
3673 bool IsXReg =
3674 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3675 Operands[1]->getReg());
3676
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003677 MCContext& Ctx = getContext();
3678 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3679 // 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 +00003680 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003681 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3682 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3683 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3684 ShiftAmt += 16;
3685 Imm >>= 16;
3686 }
3687 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3688 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3689 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003690 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003691 if (ShiftAmt)
3692 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3693 ShiftAmt, true, S, E, Ctx));
3694 return false;
3695 }
David Peixottoae5ba762014-07-18 16:05:14 +00003696 APInt Simm = APInt(64, Imm << ShiftAmt);
3697 // check if the immediate is an unsigned or signed 32-bit int for W regs
3698 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3699 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003700 }
3701 // 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 +00003702 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003703 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003704 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3705 return false;
3706 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003707 }
3708}
3709
Sander de Smalen0325e302018-07-02 07:34:52 +00003710bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3711 const MCParsedAsmOperand &Op2) const {
3712 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3713 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3714 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3715 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3716 return MCTargetAsmParser::regsEqual(Op1, Op2);
3717
3718 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3719 "Testing equality of non-scalar registers not supported");
3720
3721 // Check if a registers match their sub/super register classes.
3722 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3723 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3724 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3725 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3726 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3727 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3728 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3729 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3730
3731 return false;
3732}
3733
Tim Northover3b0846e2014-05-24 12:50:23 +00003734/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3735/// operands.
3736bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3737 StringRef Name, SMLoc NameLoc,
3738 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003739 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003740 Name = StringSwitch<StringRef>(Name.lower())
3741 .Case("beq", "b.eq")
3742 .Case("bne", "b.ne")
3743 .Case("bhs", "b.hs")
3744 .Case("bcs", "b.cs")
3745 .Case("blo", "b.lo")
3746 .Case("bcc", "b.cc")
3747 .Case("bmi", "b.mi")
3748 .Case("bpl", "b.pl")
3749 .Case("bvs", "b.vs")
3750 .Case("bvc", "b.vc")
3751 .Case("bhi", "b.hi")
3752 .Case("bls", "b.ls")
3753 .Case("bge", "b.ge")
3754 .Case("blt", "b.lt")
3755 .Case("bgt", "b.gt")
3756 .Case("ble", "b.le")
3757 .Case("bal", "b.al")
3758 .Case("bnv", "b.nv")
3759 .Default(Name);
3760
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003761 // First check for the AArch64-specific .req directive.
3762 if (Parser.getTok().is(AsmToken::Identifier) &&
3763 Parser.getTok().getIdentifier() == ".req") {
3764 parseDirectiveReq(Name, NameLoc);
3765 // We always return 'error' for this, as we're done with this
3766 // statement and don't need to match the 'instruction."
3767 return true;
3768 }
3769
Tim Northover3b0846e2014-05-24 12:50:23 +00003770 // Create the leading tokens for the mnemonic, split by '.' characters.
3771 size_t Start = 0, Next = Name.find('.');
3772 StringRef Head = Name.slice(Start, Next);
3773
Oliver Stannard224428c2018-09-27 13:47:40 +00003774 // IC, DC, AT, TLBI and Prediction invalidation instructions are aliases for
3775 // the SYS instruction.
3776 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi" ||
3777 Head == "cfp" || Head == "dvp" || Head == "cpp")
Nirav Davee833c6c2016-11-08 18:31:04 +00003778 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003779
3780 Operands.push_back(
3781 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3782 Mnemonic = Head;
3783
3784 // Handle condition codes for a branch mnemonic
3785 if (Head == "b" && Next != StringRef::npos) {
3786 Start = Next;
3787 Next = Name.find('.', Start + 1);
3788 Head = Name.slice(Start + 1, Next);
3789
3790 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3791 (Head.data() - Name.data()));
3792 AArch64CC::CondCode CC = parseCondCodeString(Head);
3793 if (CC == AArch64CC::Invalid)
3794 return Error(SuffixLoc, "invalid condition code");
3795 Operands.push_back(
3796 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3797 Operands.push_back(
3798 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3799 }
3800
3801 // Add the remaining tokens in the mnemonic.
3802 while (Next != StringRef::npos) {
3803 Start = Next;
3804 Next = Name.find('.', Start + 1);
3805 Head = Name.slice(Start, Next);
3806 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3807 (Head.data() - Name.data()) + 1);
3808 Operands.push_back(
3809 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3810 }
3811
3812 // Conditional compare instructions have a Condition Code operand, which needs
3813 // to be parsed and an immediate operand created.
3814 bool condCodeFourthOperand =
3815 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3816 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3817 Head == "csinc" || Head == "csinv" || Head == "csneg");
3818
3819 // These instructions are aliases to some of the conditional select
3820 // instructions. However, the condition code is inverted in the aliased
3821 // instruction.
3822 //
3823 // FIXME: Is this the correct way to handle these? Or should the parser
3824 // generate the aliased instructions directly?
3825 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3826 bool condCodeThirdOperand =
3827 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3828
3829 // Read the remaining operands.
3830 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003831
Oliver Stannardc4190282018-10-02 10:04:39 +00003832 unsigned N = 1;
3833 do {
Tim Northover3b0846e2014-05-24 12:50:23 +00003834 // Parse and remember the operand.
3835 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3836 (N == 3 && condCodeThirdOperand) ||
3837 (N == 2 && condCodeSecondOperand),
3838 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003839 return true;
3840 }
3841
3842 // After successfully parsing some operands there are two special cases to
3843 // consider (i.e. notional operands not separated by commas). Both are due
3844 // to memory specifiers:
3845 // + An RBrac will end an address for load/store/prefetch
3846 // + An '!' will indicate a pre-indexed operation.
3847 //
3848 // It's someone else's responsibility to make sure these tokens are sane
3849 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003850
Nirav Davee833c6c2016-11-08 18:31:04 +00003851 SMLoc RLoc = Parser.getTok().getLoc();
3852 if (parseOptionalToken(AsmToken::RBrac))
3853 Operands.push_back(
3854 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3855 SMLoc ELoc = Parser.getTok().getLoc();
3856 if (parseOptionalToken(AsmToken::Exclaim))
3857 Operands.push_back(
3858 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003859
3860 ++N;
Oliver Stannardc4190282018-10-02 10:04:39 +00003861 } while (parseOptionalToken(AsmToken::Comma));
Tim Northover3b0846e2014-05-24 12:50:23 +00003862 }
3863
Nirav Davee833c6c2016-11-08 18:31:04 +00003864 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3865 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003866
Tim Northover3b0846e2014-05-24 12:50:23 +00003867 return false;
3868}
3869
Sander de Smalen9b333092018-07-30 15:42:46 +00003870static inline bool isMatchingOrAlias(unsigned ZReg, unsigned Reg) {
3871 assert((ZReg >= AArch64::Z0) && (ZReg <= AArch64::Z31));
3872 return (ZReg == ((Reg - AArch64::B0) + AArch64::Z0)) ||
3873 (ZReg == ((Reg - AArch64::H0) + AArch64::Z0)) ||
3874 (ZReg == ((Reg - AArch64::S0) + AArch64::Z0)) ||
3875 (ZReg == ((Reg - AArch64::D0) + AArch64::Z0)) ||
3876 (ZReg == ((Reg - AArch64::Q0) + AArch64::Z0)) ||
3877 (ZReg == ((Reg - AArch64::Z0) + AArch64::Z0));
3878}
3879
Tim Northover3b0846e2014-05-24 12:50:23 +00003880// FIXME: This entire function is a giant hack to provide us with decent
3881// operand range validation/diagnostics until TableGen/MC can be extended
3882// to support autogeneration of this kind of validation.
Sander de Smalen9b333092018-07-30 15:42:46 +00003883bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
3884 SmallVectorImpl<SMLoc> &Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003885 const MCRegisterInfo *RI = getContext().getRegisterInfo();
Sander de Smalen9b333092018-07-30 15:42:46 +00003886 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
3887
3888 // A prefix only applies to the instruction following it. Here we extract
3889 // prefix information for the next instruction before validating the current
3890 // one so that in the case of failure we don't erronously continue using the
3891 // current prefix.
3892 PrefixInfo Prefix = NextPrefix;
3893 NextPrefix = PrefixInfo::CreateFromInst(Inst, MCID.TSFlags);
3894
3895 // Before validating the instruction in isolation we run through the rules
3896 // applicable when it follows a prefix instruction.
3897 // NOTE: brk & hlt can be prefixed but require no additional validation.
3898 if (Prefix.isActive() &&
3899 (Inst.getOpcode() != AArch64::BRK) &&
3900 (Inst.getOpcode() != AArch64::HLT)) {
3901
3902 // Prefixed intructions must have a destructive operand.
3903 if ((MCID.TSFlags & AArch64::DestructiveInstTypeMask) ==
3904 AArch64::NotDestructive)
3905 return Error(IDLoc, "instruction is unpredictable when following a"
3906 " movprfx, suggest replacing movprfx with mov");
3907
3908 // Destination operands must match.
3909 if (Inst.getOperand(0).getReg() != Prefix.getDstReg())
3910 return Error(Loc[0], "instruction is unpredictable when following a"
3911 " movprfx writing to a different destination");
3912
3913 // Destination operand must not be used in any other location.
3914 for (unsigned i = 1; i < Inst.getNumOperands(); ++i) {
3915 if (Inst.getOperand(i).isReg() &&
3916 (MCID.getOperandConstraint(i, MCOI::TIED_TO) == -1) &&
3917 isMatchingOrAlias(Prefix.getDstReg(), Inst.getOperand(i).getReg()))
3918 return Error(Loc[0], "instruction is unpredictable when following a"
3919 " movprfx and destination also used as non-destructive"
3920 " source");
3921 }
3922
3923 auto PPRRegClass = AArch64MCRegisterClasses[AArch64::PPRRegClassID];
3924 if (Prefix.isPredicated()) {
3925 int PgIdx = -1;
3926
3927 // Find the instructions general predicate.
3928 for (unsigned i = 1; i < Inst.getNumOperands(); ++i)
3929 if (Inst.getOperand(i).isReg() &&
3930 PPRRegClass.contains(Inst.getOperand(i).getReg())) {
3931 PgIdx = i;
3932 break;
3933 }
3934
3935 // Instruction must be predicated if the movprfx is predicated.
3936 if (PgIdx == -1 ||
3937 (MCID.TSFlags & AArch64::ElementSizeMask) == AArch64::ElementSizeNone)
3938 return Error(IDLoc, "instruction is unpredictable when following a"
3939 " predicated movprfx, suggest using unpredicated movprfx");
3940
3941 // Instruction must use same general predicate as the movprfx.
3942 if (Inst.getOperand(PgIdx).getReg() != Prefix.getPgReg())
3943 return Error(IDLoc, "instruction is unpredictable when following a"
3944 " predicated movprfx using a different general predicate");
3945
3946 // Instruction element type must match the movprfx.
3947 if ((MCID.TSFlags & AArch64::ElementSizeMask) != Prefix.getElementSize())
3948 return Error(IDLoc, "instruction is unpredictable when following a"
3949 " predicated movprfx with a different element size");
3950 }
3951 }
3952
Tim Northover3b0846e2014-05-24 12:50:23 +00003953 // Check for indexed addressing modes w/ the base register being the
3954 // same as a destination/source register or pair load where
3955 // the Rt == Rt2. All of those are undefined behaviour.
3956 switch (Inst.getOpcode()) {
3957 case AArch64::LDPSWpre:
3958 case AArch64::LDPWpost:
3959 case AArch64::LDPWpre:
3960 case AArch64::LDPXpost:
3961 case AArch64::LDPXpre: {
3962 unsigned Rt = Inst.getOperand(1).getReg();
3963 unsigned Rt2 = Inst.getOperand(2).getReg();
3964 unsigned Rn = Inst.getOperand(3).getReg();
3965 if (RI->isSubRegisterEq(Rn, Rt))
3966 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3967 "is also a destination");
3968 if (RI->isSubRegisterEq(Rn, Rt2))
3969 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3970 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003971 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003972 }
3973 case AArch64::LDPDi:
3974 case AArch64::LDPQi:
3975 case AArch64::LDPSi:
3976 case AArch64::LDPSWi:
3977 case AArch64::LDPWi:
3978 case AArch64::LDPXi: {
3979 unsigned Rt = Inst.getOperand(0).getReg();
3980 unsigned Rt2 = Inst.getOperand(1).getReg();
3981 if (Rt == Rt2)
3982 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3983 break;
3984 }
3985 case AArch64::LDPDpost:
3986 case AArch64::LDPDpre:
3987 case AArch64::LDPQpost:
3988 case AArch64::LDPQpre:
3989 case AArch64::LDPSpost:
3990 case AArch64::LDPSpre:
3991 case AArch64::LDPSWpost: {
3992 unsigned Rt = Inst.getOperand(1).getReg();
3993 unsigned Rt2 = Inst.getOperand(2).getReg();
3994 if (Rt == Rt2)
3995 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3996 break;
3997 }
3998 case AArch64::STPDpost:
3999 case AArch64::STPDpre:
4000 case AArch64::STPQpost:
4001 case AArch64::STPQpre:
4002 case AArch64::STPSpost:
4003 case AArch64::STPSpre:
4004 case AArch64::STPWpost:
4005 case AArch64::STPWpre:
4006 case AArch64::STPXpost:
4007 case AArch64::STPXpre: {
4008 unsigned Rt = Inst.getOperand(1).getReg();
4009 unsigned Rt2 = Inst.getOperand(2).getReg();
4010 unsigned Rn = Inst.getOperand(3).getReg();
4011 if (RI->isSubRegisterEq(Rn, Rt))
4012 return Error(Loc[0], "unpredictable STP instruction, writeback base "
4013 "is also a source");
4014 if (RI->isSubRegisterEq(Rn, Rt2))
4015 return Error(Loc[1], "unpredictable STP instruction, writeback base "
4016 "is also a source");
4017 break;
4018 }
4019 case AArch64::LDRBBpre:
4020 case AArch64::LDRBpre:
4021 case AArch64::LDRHHpre:
4022 case AArch64::LDRHpre:
4023 case AArch64::LDRSBWpre:
4024 case AArch64::LDRSBXpre:
4025 case AArch64::LDRSHWpre:
4026 case AArch64::LDRSHXpre:
4027 case AArch64::LDRSWpre:
4028 case AArch64::LDRWpre:
4029 case AArch64::LDRXpre:
4030 case AArch64::LDRBBpost:
4031 case AArch64::LDRBpost:
4032 case AArch64::LDRHHpost:
4033 case AArch64::LDRHpost:
4034 case AArch64::LDRSBWpost:
4035 case AArch64::LDRSBXpost:
4036 case AArch64::LDRSHWpost:
4037 case AArch64::LDRSHXpost:
4038 case AArch64::LDRSWpost:
4039 case AArch64::LDRWpost:
4040 case AArch64::LDRXpost: {
4041 unsigned Rt = Inst.getOperand(1).getReg();
4042 unsigned Rn = Inst.getOperand(2).getReg();
4043 if (RI->isSubRegisterEq(Rn, Rt))
4044 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
4045 "is also a source");
4046 break;
4047 }
4048 case AArch64::STRBBpost:
4049 case AArch64::STRBpost:
4050 case AArch64::STRHHpost:
4051 case AArch64::STRHpost:
4052 case AArch64::STRWpost:
4053 case AArch64::STRXpost:
4054 case AArch64::STRBBpre:
4055 case AArch64::STRBpre:
4056 case AArch64::STRHHpre:
4057 case AArch64::STRHpre:
4058 case AArch64::STRWpre:
4059 case AArch64::STRXpre: {
4060 unsigned Rt = Inst.getOperand(1).getReg();
4061 unsigned Rn = Inst.getOperand(2).getReg();
4062 if (RI->isSubRegisterEq(Rn, Rt))
4063 return Error(Loc[0], "unpredictable STR instruction, writeback base "
4064 "is also a source");
4065 break;
4066 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004067 case AArch64::STXRB:
4068 case AArch64::STXRH:
4069 case AArch64::STXRW:
4070 case AArch64::STXRX:
4071 case AArch64::STLXRB:
4072 case AArch64::STLXRH:
4073 case AArch64::STLXRW:
4074 case AArch64::STLXRX: {
4075 unsigned Rs = Inst.getOperand(0).getReg();
4076 unsigned Rt = Inst.getOperand(1).getReg();
4077 unsigned Rn = Inst.getOperand(2).getReg();
4078 if (RI->isSubRegisterEq(Rt, Rs) ||
4079 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
4080 return Error(Loc[0],
4081 "unpredictable STXR instruction, status is also a source");
4082 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00004083 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004084 case AArch64::STXPW:
4085 case AArch64::STXPX:
4086 case AArch64::STLXPW:
4087 case AArch64::STLXPX: {
4088 unsigned Rs = Inst.getOperand(0).getReg();
4089 unsigned Rt1 = Inst.getOperand(1).getReg();
4090 unsigned Rt2 = Inst.getOperand(2).getReg();
4091 unsigned Rn = Inst.getOperand(3).getReg();
4092 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
4093 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
4094 return Error(Loc[0],
4095 "unpredictable STXP instruction, status is also a source");
4096 break;
4097 }
Oliver Stannardc4190282018-10-02 10:04:39 +00004098 case AArch64::LDGV: {
4099 unsigned Rt = Inst.getOperand(0).getReg();
4100 unsigned Rn = Inst.getOperand(1).getReg();
4101 if (RI->isSubRegisterEq(Rt, Rn)) {
4102 return Error(Loc[0],
4103 "unpredictable LDGV instruction, writeback register is also "
4104 "the target register");
4105 }
4106 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004107 }
4108
Tim Northover3b0846e2014-05-24 12:50:23 +00004109
4110 // Now check immediate ranges. Separate from the above as there is overlap
4111 // in the instructions being checked and this keeps the nested conditionals
4112 // to a minimum.
4113 switch (Inst.getOpcode()) {
4114 case AArch64::ADDSWri:
4115 case AArch64::ADDSXri:
4116 case AArch64::ADDWri:
4117 case AArch64::ADDXri:
4118 case AArch64::SUBSWri:
4119 case AArch64::SUBSXri:
4120 case AArch64::SUBWri:
4121 case AArch64::SUBXri: {
4122 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
4123 // some slight duplication here.
4124 if (Inst.getOperand(2).isExpr()) {
4125 const MCExpr *Expr = Inst.getOperand(2).getExpr();
4126 AArch64MCExpr::VariantKind ELFRefKind;
4127 MCSymbolRefExpr::VariantKind DarwinRefKind;
4128 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00004129 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
4130
4131 // Only allow these with ADDXri.
4132 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
4133 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
4134 Inst.getOpcode() == AArch64::ADDXri)
4135 return false;
4136
4137 // Only allow these with ADDXri/ADDWri
4138 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
4139 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
4140 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
4141 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
4142 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
4143 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
4144 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00004145 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
4146 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
4147 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00004148 (Inst.getOpcode() == AArch64::ADDXri ||
4149 Inst.getOpcode() == AArch64::ADDWri))
4150 return false;
4151
4152 // Don't allow symbol refs in the immediate field otherwise
4153 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
4154 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
4155 // 'cmp w0, 'borked')
4156 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00004157 }
Diana Picusc93518d2016-10-11 09:17:47 +00004158 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00004159 }
4160 return false;
4161 }
4162 default:
4163 return false;
4164 }
4165}
4166
Craig Topper05515562017-10-26 06:46:41 +00004167static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
4168 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004169
4170bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
Sander de Smalen0325e302018-07-02 07:34:52 +00004171 uint64_t ErrorInfo,
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004172 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004173 switch (ErrCode) {
Sander de Smalen0325e302018-07-02 07:34:52 +00004174 case Match_InvalidTiedOperand: {
4175 RegConstraintEqualityTy EqTy =
4176 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
4177 .getRegEqualityTy();
4178 switch (EqTy) {
4179 case RegConstraintEqualityTy::EqualsSubReg:
4180 return Error(Loc, "operand must be 64-bit form of destination register");
4181 case RegConstraintEqualityTy::EqualsSuperReg:
4182 return Error(Loc, "operand must be 32-bit form of destination register");
4183 case RegConstraintEqualityTy::EqualsReg:
4184 return Error(Loc, "operand must match destination register");
4185 }
Simon Pilgrim6dc45e62018-07-05 09:48:01 +00004186 llvm_unreachable("Unknown RegConstraintEqualityTy");
Sander de Smalen0325e302018-07-02 07:34:52 +00004187 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004188 case Match_MissingFeature:
4189 return Error(Loc,
4190 "instruction requires a CPU feature not currently enabled");
4191 case Match_InvalidOperand:
4192 return Error(Loc, "invalid operand for instruction");
4193 case Match_InvalidSuffix:
4194 return Error(Loc, "invalid type suffix for instruction");
4195 case Match_InvalidCondCode:
4196 return Error(Loc, "expected AArch64 condition code");
4197 case Match_AddSubRegExtendSmall:
4198 return Error(Loc,
4199 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
4200 case Match_AddSubRegExtendLarge:
4201 return Error(Loc,
4202 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
4203 case Match_AddSubSecondSource:
4204 return Error(Loc,
4205 "expected compatible register, symbol or integer in range [0, 4095]");
4206 case Match_LogicalSecondSource:
4207 return Error(Loc, "expected compatible register or logical immediate");
4208 case Match_InvalidMovImm32Shift:
4209 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
4210 case Match_InvalidMovImm64Shift:
4211 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
4212 case Match_AddSubRegShift32:
4213 return Error(Loc,
4214 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
4215 case Match_AddSubRegShift64:
4216 return Error(Loc,
4217 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
4218 case Match_InvalidFPImm:
4219 return Error(Loc,
4220 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00004221 case Match_InvalidMemoryIndexedSImm6:
4222 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00004223 case Match_InvalidMemoryIndexedSImm5:
4224 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00004225 case Match_InvalidMemoryIndexed1SImm4:
4226 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00004227 case Match_InvalidMemoryIndexed2SImm4:
4228 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00004229 case Match_InvalidMemoryIndexed3SImm4:
4230 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00004231 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00004232 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004233 case Match_InvalidMemoryIndexed16SImm4:
4234 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00004235 case Match_InvalidMemoryIndexed1SImm6:
4236 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen592718f2018-07-05 07:54:10 +00004237 case Match_InvalidMemoryIndexedSImm8:
4238 return Error(Loc, "index must be an integer in range [-128, 127].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004239 case Match_InvalidMemoryIndexedSImm9:
4240 return Error(Loc, "index must be an integer in range [-256, 255].");
Oliver Stannardc4190282018-10-02 10:04:39 +00004241 case Match_InvalidMemoryIndexed16SImm9:
4242 return Error(Loc, "index must be a multiple of 16 in range [-4096, 4080].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004243 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00004244 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004245 case Match_InvalidMemoryIndexed4SImm7:
4246 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
4247 case Match_InvalidMemoryIndexed8SImm7:
4248 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
4249 case Match_InvalidMemoryIndexed16SImm7:
4250 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00004251 case Match_InvalidMemoryIndexed8UImm5:
4252 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
4253 case Match_InvalidMemoryIndexed4UImm5:
4254 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
4255 case Match_InvalidMemoryIndexed2UImm5:
4256 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00004257 case Match_InvalidMemoryIndexed8UImm6:
4258 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
Oliver Stannardc4190282018-10-02 10:04:39 +00004259 case Match_InvalidMemoryIndexed16UImm6:
4260 return Error(Loc, "index must be a multiple of 16 in range [0, 1008].");
Sander de Smalend8e76492018-05-08 10:46:55 +00004261 case Match_InvalidMemoryIndexed4UImm6:
4262 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
4263 case Match_InvalidMemoryIndexed2UImm6:
4264 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
4265 case Match_InvalidMemoryIndexed1UImm6:
4266 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004267 case Match_InvalidMemoryWExtend8:
4268 return Error(Loc,
4269 "expected 'uxtw' or 'sxtw' with optional shift of #0");
4270 case Match_InvalidMemoryWExtend16:
4271 return Error(Loc,
4272 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
4273 case Match_InvalidMemoryWExtend32:
4274 return Error(Loc,
4275 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
4276 case Match_InvalidMemoryWExtend64:
4277 return Error(Loc,
4278 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
4279 case Match_InvalidMemoryWExtend128:
4280 return Error(Loc,
4281 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
4282 case Match_InvalidMemoryXExtend8:
4283 return Error(Loc,
4284 "expected 'lsl' or 'sxtx' with optional shift of #0");
4285 case Match_InvalidMemoryXExtend16:
4286 return Error(Loc,
4287 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
4288 case Match_InvalidMemoryXExtend32:
4289 return Error(Loc,
4290 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
4291 case Match_InvalidMemoryXExtend64:
4292 return Error(Loc,
4293 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
4294 case Match_InvalidMemoryXExtend128:
4295 return Error(Loc,
4296 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
4297 case Match_InvalidMemoryIndexed1:
4298 return Error(Loc, "index must be an integer in range [0, 4095].");
4299 case Match_InvalidMemoryIndexed2:
4300 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
4301 case Match_InvalidMemoryIndexed4:
4302 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
4303 case Match_InvalidMemoryIndexed8:
4304 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
4305 case Match_InvalidMemoryIndexed16:
4306 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004307 case Match_InvalidImm0_1:
4308 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004309 case Match_InvalidImm0_7:
4310 return Error(Loc, "immediate must be an integer in range [0, 7].");
4311 case Match_InvalidImm0_15:
4312 return Error(Loc, "immediate must be an integer in range [0, 15].");
4313 case Match_InvalidImm0_31:
4314 return Error(Loc, "immediate must be an integer in range [0, 31].");
4315 case Match_InvalidImm0_63:
4316 return Error(Loc, "immediate must be an integer in range [0, 63].");
4317 case Match_InvalidImm0_127:
4318 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004319 case Match_InvalidImm0_255:
4320 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004321 case Match_InvalidImm0_65535:
4322 return Error(Loc, "immediate must be an integer in range [0, 65535].");
4323 case Match_InvalidImm1_8:
4324 return Error(Loc, "immediate must be an integer in range [1, 8].");
4325 case Match_InvalidImm1_16:
4326 return Error(Loc, "immediate must be an integer in range [1, 16].");
4327 case Match_InvalidImm1_32:
4328 return Error(Loc, "immediate must be an integer in range [1, 32].");
4329 case Match_InvalidImm1_64:
4330 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00004331 case Match_InvalidSVEAddSubImm8:
4332 return Error(Loc, "immediate must be an integer in range [0, 255]"
4333 " with a shift amount of 0");
4334 case Match_InvalidSVEAddSubImm16:
4335 case Match_InvalidSVEAddSubImm32:
4336 case Match_InvalidSVEAddSubImm64:
4337 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
4338 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004339 case Match_InvalidSVECpyImm8:
4340 return Error(Loc, "immediate must be an integer in range [-128, 255]"
4341 " with a shift amount of 0");
4342 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00004343 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4344 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004345 case Match_InvalidSVECpyImm32:
4346 case Match_InvalidSVECpyImm64:
4347 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4348 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004349 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004350 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004351 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00004352 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004353 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00004354 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004355 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004356 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004357 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004358 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004359 case Match_InvalidSVEIndexRange0_63:
4360 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4361 case Match_InvalidSVEIndexRange0_31:
4362 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4363 case Match_InvalidSVEIndexRange0_15:
4364 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4365 case Match_InvalidSVEIndexRange0_7:
4366 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4367 case Match_InvalidSVEIndexRange0_3:
4368 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004369 case Match_InvalidLabel:
4370 return Error(Loc, "expected label or encodable integer pc offset");
4371 case Match_MRS:
4372 return Error(Loc, "expected readable system register");
4373 case Match_MSR:
4374 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00004375 case Match_InvalidComplexRotationEven:
4376 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4377 case Match_InvalidComplexRotationOdd:
4378 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004379 case Match_MnemonicFail: {
4380 std::string Suggestion = AArch64MnemonicSpellCheck(
4381 ((AArch64Operand &)*Operands[0]).getToken(),
4382 ComputeAvailableFeatures(STI->getFeatureBits()));
4383 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4384 }
Sander de Smalen367694b2018-04-20 08:54:49 +00004385 case Match_InvalidGPR64shifted8:
4386 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4387 case Match_InvalidGPR64shifted16:
4388 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4389 case Match_InvalidGPR64shifted32:
4390 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4391 case Match_InvalidGPR64shifted64:
4392 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4393 case Match_InvalidGPR64NoXZRshifted8:
4394 return Error(Loc, "register must be x0..x30 without shift");
4395 case Match_InvalidGPR64NoXZRshifted16:
4396 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4397 case Match_InvalidGPR64NoXZRshifted32:
4398 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4399 case Match_InvalidGPR64NoXZRshifted64:
4400 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004401 case Match_InvalidZPR32UXTW8:
4402 case Match_InvalidZPR32SXTW8:
4403 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4404 case Match_InvalidZPR32UXTW16:
4405 case Match_InvalidZPR32SXTW16:
4406 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4407 case Match_InvalidZPR32UXTW32:
4408 case Match_InvalidZPR32SXTW32:
4409 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4410 case Match_InvalidZPR32UXTW64:
4411 case Match_InvalidZPR32SXTW64:
4412 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4413 case Match_InvalidZPR64UXTW8:
4414 case Match_InvalidZPR64SXTW8:
4415 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4416 case Match_InvalidZPR64UXTW16:
4417 case Match_InvalidZPR64SXTW16:
4418 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4419 case Match_InvalidZPR64UXTW32:
4420 case Match_InvalidZPR64SXTW32:
4421 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4422 case Match_InvalidZPR64UXTW64:
4423 case Match_InvalidZPR64SXTW64:
4424 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
Sander de Smalenc69944c2018-07-09 09:58:24 +00004425 case Match_InvalidZPR32LSL8:
4426 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s'");
4427 case Match_InvalidZPR32LSL16:
4428 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #1'");
4429 case Match_InvalidZPR32LSL32:
4430 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #2'");
4431 case Match_InvalidZPR32LSL64:
4432 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004433 case Match_InvalidZPR64LSL8:
4434 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4435 case Match_InvalidZPR64LSL16:
4436 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4437 case Match_InvalidZPR64LSL32:
4438 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4439 case Match_InvalidZPR64LSL64:
4440 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00004441 case Match_InvalidZPR0:
4442 return Error(Loc, "expected register without element width sufix");
4443 case Match_InvalidZPR8:
4444 case Match_InvalidZPR16:
4445 case Match_InvalidZPR32:
4446 case Match_InvalidZPR64:
4447 case Match_InvalidZPR128:
4448 return Error(Loc, "invalid element width");
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004449 case Match_InvalidZPR_3b8:
4450 return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b");
4451 case Match_InvalidZPR_3b16:
4452 return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h");
4453 case Match_InvalidZPR_3b32:
4454 return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s");
4455 case Match_InvalidZPR_4b16:
4456 return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h");
4457 case Match_InvalidZPR_4b32:
4458 return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s");
4459 case Match_InvalidZPR_4b64:
4460 return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004461 case Match_InvalidSVEPattern:
4462 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004463 case Match_InvalidSVEPredicateAnyReg:
4464 case Match_InvalidSVEPredicateBReg:
4465 case Match_InvalidSVEPredicateHReg:
4466 case Match_InvalidSVEPredicateSReg:
4467 case Match_InvalidSVEPredicateDReg:
4468 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004469 case Match_InvalidSVEPredicate3bAnyReg:
4470 case Match_InvalidSVEPredicate3bBReg:
4471 case Match_InvalidSVEPredicate3bHReg:
4472 case Match_InvalidSVEPredicate3bSReg:
4473 case Match_InvalidSVEPredicate3bDReg:
4474 return Error(Loc, "restricted predicate has range [0, 7].");
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004475 case Match_InvalidSVEExactFPImmOperandHalfOne:
4476 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4477 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4478 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4479 case Match_InvalidSVEExactFPImmOperandZeroOne:
4480 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004481 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004482 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004483 }
4484}
4485
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004486static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004487
4488bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4489 OperandVector &Operands,
4490 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004491 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004492 bool MatchingInlineAsm) {
4493 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004494 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4495 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004496
David Blaikie960ea3f2014-06-08 16:18:35 +00004497 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004498 unsigned NumOperands = Operands.size();
4499
4500 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004501 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4502 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004503 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004504 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004505 if (Op3CE) {
4506 uint64_t Op3Val = Op3CE->getValue();
4507 uint64_t NewOp3Val = 0;
4508 uint64_t NewOp4Val = 0;
4509 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004510 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004511 NewOp3Val = (32 - Op3Val) & 0x1f;
4512 NewOp4Val = 31 - Op3Val;
4513 } else {
4514 NewOp3Val = (64 - Op3Val) & 0x3f;
4515 NewOp4Val = 63 - Op3Val;
4516 }
4517
Jim Grosbach13760bd2015-05-30 01:25:56 +00004518 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4519 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004520
4521 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004522 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004523 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004524 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4525 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4526 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004527 }
4528 }
Tim Northover03b99f62015-04-30 18:28:58 +00004529 } else if (NumOperands == 4 && Tok == "bfc") {
4530 // FIXME: Horrible hack to handle BFC->BFM alias.
4531 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4532 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4533 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4534
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004535 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004536 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4537 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4538
4539 if (LSBCE && WidthCE) {
4540 uint64_t LSB = LSBCE->getValue();
4541 uint64_t Width = WidthCE->getValue();
4542
4543 uint64_t RegWidth = 0;
4544 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4545 Op1.getReg()))
4546 RegWidth = 64;
4547 else
4548 RegWidth = 32;
4549
4550 if (LSB >= RegWidth)
4551 return Error(LSBOp.getStartLoc(),
4552 "expected integer in range [0, 31]");
4553 if (Width < 1 || Width > RegWidth)
4554 return Error(WidthOp.getStartLoc(),
4555 "expected integer in range [1, 32]");
4556
4557 uint64_t ImmR = 0;
4558 if (RegWidth == 32)
4559 ImmR = (32 - LSB) & 0x1f;
4560 else
4561 ImmR = (64 - LSB) & 0x3f;
4562
4563 uint64_t ImmS = Width - 1;
4564
4565 if (ImmR != 0 && ImmS >= ImmR)
4566 return Error(WidthOp.getStartLoc(),
4567 "requested insert overflows register");
4568
Jim Grosbach13760bd2015-05-30 01:25:56 +00004569 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4570 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004571 Operands[0] = AArch64Operand::CreateToken(
4572 "bfm", false, Op.getStartLoc(), getContext());
4573 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004574 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4575 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004576 Operands[3] = AArch64Operand::CreateImm(
4577 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4578 Operands.emplace_back(
4579 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4580 WidthOp.getEndLoc(), getContext()));
4581 }
4582 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004583 } else if (NumOperands == 5) {
4584 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4585 // UBFIZ -> UBFM aliases.
4586 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004587 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4588 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4589 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004590
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004591 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004592 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4593 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004594
4595 if (Op3CE && Op4CE) {
4596 uint64_t Op3Val = Op3CE->getValue();
4597 uint64_t Op4Val = Op4CE->getValue();
4598
4599 uint64_t RegWidth = 0;
4600 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004601 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004602 RegWidth = 64;
4603 else
4604 RegWidth = 32;
4605
4606 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004607 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004608 "expected integer in range [0, 31]");
4609 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004610 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004611 "expected integer in range [1, 32]");
4612
4613 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004614 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004615 NewOp3Val = (32 - Op3Val) & 0x1f;
4616 else
4617 NewOp3Val = (64 - Op3Val) & 0x3f;
4618
4619 uint64_t NewOp4Val = Op4Val - 1;
4620
4621 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004622 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004623 "requested insert overflows register");
4624
4625 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004626 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004627 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004628 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004629 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004630 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004631 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004632 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004633 if (Tok == "bfi")
4634 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004635 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004636 else if (Tok == "sbfiz")
4637 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004638 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004639 else if (Tok == "ubfiz")
4640 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004641 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004642 else
4643 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004644 }
4645 }
4646
4647 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4648 // UBFX -> UBFM aliases.
4649 } else if (NumOperands == 5 &&
4650 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004651 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4652 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4653 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004654
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004655 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004656 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4657 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004658
4659 if (Op3CE && Op4CE) {
4660 uint64_t Op3Val = Op3CE->getValue();
4661 uint64_t Op4Val = Op4CE->getValue();
4662
4663 uint64_t RegWidth = 0;
4664 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004665 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004666 RegWidth = 64;
4667 else
4668 RegWidth = 32;
4669
4670 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004671 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004672 "expected integer in range [0, 31]");
4673 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004674 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004675 "expected integer in range [1, 32]");
4676
4677 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4678
4679 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004680 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004681 "requested extract overflows register");
4682
4683 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004684 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004685 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004686 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004687 if (Tok == "bfxil")
4688 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004689 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004690 else if (Tok == "sbfx")
4691 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004692 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004693 else if (Tok == "ubfx")
4694 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004695 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004696 else
4697 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004698 }
4699 }
4700 }
4701 }
Tim Northover9097a072017-12-18 10:36:00 +00004702
4703 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4704 // instruction for FP registers correctly in some rare circumstances. Convert
4705 // it to a safe instruction and warn (because silently changing someone's
4706 // assembly is rude).
4707 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4708 NumOperands == 4 && Tok == "movi") {
4709 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4710 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4711 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4712 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4713 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4714 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4715 if (Suffix.lower() == ".2d" &&
4716 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4717 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4718 " correctly on this CPU, converting to equivalent movi.16b");
4719 // Switch the suffix to .16b.
4720 unsigned Idx = Op1.isToken() ? 1 : 2;
4721 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4722 getContext());
4723 }
4724 }
4725 }
4726
Tim Northover3b0846e2014-05-24 12:50:23 +00004727 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4728 // InstAlias can't quite handle this since the reg classes aren't
4729 // subclasses.
4730 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4731 // The source register can be Wn here, but the matcher expects a
4732 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004733 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004734 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004735 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004736 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4737 Op.getStartLoc(), Op.getEndLoc(),
4738 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004739 }
4740 }
4741 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4742 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004743 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004744 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004745 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004746 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004747 // The source register can be Wn here, but the matcher expects a
4748 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004749 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004750 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004751 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004752 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4753 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004754 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004755 }
4756 }
4757 }
4758 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4759 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004760 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004761 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004762 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004763 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004764 // The source register can be Wn here, but the matcher expects a
4765 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004766 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004767 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004768 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004769 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4770 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004771 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004772 }
4773 }
4774 }
4775
Tim Northover3b0846e2014-05-24 12:50:23 +00004776 MCInst Inst;
4777 // First try to match against the secondary set of tables containing the
4778 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4779 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004780 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004781
4782 // If that fails, try against the alternate table containing long-form NEON:
4783 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004784 if (MatchResult != Match_Success) {
4785 // But first, save the short-form match result: we can use it in case the
4786 // long-form match also fails.
4787 auto ShortFormNEONErrorInfo = ErrorInfo;
4788 auto ShortFormNEONMatchResult = MatchResult;
4789
Tim Northover3b0846e2014-05-24 12:50:23 +00004790 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004791 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004792
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004793 // Now, both matches failed, and the long-form match failed on the mnemonic
4794 // suffix token operand. The short-form match failure is probably more
4795 // relevant: use it instead.
4796 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004797 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004798 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4799 MatchResult = ShortFormNEONMatchResult;
4800 ErrorInfo = ShortFormNEONErrorInfo;
4801 }
4802 }
4803
Tim Northover3b0846e2014-05-24 12:50:23 +00004804 switch (MatchResult) {
4805 case Match_Success: {
4806 // Perform range checking and other semantic validations
4807 SmallVector<SMLoc, 8> OperandLocs;
4808 NumOperands = Operands.size();
4809 for (unsigned i = 1; i < NumOperands; ++i)
4810 OperandLocs.push_back(Operands[i]->getStartLoc());
Sander de Smalen9b333092018-07-30 15:42:46 +00004811 if (validateInstruction(Inst, IDLoc, OperandLocs))
Tim Northover3b0846e2014-05-24 12:50:23 +00004812 return true;
4813
4814 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004815 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004816 return false;
4817 }
4818 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004819 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004820 // Special case the error message for the very common case where only
4821 // a single subtarget feature is missing (neon, e.g.).
4822 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004823 uint64_t Mask = 1;
4824 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4825 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004826 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004827 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004828 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004829 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004830 }
4831 return Error(IDLoc, Msg);
4832 }
4833 case Match_MnemonicFail:
Sander de Smalen0325e302018-07-02 07:34:52 +00004834 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004835 case Match_InvalidOperand: {
4836 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004837
Tim Northover26bb14e2014-08-18 11:49:42 +00004838 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004839 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004840 return Error(IDLoc, "too few operands for instruction",
4841 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004842
David Blaikie960ea3f2014-06-08 16:18:35 +00004843 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004844 if (ErrorLoc == SMLoc())
4845 ErrorLoc = IDLoc;
4846 }
4847 // If the match failed on a suffix token operand, tweak the diagnostic
4848 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004849 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4850 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004851 MatchResult = Match_InvalidSuffix;
4852
Sander de Smalen0325e302018-07-02 07:34:52 +00004853 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004854 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004855 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004856 case Match_InvalidMemoryIndexed1:
4857 case Match_InvalidMemoryIndexed2:
4858 case Match_InvalidMemoryIndexed4:
4859 case Match_InvalidMemoryIndexed8:
4860 case Match_InvalidMemoryIndexed16:
4861 case Match_InvalidCondCode:
4862 case Match_AddSubRegExtendSmall:
4863 case Match_AddSubRegExtendLarge:
4864 case Match_AddSubSecondSource:
4865 case Match_LogicalSecondSource:
4866 case Match_AddSubRegShift32:
4867 case Match_AddSubRegShift64:
4868 case Match_InvalidMovImm32Shift:
4869 case Match_InvalidMovImm64Shift:
4870 case Match_InvalidFPImm:
4871 case Match_InvalidMemoryWExtend8:
4872 case Match_InvalidMemoryWExtend16:
4873 case Match_InvalidMemoryWExtend32:
4874 case Match_InvalidMemoryWExtend64:
4875 case Match_InvalidMemoryWExtend128:
4876 case Match_InvalidMemoryXExtend8:
4877 case Match_InvalidMemoryXExtend16:
4878 case Match_InvalidMemoryXExtend32:
4879 case Match_InvalidMemoryXExtend64:
4880 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004881 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004882 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004883 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004884 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004885 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004886 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004887 case Match_InvalidMemoryIndexed4SImm7:
4888 case Match_InvalidMemoryIndexed8SImm7:
4889 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004890 case Match_InvalidMemoryIndexed8UImm5:
4891 case Match_InvalidMemoryIndexed4UImm5:
4892 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004893 case Match_InvalidMemoryIndexed1UImm6:
4894 case Match_InvalidMemoryIndexed2UImm6:
4895 case Match_InvalidMemoryIndexed4UImm6:
4896 case Match_InvalidMemoryIndexed8UImm6:
Oliver Stannardc4190282018-10-02 10:04:39 +00004897 case Match_InvalidMemoryIndexed16UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004898 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004899 case Match_InvalidMemoryIndexedSImm5:
Sander de Smalen592718f2018-07-05 07:54:10 +00004900 case Match_InvalidMemoryIndexedSImm8:
Tim Northover3b0846e2014-05-24 12:50:23 +00004901 case Match_InvalidMemoryIndexedSImm9:
Oliver Stannardc4190282018-10-02 10:04:39 +00004902 case Match_InvalidMemoryIndexed16SImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004903 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004904 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004905 case Match_InvalidImm0_7:
4906 case Match_InvalidImm0_15:
4907 case Match_InvalidImm0_31:
4908 case Match_InvalidImm0_63:
4909 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004910 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004911 case Match_InvalidImm0_65535:
4912 case Match_InvalidImm1_8:
4913 case Match_InvalidImm1_16:
4914 case Match_InvalidImm1_32:
4915 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004916 case Match_InvalidSVEAddSubImm8:
4917 case Match_InvalidSVEAddSubImm16:
4918 case Match_InvalidSVEAddSubImm32:
4919 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004920 case Match_InvalidSVECpyImm8:
4921 case Match_InvalidSVECpyImm16:
4922 case Match_InvalidSVECpyImm32:
4923 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004924 case Match_InvalidIndexRange1_1:
4925 case Match_InvalidIndexRange0_15:
4926 case Match_InvalidIndexRange0_7:
4927 case Match_InvalidIndexRange0_3:
4928 case Match_InvalidIndexRange0_1:
4929 case Match_InvalidSVEIndexRange0_63:
4930 case Match_InvalidSVEIndexRange0_31:
4931 case Match_InvalidSVEIndexRange0_15:
4932 case Match_InvalidSVEIndexRange0_7:
4933 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004934 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004935 case Match_InvalidComplexRotationEven:
4936 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004937 case Match_InvalidGPR64shifted8:
4938 case Match_InvalidGPR64shifted16:
4939 case Match_InvalidGPR64shifted32:
4940 case Match_InvalidGPR64shifted64:
4941 case Match_InvalidGPR64NoXZRshifted8:
4942 case Match_InvalidGPR64NoXZRshifted16:
4943 case Match_InvalidGPR64NoXZRshifted32:
4944 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004945 case Match_InvalidZPR32UXTW8:
4946 case Match_InvalidZPR32UXTW16:
4947 case Match_InvalidZPR32UXTW32:
4948 case Match_InvalidZPR32UXTW64:
4949 case Match_InvalidZPR32SXTW8:
4950 case Match_InvalidZPR32SXTW16:
4951 case Match_InvalidZPR32SXTW32:
4952 case Match_InvalidZPR32SXTW64:
4953 case Match_InvalidZPR64UXTW8:
4954 case Match_InvalidZPR64SXTW8:
4955 case Match_InvalidZPR64UXTW16:
4956 case Match_InvalidZPR64SXTW16:
4957 case Match_InvalidZPR64UXTW32:
4958 case Match_InvalidZPR64SXTW32:
4959 case Match_InvalidZPR64UXTW64:
4960 case Match_InvalidZPR64SXTW64:
Sander de Smalenc69944c2018-07-09 09:58:24 +00004961 case Match_InvalidZPR32LSL8:
4962 case Match_InvalidZPR32LSL16:
4963 case Match_InvalidZPR32LSL32:
4964 case Match_InvalidZPR32LSL64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004965 case Match_InvalidZPR64LSL8:
4966 case Match_InvalidZPR64LSL16:
4967 case Match_InvalidZPR64LSL32:
4968 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004969 case Match_InvalidZPR0:
4970 case Match_InvalidZPR8:
4971 case Match_InvalidZPR16:
4972 case Match_InvalidZPR32:
4973 case Match_InvalidZPR64:
4974 case Match_InvalidZPR128:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004975 case Match_InvalidZPR_3b8:
4976 case Match_InvalidZPR_3b16:
4977 case Match_InvalidZPR_3b32:
4978 case Match_InvalidZPR_4b16:
4979 case Match_InvalidZPR_4b32:
4980 case Match_InvalidZPR_4b64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004981 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004982 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004983 case Match_InvalidSVEPredicateBReg:
4984 case Match_InvalidSVEPredicateHReg:
4985 case Match_InvalidSVEPredicateSReg:
4986 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004987 case Match_InvalidSVEPredicate3bAnyReg:
4988 case Match_InvalidSVEPredicate3bBReg:
4989 case Match_InvalidSVEPredicate3bHReg:
4990 case Match_InvalidSVEPredicate3bSReg:
4991 case Match_InvalidSVEPredicate3bDReg:
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004992 case Match_InvalidSVEExactFPImmOperandHalfOne:
4993 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4994 case Match_InvalidSVEExactFPImmOperandZeroOne:
Tim Northover3b0846e2014-05-24 12:50:23 +00004995 case Match_MSR:
4996 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004997 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004998 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004999 // Any time we get here, there's nothing fancy to do. Just get the
5000 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00005001 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00005002 if (ErrorLoc == SMLoc())
5003 ErrorLoc = IDLoc;
Sander de Smalen0325e302018-07-02 07:34:52 +00005004 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00005005 }
5006 }
5007
5008 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00005009}
5010
5011/// ParseDirective parses the arm specific directives
5012bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00005013 const MCObjectFileInfo::Environment Format =
5014 getContext().getObjectFileInfo()->getObjectFileType();
5015 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005016
Tim Northover3b0846e2014-05-24 12:50:23 +00005017 StringRef IDVal = DirectiveID.getIdentifier();
5018 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005019 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00005020 parseDirectiveArch(Loc);
5021 else if (IDVal == ".cpu")
5022 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00005023 else if (IDVal == ".tlsdesccall")
5024 parseDirectiveTLSDescCall(Loc);
5025 else if (IDVal == ".ltorg" || IDVal == ".pool")
5026 parseDirectiveLtorg(Loc);
5027 else if (IDVal == ".unreq")
5028 parseDirectiveUnreq(Loc);
Martin Storsjo3e3d39d2018-07-31 09:26:52 +00005029 else if (IDVal == ".inst")
5030 parseDirectiveInst(Loc);
Luke Cheesemanf57d7d82018-12-18 10:37:42 +00005031 else if (IDVal == ".cfi_negate_ra_state")
5032 parseDirectiveCFINegateRAState();
Martin Storsjod4590c32018-08-01 06:50:18 +00005033 else if (IsMachO) {
5034 if (IDVal == MCLOHDirectiveName())
5035 parseDirectiveLOH(IDVal, Loc);
5036 else
5037 return true;
5038 } else
Nirav Davee833c6c2016-11-08 18:31:04 +00005039 return true;
5040 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00005041}
5042
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005043static void ExpandCryptoAEK(AArch64::ArchKind ArchKind,
5044 SmallVector<StringRef, 4> &RequestedExtensions) {
5045 const bool NoCrypto =
5046 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
5047 "nocrypto") != std::end(RequestedExtensions));
5048 const bool Crypto =
5049 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
5050 "crypto") != std::end(RequestedExtensions));
5051
5052 if (!NoCrypto && Crypto) {
5053 switch (ArchKind) {
5054 default:
5055 // Map 'generic' (and others) to sha2 and aes, because
5056 // that was the traditional meaning of crypto.
5057 case AArch64::ArchKind::ARMV8_1A:
5058 case AArch64::ArchKind::ARMV8_2A:
5059 case AArch64::ArchKind::ARMV8_3A:
5060 RequestedExtensions.push_back("sha2");
5061 RequestedExtensions.push_back("aes");
5062 break;
5063 case AArch64::ArchKind::ARMV8_4A:
Oliver Stannard7c3c4ba2018-09-26 12:48:21 +00005064 case AArch64::ArchKind::ARMV8_5A:
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005065 RequestedExtensions.push_back("sm4");
5066 RequestedExtensions.push_back("sha3");
5067 RequestedExtensions.push_back("sha2");
5068 RequestedExtensions.push_back("aes");
5069 break;
5070 }
5071 } else if (NoCrypto) {
5072 switch (ArchKind) {
5073 default:
5074 // Map 'generic' (and others) to sha2 and aes, because
5075 // that was the traditional meaning of crypto.
5076 case AArch64::ArchKind::ARMV8_1A:
5077 case AArch64::ArchKind::ARMV8_2A:
5078 case AArch64::ArchKind::ARMV8_3A:
5079 RequestedExtensions.push_back("nosha2");
5080 RequestedExtensions.push_back("noaes");
5081 break;
5082 case AArch64::ArchKind::ARMV8_4A:
Oliver Stannard7c3c4ba2018-09-26 12:48:21 +00005083 case AArch64::ArchKind::ARMV8_5A:
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005084 RequestedExtensions.push_back("nosm4");
5085 RequestedExtensions.push_back("nosha3");
5086 RequestedExtensions.push_back("nosha2");
5087 RequestedExtensions.push_back("noaes");
5088 break;
5089 }
5090 }
5091}
5092
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005093/// parseDirectiveArch
5094/// ::= .arch token
5095bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
5096 SMLoc ArchLoc = getLoc();
5097
5098 StringRef Arch, ExtensionString;
5099 std::tie(Arch, ExtensionString) =
5100 getParser().parseStringToEndOfStatement().trim().split('+');
5101
Florian Hahn67ddd1d2017-07-27 16:27:56 +00005102 AArch64::ArchKind ID = AArch64::parseArch(Arch);
5103 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00005104 return Error(ArchLoc, "unknown arch name");
5105
5106 if (parseToken(AsmToken::EndOfStatement))
5107 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005108
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005109 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00005110 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005111 AArch64::getArchFeatures(ID, AArch64Features);
5112 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
5113 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005114
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005115 MCSubtargetInfo &STI = copySTI();
5116 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
5117 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
5118
5119 SmallVector<StringRef, 4> RequestedExtensions;
5120 if (!ExtensionString.empty())
5121 ExtensionString.split(RequestedExtensions, '+');
5122
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005123 ExpandCryptoAEK(ID, RequestedExtensions);
5124
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005125 FeatureBitset Features = STI.getFeatureBits();
5126 for (auto Name : RequestedExtensions) {
5127 bool EnableFeature = true;
5128
5129 if (Name.startswith_lower("no")) {
5130 EnableFeature = false;
5131 Name = Name.substr(2);
5132 }
5133
5134 for (const auto &Extension : ExtensionMap) {
5135 if (Extension.Name != Name)
5136 continue;
5137
5138 if (Extension.Features.none())
5139 report_fatal_error("unsupported architectural extension: " + Name);
5140
5141 FeatureBitset ToggleFeatures = EnableFeature
5142 ? (~Features & Extension.Features)
5143 : ( Features & Extension.Features);
5144 uint64_t Features =
5145 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5146 setAvailableFeatures(Features);
5147 break;
5148 }
5149 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005150 return false;
5151}
5152
Tim Northover8b96c7e2017-05-15 19:42:15 +00005153static SMLoc incrementLoc(SMLoc L, int Offset) {
5154 return SMLoc::getFromPointer(L.getPointer() + Offset);
5155}
5156
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005157/// parseDirectiveCPU
5158/// ::= .cpu id
5159bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005160 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005161
5162 StringRef CPU, ExtensionString;
5163 std::tie(CPU, ExtensionString) =
5164 getParser().parseStringToEndOfStatement().trim().split('+');
5165
Nirav Davee833c6c2016-11-08 18:31:04 +00005166 if (parseToken(AsmToken::EndOfStatement))
5167 return true;
5168
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005169 SmallVector<StringRef, 4> RequestedExtensions;
5170 if (!ExtensionString.empty())
5171 ExtensionString.split(RequestedExtensions, '+');
5172
5173 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
5174 // once that is tablegen'ed
5175 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005176 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005177 return false;
5178 }
5179
5180 MCSubtargetInfo &STI = copySTI();
5181 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00005182 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005183
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005184 ExpandCryptoAEK(llvm::AArch64::getCPUArchKind(CPU), RequestedExtensions);
5185
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005186 FeatureBitset Features = STI.getFeatureBits();
5187 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005188 // Advance source location past '+'.
5189 CurLoc = incrementLoc(CurLoc, 1);
5190
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005191 bool EnableFeature = true;
5192
5193 if (Name.startswith_lower("no")) {
5194 EnableFeature = false;
5195 Name = Name.substr(2);
5196 }
5197
Tim Northover8b96c7e2017-05-15 19:42:15 +00005198 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005199 for (const auto &Extension : ExtensionMap) {
5200 if (Extension.Name != Name)
5201 continue;
5202
5203 if (Extension.Features.none())
5204 report_fatal_error("unsupported architectural extension: " + Name);
5205
5206 FeatureBitset ToggleFeatures = EnableFeature
5207 ? (~Features & Extension.Features)
5208 : ( Features & Extension.Features);
5209 uint64_t Features =
5210 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5211 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00005212 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005213
5214 break;
5215 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00005216
5217 if (!FoundExtension)
5218 Error(CurLoc, "unsupported architectural extension");
5219
5220 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005221 }
5222 return false;
5223}
5224
Chad Rosierdcd2a302014-10-22 20:35:57 +00005225/// parseDirectiveInst
5226/// ::= .inst opcode [, ...]
5227bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005228 if (getLexer().is(AsmToken::EndOfStatement))
5229 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005230
Nirav Davee833c6c2016-11-08 18:31:04 +00005231 auto parseOp = [&]() -> bool {
5232 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00005233 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00005234 if (check(getParser().parseExpression(Expr), L, "expected expression"))
5235 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005236 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00005237 if (check(!Value, L, "expected constant expression"))
5238 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005239 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00005240 return false;
5241 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00005242
Nirav Davee833c6c2016-11-08 18:31:04 +00005243 if (parseMany(parseOp))
5244 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005245 return false;
5246}
5247
Tim Northover3b0846e2014-05-24 12:50:23 +00005248// parseDirectiveTLSDescCall:
5249// ::= .tlsdesccall symbol
5250bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
5251 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00005252 if (check(getParser().parseIdentifier(Name), L,
5253 "expected symbol after directive") ||
5254 parseToken(AsmToken::EndOfStatement))
5255 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005256
Jim Grosbach6f482002015-05-18 18:43:14 +00005257 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00005258 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
5259 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00005260
5261 MCInst Inst;
5262 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00005263 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00005264
Akira Hatanakabd9fc282015-11-14 05:20:05 +00005265 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00005266 return false;
5267}
5268
5269/// ::= .loh <lohName | lohId> label1, ..., labelN
5270/// The number of arguments depends on the loh identifier.
5271bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00005272 MCLOHType Kind;
5273 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5274 if (getParser().getTok().isNot(AsmToken::Integer))
5275 return TokError("expected an identifier or a number in directive");
5276 // We successfully get a numeric value for the identifier.
5277 // Check if it is valid.
5278 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00005279 if (Id <= -1U && !isValidMCLOHType(Id))
5280 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00005281 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00005282 } else {
5283 StringRef Name = getTok().getIdentifier();
5284 // We successfully parse an identifier.
5285 // Check if it is a recognized one.
5286 int Id = MCLOHNameToId(Name);
5287
5288 if (Id == -1)
5289 return TokError("invalid identifier in directive");
5290 Kind = (MCLOHType)Id;
5291 }
5292 // Consume the identifier.
5293 Lex();
5294 // Get the number of arguments of this LOH.
5295 int NbArgs = MCLOHIdToNbArgs(Kind);
5296
5297 assert(NbArgs != -1 && "Invalid number of arguments");
5298
5299 SmallVector<MCSymbol *, 3> Args;
5300 for (int Idx = 0; Idx < NbArgs; ++Idx) {
5301 StringRef Name;
5302 if (getParser().parseIdentifier(Name))
5303 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00005304 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00005305
5306 if (Idx + 1 == NbArgs)
5307 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00005308 if (parseToken(AsmToken::Comma,
5309 "unexpected token in '" + Twine(IDVal) + "' directive"))
5310 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005311 }
Nirav Davee833c6c2016-11-08 18:31:04 +00005312 if (parseToken(AsmToken::EndOfStatement,
5313 "unexpected token in '" + Twine(IDVal) + "' directive"))
5314 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005315
5316 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
5317 return false;
5318}
5319
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005320/// parseDirectiveLtorg
5321/// ::= .ltorg | .pool
5322bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005323 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5324 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005325 getTargetStreamer().emitCurrentConstantPool();
5326 return false;
5327}
5328
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005329/// parseDirectiveReq
5330/// ::= name .req registername
5331bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005332 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005333 Parser.Lex(); // Eat the '.req' token.
5334 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00005335 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00005336 unsigned RegNum;
5337 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005338
Sander de Smalen50d87022018-04-19 07:35:08 +00005339 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005340 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00005341 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005342 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00005343
Sander de Smalen50d87022018-04-19 07:35:08 +00005344 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00005345 return true;
5346
Sander de Smalen50d87022018-04-19 07:35:08 +00005347 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00005348 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005349 }
5350
Sander de Smalen50d87022018-04-19 07:35:08 +00005351 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005352 StringRef Kind;
5353 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005354 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00005355 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005356
Sander de Smalen50d87022018-04-19 07:35:08 +00005357 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00005358 return true;
5359
Sander de Smalen50d87022018-04-19 07:35:08 +00005360 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00005361 return Error(SRegLoc,
5362 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00005363 }
5364
Sander de Smalen50d87022018-04-19 07:35:08 +00005365 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00005366 StringRef Kind;
5367 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005368 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00005369
Sander de Smalen50d87022018-04-19 07:35:08 +00005370 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00005371 return true;
5372
Sander de Smalen50d87022018-04-19 07:35:08 +00005373 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00005374 return Error(SRegLoc,
5375 "sve predicate register without type specifier expected");
5376 }
5377
Sander de Smalen50d87022018-04-19 07:35:08 +00005378 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00005379 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005380
5381 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00005382 if (parseToken(AsmToken::EndOfStatement,
5383 "unexpected input in .req directive"))
5384 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005385
Sander de Smalen8e607342017-11-15 15:44:43 +00005386 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00005387 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005388 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
5389
Nirav Dave2364748a2016-09-16 18:30:20 +00005390 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005391}
5392
5393/// parseDirectiveUneq
5394/// ::= .unreq registername
5395bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005396 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00005397 if (getTok().isNot(AsmToken::Identifier))
5398 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005399 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
5400 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00005401 if (parseToken(AsmToken::EndOfStatement))
5402 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005403 return false;
5404}
5405
Luke Cheesemanf57d7d82018-12-18 10:37:42 +00005406bool AArch64AsmParser::parseDirectiveCFINegateRAState() {
5407 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5408 return true;
5409 getStreamer().EmitCFINegateRAState();
5410 return false;
5411}
5412
Tim Northover3b0846e2014-05-24 12:50:23 +00005413bool
5414AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
5415 AArch64MCExpr::VariantKind &ELFRefKind,
5416 MCSymbolRefExpr::VariantKind &DarwinRefKind,
5417 int64_t &Addend) {
5418 ELFRefKind = AArch64MCExpr::VK_INVALID;
5419 DarwinRefKind = MCSymbolRefExpr::VK_None;
5420 Addend = 0;
5421
5422 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5423 ELFRefKind = AE->getKind();
5424 Expr = AE->getSubExpr();
5425 }
5426
5427 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5428 if (SE) {
5429 // It's a simple symbol reference with no addend.
5430 DarwinRefKind = SE->getKind();
5431 return true;
5432 }
5433
David Green85d6a552018-09-18 09:44:53 +00005434 // Check that it looks like a symbol + an addend
5435 MCValue Res;
5436 bool Relocatable = Expr->evaluateAsRelocatable(Res, nullptr, nullptr);
5437 if (!Relocatable || !Res.getSymA() || Res.getSymB())
Tim Northover3b0846e2014-05-24 12:50:23 +00005438 return false;
5439
David Green85d6a552018-09-18 09:44:53 +00005440 DarwinRefKind = Res.getSymA()->getKind();
5441 Addend = Res.getConstant();
Tim Northover3b0846e2014-05-24 12:50:23 +00005442
5443 // It's some symbol reference + a constant addend, but really
5444 // shouldn't use both Darwin and ELF syntax.
5445 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5446 DarwinRefKind == MCSymbolRefExpr::VK_None;
5447}
5448
5449/// Force static initialization.
5450extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00005451 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5452 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5453 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00005454}
5455
5456#define GET_REGISTER_MATCHER
5457#define GET_SUBTARGET_FEATURE_NAME
5458#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00005459#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00005460#include "AArch64GenAsmMatcher.inc"
5461
5462// Define this matcher function after the auto-generated include so we
5463// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00005464unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00005465 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005466 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00005467 // If the kind is a token for a literal immediate, check if our asm
5468 // operand matches. This is for InstAliases which have a fixed-value
5469 // immediate in the syntax.
5470 int64_t ExpectedVal;
5471 switch (Kind) {
5472 default:
5473 return Match_InvalidOperand;
5474 case MCK__35_0:
5475 ExpectedVal = 0;
5476 break;
5477 case MCK__35_1:
5478 ExpectedVal = 1;
5479 break;
5480 case MCK__35_12:
5481 ExpectedVal = 12;
5482 break;
5483 case MCK__35_16:
5484 ExpectedVal = 16;
5485 break;
5486 case MCK__35_2:
5487 ExpectedVal = 2;
5488 break;
5489 case MCK__35_24:
5490 ExpectedVal = 24;
5491 break;
5492 case MCK__35_3:
5493 ExpectedVal = 3;
5494 break;
5495 case MCK__35_32:
5496 ExpectedVal = 32;
5497 break;
5498 case MCK__35_4:
5499 ExpectedVal = 4;
5500 break;
5501 case MCK__35_48:
5502 ExpectedVal = 48;
5503 break;
5504 case MCK__35_6:
5505 ExpectedVal = 6;
5506 break;
5507 case MCK__35_64:
5508 ExpectedVal = 64;
5509 break;
5510 case MCK__35_8:
5511 ExpectedVal = 8;
5512 break;
5513 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005514 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005515 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005516 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005517 if (!CE)
5518 return Match_InvalidOperand;
5519 if (CE->getValue() == ExpectedVal)
5520 return Match_Success;
5521 return Match_InvalidOperand;
5522}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005523
Alex Bradbury58eba092016-11-01 16:32:05 +00005524OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005525AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5526
5527 SMLoc S = getLoc();
5528
5529 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5530 Error(S, "expected register");
5531 return MatchOperand_ParseFail;
5532 }
5533
Sander de Smalen50d87022018-04-19 07:35:08 +00005534 unsigned FirstReg;
5535 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5536 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005537 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005538
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005539 const MCRegisterClass &WRegClass =
5540 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5541 const MCRegisterClass &XRegClass =
5542 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5543
5544 bool isXReg = XRegClass.contains(FirstReg),
5545 isWReg = WRegClass.contains(FirstReg);
5546 if (!isXReg && !isWReg) {
5547 Error(S, "expected first even register of a "
5548 "consecutive same-size even/odd register pair");
5549 return MatchOperand_ParseFail;
5550 }
5551
5552 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5553 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5554
5555 if (FirstEncoding & 0x1) {
5556 Error(S, "expected first even register of a "
5557 "consecutive same-size even/odd register pair");
5558 return MatchOperand_ParseFail;
5559 }
5560
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005561 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005562 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005563 return MatchOperand_ParseFail;
5564 }
5565 // Eat the comma
5566 getParser().Lex();
5567
5568 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005569 unsigned SecondReg;
5570 Res = tryParseScalarRegister(SecondReg);
5571 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005572 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005573
Eugene Zelenko049b0172017-01-06 00:30:53 +00005574 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005575 (isXReg && !XRegClass.contains(SecondReg)) ||
5576 (isWReg && !WRegClass.contains(SecondReg))) {
5577 Error(E,"expected second odd register of a "
5578 "consecutive same-size even/odd register pair");
5579 return MatchOperand_ParseFail;
5580 }
Joel Jones504bf332016-10-24 13:37:13 +00005581
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005582 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005583 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005584 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5585 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5586 } else {
5587 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5588 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5589 }
5590
Florian Hahnc4422242017-11-07 13:07:50 +00005591 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5592 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005593
5594 return MatchOperand_Success;
5595}
Florian Hahn91f11e52017-11-07 16:45:48 +00005596
Sander de Smaleneb896b12018-04-25 09:26:47 +00005597template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005598OperandMatchResultTy
5599AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005600 const SMLoc S = getLoc();
5601 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005602 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005603 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005604
Sander de Smalen8e607342017-11-15 15:44:43 +00005605 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005606 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005607
5608 if (Res != MatchOperand_Success)
5609 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005610
5611 if (ParseSuffix && Kind.empty())
5612 return MatchOperand_NoMatch;
5613
Sander de Smalen73937b72018-04-11 07:36:10 +00005614 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5615 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005616 return MatchOperand_NoMatch;
5617
Sander de Smalen73937b72018-04-11 07:36:10 +00005618 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005619
5620 // No shift/extend is the default.
5621 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5622 Operands.push_back(AArch64Operand::CreateVectorReg(
5623 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5624
Sander de Smalenc33d6682018-06-04 06:40:55 +00005625 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5626 if (Res == MatchOperand_ParseFail)
5627 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005628 return MatchOperand_Success;
5629 }
5630
5631 // Eat the comma
5632 getParser().Lex();
5633
5634 // Match the shift
5635 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5636 Res = tryParseOptionalShiftExtend(ExtOpnd);
5637 if (Res != MatchOperand_Success)
5638 return Res;
5639
5640 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005641 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005642 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5643 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5644 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005645
5646 return MatchOperand_Success;
5647}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005648
5649OperandMatchResultTy
5650AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5651 MCAsmParser &Parser = getParser();
5652
5653 SMLoc SS = getLoc();
5654 const AsmToken &TokE = Parser.getTok();
5655 bool IsHash = TokE.is(AsmToken::Hash);
5656
5657 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5658 return MatchOperand_NoMatch;
5659
5660 int64_t Pattern;
5661 if (IsHash) {
5662 Parser.Lex(); // Eat hash
5663
5664 // Parse the immediate operand.
5665 const MCExpr *ImmVal;
5666 SS = getLoc();
5667 if (Parser.parseExpression(ImmVal))
5668 return MatchOperand_ParseFail;
5669
5670 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5671 if (!MCE)
5672 return MatchOperand_ParseFail;
5673
5674 Pattern = MCE->getValue();
5675 } else {
5676 // Parse the pattern
5677 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5678 if (!Pat)
5679 return MatchOperand_NoMatch;
5680
5681 Parser.Lex();
5682 Pattern = Pat->Encoding;
5683 assert(Pattern >= 0 && Pattern < 32);
5684 }
5685
5686 Operands.push_back(
5687 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5688 SS, getLoc(), getContext()));
5689
5690 return MatchOperand_Success;
5691}