blob: 149b00a29f8c556b9314d667647b55c1fe2bcb6a [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Tim Northover3b0846e2014-05-24 12:50:23 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "MCTargetDesc/AArch64AddressingModes.h"
10#include "MCTargetDesc/AArch64MCExpr.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000011#include "MCTargetDesc/AArch64MCTargetDesc.h"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000012#include "MCTargetDesc/AArch64TargetStreamer.h"
Sander de Smalen9b333092018-07-30 15:42:46 +000013#include "AArch64InstrInfo.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000014#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000015#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000016#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000017#include "llvm/ADT/ArrayRef.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000018#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "llvm/ADT/SmallVector.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000020#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000021#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000023#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000025#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000028#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000029#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000030#include "llvm/MC/MCParser/MCAsmLexer.h"
31#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000032#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000033#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000034#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000035#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSubtargetInfo.h"
38#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000039#include "llvm/MC/MCTargetOptions.h"
40#include "llvm/MC/SubtargetFeature.h"
David Green85d6a552018-09-18 09:44:53 +000041#include "llvm/MC/MCValue.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000042#include "llvm/Support/Casting.h"
43#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000044#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000045#include "llvm/Support/MathExtras.h"
46#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000047#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000049#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000050#include <cassert>
51#include <cctype>
52#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000053#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000054#include <string>
55#include <tuple>
56#include <utility>
57#include <vector>
58
Tim Northover3b0846e2014-05-24 12:50:23 +000059using namespace llvm;
60
61namespace {
62
Sander de Smalencd6be962017-12-20 11:02:42 +000063enum class RegKind {
64 Scalar,
65 NeonVector,
66 SVEDataVector,
67 SVEPredicateVector
68};
Florian Hahnc4422242017-11-07 13:07:50 +000069
Sander de Smalen0325e302018-07-02 07:34:52 +000070enum RegConstraintEqualityTy {
71 EqualsReg,
72 EqualsSuperReg,
73 EqualsSubReg
74};
75
Tim Northover3b0846e2014-05-24 12:50:23 +000076class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000077private:
78 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000079
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000080 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000081 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000082
Sander de Smalen9b333092018-07-30 15:42:46 +000083 class PrefixInfo {
84 public:
85 static PrefixInfo CreateFromInst(const MCInst &Inst, uint64_t TSFlags) {
86 PrefixInfo Prefix;
87 switch (Inst.getOpcode()) {
88 case AArch64::MOVPRFX_ZZ:
89 Prefix.Active = true;
90 Prefix.Dst = Inst.getOperand(0).getReg();
91 break;
92 case AArch64::MOVPRFX_ZPmZ_B:
93 case AArch64::MOVPRFX_ZPmZ_H:
94 case AArch64::MOVPRFX_ZPmZ_S:
95 case AArch64::MOVPRFX_ZPmZ_D:
96 Prefix.Active = true;
97 Prefix.Predicated = true;
98 Prefix.ElementSize = TSFlags & AArch64::ElementSizeMask;
99 assert(Prefix.ElementSize != AArch64::ElementSizeNone &&
100 "No destructive element size set for movprfx");
101 Prefix.Dst = Inst.getOperand(0).getReg();
102 Prefix.Pg = Inst.getOperand(2).getReg();
103 break;
104 case AArch64::MOVPRFX_ZPzZ_B:
105 case AArch64::MOVPRFX_ZPzZ_H:
106 case AArch64::MOVPRFX_ZPzZ_S:
107 case AArch64::MOVPRFX_ZPzZ_D:
108 Prefix.Active = true;
109 Prefix.Predicated = true;
110 Prefix.ElementSize = TSFlags & AArch64::ElementSizeMask;
111 assert(Prefix.ElementSize != AArch64::ElementSizeNone &&
112 "No destructive element size set for movprfx");
113 Prefix.Dst = Inst.getOperand(0).getReg();
114 Prefix.Pg = Inst.getOperand(1).getReg();
115 break;
116 default:
117 break;
118 }
119
120 return Prefix;
121 }
122
123 PrefixInfo() : Active(false), Predicated(false) {}
124 bool isActive() const { return Active; }
125 bool isPredicated() const { return Predicated; }
126 unsigned getElementSize() const {
127 assert(Predicated);
128 return ElementSize;
129 }
130 unsigned getDstReg() const { return Dst; }
131 unsigned getPgReg() const {
132 assert(Predicated);
133 return Pg;
134 }
135
136 private:
137 bool Active;
138 bool Predicated;
139 unsigned ElementSize;
140 unsigned Dst;
141 unsigned Pg;
142 } NextPrefix;
143
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000144 AArch64TargetStreamer &getTargetStreamer() {
145 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
146 return static_cast<AArch64TargetStreamer &>(TS);
147 }
148
Rafael Espindola961d4692014-11-11 05:18:41 +0000149 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +0000150
151 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +0000152 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000153 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
154 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +0000155 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000156 bool parseRegister(OperandVector &Operands);
157 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000158 bool parseNeonVectorList(OperandVector &Operands);
Sander de Smalen18ac8f92018-06-15 15:47:44 +0000159 bool parseOptionalMulOperand(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000160 bool parseOperand(OperandVector &Operands, bool isCondCode,
161 bool invertCondCode);
162
Sander de Smalen0325e302018-07-02 07:34:52 +0000163 bool showMatchError(SMLoc Loc, unsigned ErrCode, uint64_t ErrorInfo,
164 OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000165
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +0000166 bool parseDirectiveArch(SMLoc L);
Martin Storsjo20187772018-12-30 21:06:32 +0000167 bool parseDirectiveArchExtension(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +0000168 bool parseDirectiveCPU(SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +0000169 bool parseDirectiveInst(SMLoc L);
170
Tim Northover3b0846e2014-05-24 12:50:23 +0000171 bool parseDirectiveTLSDescCall(SMLoc L);
172
173 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000174 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000175
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000176 bool parseDirectiveReq(StringRef Name, SMLoc L);
177 bool parseDirectiveUnreq(SMLoc L);
Luke Cheesemanf57d7d82018-12-18 10:37:42 +0000178 bool parseDirectiveCFINegateRAState();
Luke Cheeseman41a9e532018-12-21 10:45:08 +0000179 bool parseDirectiveCFIBKeyFrame();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000180
Sander de Smalen9b333092018-07-30 15:42:46 +0000181 bool validateInstruction(MCInst &Inst, SMLoc &IDLoc,
182 SmallVectorImpl<SMLoc> &Loc);
Tim Northover3b0846e2014-05-24 12:50:23 +0000183 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
184 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000185 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000186 bool MatchingInlineAsm) override;
187/// @name Auto-generated Match Functions
188/// {
189
190#define GET_ASSEMBLER_HEADER
191#include "AArch64GenAsmMatcher.inc"
192
193 /// }
194
Sander de Smalen50d87022018-04-19 07:35:08 +0000195 OperandMatchResultTy tryParseScalarRegister(unsigned &Reg);
196 OperandMatchResultTy tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +0000197 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000198 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
199 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
200 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
201 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
202 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
Sander de Smalen93380372018-05-14 11:54:41 +0000203 template <bool IsSVEPrefetch = false>
Tim Northover3b0846e2014-05-24 12:50:23 +0000204 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000205 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000206 OperandMatchResultTy tryParseBTIHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000207 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
208 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000209 template<bool AddFPZeroAsLiteral>
Tim Northover3b0846e2014-05-24 12:50:23 +0000210 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
Sander de Smalen62770792018-05-25 09:47:52 +0000211 OperandMatchResultTy tryParseImmWithOptionalShift(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000212 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000213 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000214 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000215 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Sander de Smalen0325e302018-07-02 07:34:52 +0000216 template <bool ParseShiftExtend,
217 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg>
Sander de Smalen149916d2018-04-20 07:24:20 +0000218 OperandMatchResultTy tryParseGPROperand(OperandVector &Operands);
Sander de Smaleneb896b12018-04-25 09:26:47 +0000219 template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +0000220 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000221 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000222 template <RegKind VectorKind>
223 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
224 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000225 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000226
227public:
228 enum AArch64MatchResultTy {
229 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
230#define GET_OPERAND_DIAGNOSTIC_TYPES
231#include "AArch64GenAsmMatcher.inc"
232 };
Joel Jones504bf332016-10-24 13:37:13 +0000233 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000234
Akira Hatanakab11ef082015-11-14 06:35:56 +0000235 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000236 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000237 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000238 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000239 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000240 MCStreamer &S = getParser().getStreamer();
241 if (S.getTargetStreamer() == nullptr)
242 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000243
Bill Wendling6ee7f312019-05-09 21:57:44 +0000244 // Alias .hword/.word/.[dx]word to the target-independent
245 // .2byte/.4byte/.8byte directives as they have the same form and
246 // semantics:
247 /// ::= (.hword | .word | .dword | .xword ) [ expression (, expression)* ]
Alex Bradbury0a59f182018-05-23 11:17:20 +0000248 Parser.addAliasForDirective(".hword", ".2byte");
249 Parser.addAliasForDirective(".word", ".4byte");
Bill Wendling6ee7f312019-05-09 21:57:44 +0000250 Parser.addAliasForDirective(".dword", ".8byte");
Alex Bradbury0a59f182018-05-23 11:17:20 +0000251 Parser.addAliasForDirective(".xword", ".8byte");
252
Tim Northover3b0846e2014-05-24 12:50:23 +0000253 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000254 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000255 }
256
Sander de Smalen0325e302018-07-02 07:34:52 +0000257 bool regsEqual(const MCParsedAsmOperand &Op1,
258 const MCParsedAsmOperand &Op2) const override;
Tim Northover3b0846e2014-05-24 12:50:23 +0000259 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
260 SMLoc NameLoc, OperandVector &Operands) override;
261 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
262 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000263 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000264 unsigned Kind) override;
265
266 static bool classifySymbolRef(const MCExpr *Expr,
267 AArch64MCExpr::VariantKind &ELFRefKind,
268 MCSymbolRefExpr::VariantKind &DarwinRefKind,
269 int64_t &Addend);
270};
Tim Northover3b0846e2014-05-24 12:50:23 +0000271
272/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
273/// instruction.
274class AArch64Operand : public MCParsedAsmOperand {
275private:
276 enum KindTy {
277 k_Immediate,
278 k_ShiftedImm,
279 k_CondCode,
280 k_Register,
281 k_VectorList,
282 k_VectorIndex,
283 k_Token,
284 k_SysReg,
285 k_SysCR,
286 k_Prefetch,
287 k_ShiftExtend,
288 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000289 k_Barrier,
290 k_PSBHint,
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000291 k_BTIHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000292 } Kind;
293
294 SMLoc StartLoc, EndLoc;
295
296 struct TokOp {
297 const char *Data;
298 unsigned Length;
299 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
300 };
301
Sander de Smalen149916d2018-04-20 07:24:20 +0000302 // Separate shift/extend operand.
303 struct ShiftExtendOp {
304 AArch64_AM::ShiftExtendType Type;
305 unsigned Amount;
306 bool HasExplicitAmount;
307 };
308
Tim Northover3b0846e2014-05-24 12:50:23 +0000309 struct RegOp {
310 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000311 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000312 int ElementWidth;
Sander de Smalen149916d2018-04-20 07:24:20 +0000313
Sander de Smalen0325e302018-07-02 07:34:52 +0000314 // The register may be allowed as a different register class,
315 // e.g. for GPR64as32 or GPR32as64.
316 RegConstraintEqualityTy EqualityTy;
317
Sander de Smalen149916d2018-04-20 07:24:20 +0000318 // In some cases the shift/extend needs to be explicitly parsed together
319 // with the register, rather than as a separate operand. This is needed
320 // for addressing modes where the instruction as a whole dictates the
321 // scaling/extend, rather than specific bits in the instruction.
322 // By parsing them as a single operand, we avoid the need to pass an
323 // extra operand in all CodeGen patterns (because all operands need to
324 // have an associated value), and we avoid the need to update TableGen to
325 // accept operands that have no associated bits in the instruction.
326 //
327 // An added benefit of parsing them together is that the assembler
328 // can give a sensible diagnostic if the scaling is not correct.
329 //
330 // The default is 'lsl #0' (HasExplicitAmount = false) if no
331 // ShiftExtend is specified.
332 ShiftExtendOp ShiftExtend;
Tim Northover3b0846e2014-05-24 12:50:23 +0000333 };
334
335 struct VectorListOp {
336 unsigned RegNum;
337 unsigned Count;
338 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000339 unsigned ElementWidth;
340 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000341 };
342
343 struct VectorIndexOp {
344 unsigned Val;
345 };
346
347 struct ImmOp {
348 const MCExpr *Val;
349 };
350
351 struct ShiftedImmOp {
352 const MCExpr *Val;
353 unsigned ShiftAmount;
354 };
355
356 struct CondCodeOp {
357 AArch64CC::CondCode Code;
358 };
359
360 struct FPImmOp {
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000361 uint64_t Val; // APFloat value bitcasted to uint64_t.
362 bool IsExact; // describes whether parsed value was exact.
Tim Northover3b0846e2014-05-24 12:50:23 +0000363 };
364
365 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000366 const char *Data;
367 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000368 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000369 };
370
371 struct SysRegOp {
372 const char *Data;
373 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000374 uint32_t MRSReg;
375 uint32_t MSRReg;
376 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000377 };
378
379 struct SysCRImmOp {
380 unsigned Val;
381 };
382
383 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000384 const char *Data;
385 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000386 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000387 };
388
Oliver Stannarda34e4702015-12-01 10:48:51 +0000389 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000390 const char *Data;
391 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000392 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000393 };
394
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000395 struct BTIHintOp {
396 const char *Data;
397 unsigned Length;
398 unsigned Val;
399 };
400
Tim Northover3b0846e2014-05-24 12:50:23 +0000401 struct ExtendOp {
402 unsigned Val;
403 };
404
405 union {
406 struct TokOp Tok;
407 struct RegOp Reg;
408 struct VectorListOp VectorList;
409 struct VectorIndexOp VectorIndex;
410 struct ImmOp Imm;
411 struct ShiftedImmOp ShiftedImm;
412 struct CondCodeOp CondCode;
413 struct FPImmOp FPImm;
414 struct BarrierOp Barrier;
415 struct SysRegOp SysReg;
416 struct SysCRImmOp SysCRImm;
417 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000418 struct PSBHintOp PSBHint;
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000419 struct BTIHintOp BTIHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000420 struct ShiftExtendOp ShiftExtend;
421 };
422
423 // Keep the MCContext around as the MCExprs may need manipulated during
424 // the add<>Operands() calls.
425 MCContext &Ctx;
426
David Blaikie960ea3f2014-06-08 16:18:35 +0000427public:
David Blaikie9f380a32015-03-16 18:06:57 +0000428 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000429
Tim Northover3b0846e2014-05-24 12:50:23 +0000430 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
431 Kind = o.Kind;
432 StartLoc = o.StartLoc;
433 EndLoc = o.EndLoc;
434 switch (Kind) {
435 case k_Token:
436 Tok = o.Tok;
437 break;
438 case k_Immediate:
439 Imm = o.Imm;
440 break;
441 case k_ShiftedImm:
442 ShiftedImm = o.ShiftedImm;
443 break;
444 case k_CondCode:
445 CondCode = o.CondCode;
446 break;
447 case k_FPImm:
448 FPImm = o.FPImm;
449 break;
450 case k_Barrier:
451 Barrier = o.Barrier;
452 break;
453 case k_Register:
454 Reg = o.Reg;
455 break;
456 case k_VectorList:
457 VectorList = o.VectorList;
458 break;
459 case k_VectorIndex:
460 VectorIndex = o.VectorIndex;
461 break;
462 case k_SysReg:
463 SysReg = o.SysReg;
464 break;
465 case k_SysCR:
466 SysCRImm = o.SysCRImm;
467 break;
468 case k_Prefetch:
469 Prefetch = o.Prefetch;
470 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000471 case k_PSBHint:
472 PSBHint = o.PSBHint;
473 break;
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000474 case k_BTIHint:
475 BTIHint = o.BTIHint;
476 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000477 case k_ShiftExtend:
478 ShiftExtend = o.ShiftExtend;
479 break;
480 }
481 }
482
483 /// getStartLoc - Get the location of the first token of this operand.
484 SMLoc getStartLoc() const override { return StartLoc; }
485 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000486 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000487
488 StringRef getToken() const {
489 assert(Kind == k_Token && "Invalid access!");
490 return StringRef(Tok.Data, Tok.Length);
491 }
492
493 bool isTokenSuffix() const {
494 assert(Kind == k_Token && "Invalid access!");
495 return Tok.IsSuffix;
496 }
497
498 const MCExpr *getImm() const {
499 assert(Kind == k_Immediate && "Invalid access!");
500 return Imm.Val;
501 }
502
503 const MCExpr *getShiftedImmVal() const {
504 assert(Kind == k_ShiftedImm && "Invalid access!");
505 return ShiftedImm.Val;
506 }
507
508 unsigned getShiftedImmShift() const {
509 assert(Kind == k_ShiftedImm && "Invalid access!");
510 return ShiftedImm.ShiftAmount;
511 }
512
513 AArch64CC::CondCode getCondCode() const {
514 assert(Kind == k_CondCode && "Invalid access!");
515 return CondCode.Code;
516 }
517
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000518 APFloat getFPImm() const {
519 assert (Kind == k_FPImm && "Invalid access!");
520 return APFloat(APFloat::IEEEdouble(), APInt(64, FPImm.Val, true));
521 }
522
523 bool getFPImmIsExact() const {
524 assert (Kind == k_FPImm && "Invalid access!");
525 return FPImm.IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +0000526 }
527
528 unsigned getBarrier() const {
529 assert(Kind == k_Barrier && "Invalid access!");
530 return Barrier.Val;
531 }
532
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000533 StringRef getBarrierName() const {
534 assert(Kind == k_Barrier && "Invalid access!");
535 return StringRef(Barrier.Data, Barrier.Length);
536 }
537
Tim Northover3b0846e2014-05-24 12:50:23 +0000538 unsigned getReg() const override {
539 assert(Kind == k_Register && "Invalid access!");
540 return Reg.RegNum;
541 }
542
Sander de Smalen0325e302018-07-02 07:34:52 +0000543 RegConstraintEqualityTy getRegEqualityTy() const {
544 assert(Kind == k_Register && "Invalid access!");
545 return Reg.EqualityTy;
546 }
547
Tim Northover3b0846e2014-05-24 12:50:23 +0000548 unsigned getVectorListStart() const {
549 assert(Kind == k_VectorList && "Invalid access!");
550 return VectorList.RegNum;
551 }
552
553 unsigned getVectorListCount() const {
554 assert(Kind == k_VectorList && "Invalid access!");
555 return VectorList.Count;
556 }
557
558 unsigned getVectorIndex() const {
559 assert(Kind == k_VectorIndex && "Invalid access!");
560 return VectorIndex.Val;
561 }
562
563 StringRef getSysReg() const {
564 assert(Kind == k_SysReg && "Invalid access!");
565 return StringRef(SysReg.Data, SysReg.Length);
566 }
567
Tim Northover3b0846e2014-05-24 12:50:23 +0000568 unsigned getSysCR() const {
569 assert(Kind == k_SysCR && "Invalid access!");
570 return SysCRImm.Val;
571 }
572
573 unsigned getPrefetch() const {
574 assert(Kind == k_Prefetch && "Invalid access!");
575 return Prefetch.Val;
576 }
577
Oliver Stannarda34e4702015-12-01 10:48:51 +0000578 unsigned getPSBHint() const {
579 assert(Kind == k_PSBHint && "Invalid access!");
580 return PSBHint.Val;
581 }
582
583 StringRef getPSBHintName() const {
584 assert(Kind == k_PSBHint && "Invalid access!");
585 return StringRef(PSBHint.Data, PSBHint.Length);
586 }
587
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000588 unsigned getBTIHint() const {
589 assert(Kind == k_BTIHint && "Invalid access!");
590 return BTIHint.Val;
591 }
592
593 StringRef getBTIHintName() const {
594 assert(Kind == k_BTIHint && "Invalid access!");
595 return StringRef(BTIHint.Data, BTIHint.Length);
596 }
597
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000598 StringRef getPrefetchName() const {
599 assert(Kind == k_Prefetch && "Invalid access!");
600 return StringRef(Prefetch.Data, Prefetch.Length);
601 }
602
Tim Northover3b0846e2014-05-24 12:50:23 +0000603 AArch64_AM::ShiftExtendType getShiftExtendType() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000604 if (Kind == k_ShiftExtend)
605 return ShiftExtend.Type;
606 if (Kind == k_Register)
607 return Reg.ShiftExtend.Type;
608 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000609 }
610
611 unsigned getShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000612 if (Kind == k_ShiftExtend)
613 return ShiftExtend.Amount;
614 if (Kind == k_Register)
615 return Reg.ShiftExtend.Amount;
616 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000617 }
618
619 bool hasShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000620 if (Kind == k_ShiftExtend)
621 return ShiftExtend.HasExplicitAmount;
622 if (Kind == k_Register)
623 return Reg.ShiftExtend.HasExplicitAmount;
624 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000625 }
626
627 bool isImm() const override { return Kind == k_Immediate; }
628 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000629
Sjoerd Meijera3dad802018-07-06 12:32:33 +0000630 bool isUImm6() const {
631 if (!isImm())
632 return false;
633 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
634 if (!MCE)
635 return false;
636 int64_t Val = MCE->getValue();
637 return (Val >= 0 && Val < 64);
638 }
639
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000640 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
641
Sander de Smalen50ded902018-04-29 17:33:38 +0000642 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
643 return isImmScaled<Bits, Scale>(true);
644 }
645
646 template <int Bits, int Scale> DiagnosticPredicate isUImmScaled() const {
647 return isImmScaled<Bits, Scale>(false);
648 }
649
Sander de Smalenfe17a782018-04-26 12:54:42 +0000650 template <int Bits, int Scale>
Sander de Smalen50ded902018-04-29 17:33:38 +0000651 DiagnosticPredicate isImmScaled(bool Signed) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000652 if (!isImm())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000653 return DiagnosticPredicateTy::NoMatch;
654
Tim Northover3b0846e2014-05-24 12:50:23 +0000655 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
656 if (!MCE)
Sander de Smalenfe17a782018-04-26 12:54:42 +0000657 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000658
Sander de Smalen50ded902018-04-29 17:33:38 +0000659 int64_t MinVal, MaxVal;
660 if (Signed) {
661 int64_t Shift = Bits - 1;
662 MinVal = (int64_t(1) << Shift) * -Scale;
663 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
664 } else {
665 MinVal = 0;
666 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
667 }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000668
Tim Northover3b0846e2014-05-24 12:50:23 +0000669 int64_t Val = MCE->getValue();
Sander de Smalenfe17a782018-04-26 12:54:42 +0000670 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
671 return DiagnosticPredicateTy::Match;
672
673 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +0000674 }
675
Sander de Smalen0325e302018-07-02 07:34:52 +0000676 DiagnosticPredicate isSVEPattern() const {
Sander de Smalen245e0e62018-01-22 10:46:00 +0000677 if (!isImm())
Sander de Smalen0325e302018-07-02 07:34:52 +0000678 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000679 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
680 if (!MCE)
Sander de Smalen0325e302018-07-02 07:34:52 +0000681 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000682 int64_t Val = MCE->getValue();
Sander de Smalen0325e302018-07-02 07:34:52 +0000683 if (Val >= 0 && Val < 32)
684 return DiagnosticPredicateTy::Match;
685 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000686 }
687
David Green85d6a552018-09-18 09:44:53 +0000688 bool isSymbolicUImm12Offset(const MCExpr *Expr) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000689 AArch64MCExpr::VariantKind ELFRefKind;
690 MCSymbolRefExpr::VariantKind DarwinRefKind;
691 int64_t Addend;
692 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
693 Addend)) {
694 // If we don't understand the expression, assume the best and
695 // let the fixup and relocation code deal with it.
696 return true;
697 }
698
699 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
700 ELFRefKind == AArch64MCExpr::VK_LO12 ||
701 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
702 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
703 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
704 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
705 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
706 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000707 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
708 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
709 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000710 // Note that we don't range-check the addend. It's adjusted modulo page
711 // size when converted, so there is no "out of range" condition when using
712 // @pageoff.
David Green85d6a552018-09-18 09:44:53 +0000713 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000714 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
715 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
716 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
717 return Addend == 0;
718 }
719
720 return false;
721 }
722
723 template <int Scale> bool isUImm12Offset() const {
724 if (!isImm())
725 return false;
726
727 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
728 if (!MCE)
David Green85d6a552018-09-18 09:44:53 +0000729 return isSymbolicUImm12Offset(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +0000730
731 int64_t Val = MCE->getValue();
732 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
733 }
734
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000735 template <int N, int M>
736 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000737 if (!isImm())
738 return false;
739 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
740 if (!MCE)
741 return false;
742 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000743 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000744 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000745
Sander de Smalena1c259c2018-01-29 13:05:38 +0000746 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
747 // a logical immediate can always be represented when inverted.
748 template <typename T>
749 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000750 if (!isImm())
751 return false;
752 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
753 if (!MCE)
754 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000755
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000756 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000757 int64_t SVal = typename std::make_signed<T>::type(Val);
758 int64_t UVal = typename std::make_unsigned<T>::type(Val);
759 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000760 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000761
Sander de Smalena1c259c2018-01-29 13:05:38 +0000762 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000763 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000764
Tim Northover3b0846e2014-05-24 12:50:23 +0000765 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000766
Sander de Smalen62770792018-05-25 09:47:52 +0000767 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
768 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
769 /// immediate that can be shifted by 'Shift'.
770 template <unsigned Width>
771 Optional<std::pair<int64_t, unsigned> > getShiftedVal() const {
772 if (isShiftedImm() && Width == getShiftedImmShift())
773 if (auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
774 return std::make_pair(CE->getValue(), Width);
775
776 if (isImm())
777 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
778 int64_t Val = CE->getValue();
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000779 if ((Val != 0) && (uint64_t(Val >> Width) << Width) == uint64_t(Val))
Sander de Smalen62770792018-05-25 09:47:52 +0000780 return std::make_pair(Val >> Width, Width);
781 else
782 return std::make_pair(Val, 0u);
783 }
784
785 return {};
786 }
787
Tim Northover3b0846e2014-05-24 12:50:23 +0000788 bool isAddSubImm() const {
789 if (!isShiftedImm() && !isImm())
790 return false;
791
792 const MCExpr *Expr;
793
794 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
795 if (isShiftedImm()) {
796 unsigned Shift = ShiftedImm.ShiftAmount;
797 Expr = ShiftedImm.Val;
798 if (Shift != 0 && Shift != 12)
799 return false;
800 } else {
801 Expr = getImm();
802 }
803
804 AArch64MCExpr::VariantKind ELFRefKind;
805 MCSymbolRefExpr::VariantKind DarwinRefKind;
806 int64_t Addend;
807 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
808 DarwinRefKind, Addend)) {
809 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
810 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
811 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
812 || ELFRefKind == AArch64MCExpr::VK_LO12
813 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
814 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
815 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
816 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
817 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
818 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000819 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
820 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
821 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000822 }
823
Sander de Smalen98686c62018-05-29 10:39:49 +0000824 // If it's a constant, it should be a real immediate in range.
Sander de Smalen62770792018-05-25 09:47:52 +0000825 if (auto ShiftedVal = getShiftedVal<12>())
826 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
Diana Picusc93518d2016-10-11 09:17:47 +0000827
828 // If it's an expression, we hope for the best and let the fixup/relocation
829 // code deal with it.
830 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000831 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000832
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000833 bool isAddSubImmNeg() const {
834 if (!isShiftedImm() && !isImm())
835 return false;
836
Sander de Smalen98686c62018-05-29 10:39:49 +0000837 // Otherwise it should be a real negative immediate in range.
838 if (auto ShiftedVal = getShiftedVal<12>())
839 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000840
Sander de Smalen98686c62018-05-29 10:39:49 +0000841 return false;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000842 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000843
Sander de Smalen62770792018-05-25 09:47:52 +0000844 // Signed value in the range -128 to +127. For element widths of
845 // 16 bits or higher it may also be a signed multiple of 256 in the
846 // range -32768 to +32512.
847 // For element-width of 8 bits a range of -128 to 255 is accepted,
848 // since a copy of a byte can be either signed/unsigned.
849 template <typename T>
850 DiagnosticPredicate isSVECpyImm() const {
851 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
852 return DiagnosticPredicateTy::NoMatch;
853
854 bool IsByte =
855 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
856 if (auto ShiftedImm = getShiftedVal<8>())
857 if (!(IsByte && ShiftedImm->second) &&
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000858 AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
859 << ShiftedImm->second))
Sander de Smalen62770792018-05-25 09:47:52 +0000860 return DiagnosticPredicateTy::Match;
861
862 return DiagnosticPredicateTy::NearMatch;
863 }
864
Sander de Smalen98686c62018-05-29 10:39:49 +0000865 // Unsigned value in the range 0 to 255. For element widths of
866 // 16 bits or higher it may also be a signed multiple of 256 in the
867 // range 0 to 65280.
868 template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
869 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
870 return DiagnosticPredicateTy::NoMatch;
871
872 bool IsByte =
873 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
874 if (auto ShiftedImm = getShiftedVal<8>())
875 if (!(IsByte && ShiftedImm->second) &&
876 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
877 << ShiftedImm->second))
878 return DiagnosticPredicateTy::Match;
879
880 return DiagnosticPredicateTy::NearMatch;
881 }
882
Sander de Smalen97ca6b92018-06-01 07:25:46 +0000883 template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
884 if (isLogicalImm<T>() && !isSVECpyImm<T>())
885 return DiagnosticPredicateTy::Match;
886 return DiagnosticPredicateTy::NoMatch;
887 }
888
Tim Northover3b0846e2014-05-24 12:50:23 +0000889 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000890
Tim Northover3b0846e2014-05-24 12:50:23 +0000891 bool isSIMDImmType10() const {
892 if (!isImm())
893 return false;
894 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
895 if (!MCE)
896 return false;
897 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
898 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000899
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000900 template<int N>
901 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000902 if (!isImm())
903 return false;
904 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
905 if (!MCE)
906 return true;
907 int64_t Val = MCE->getValue();
908 if (Val & 0x3)
909 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000910 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
911 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000912 }
913
914 bool
915 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
916 if (!isImm())
917 return false;
918
919 AArch64MCExpr::VariantKind ELFRefKind;
920 MCSymbolRefExpr::VariantKind DarwinRefKind;
921 int64_t Addend;
922 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
923 DarwinRefKind, Addend)) {
924 return false;
925 }
926 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
927 return false;
928
929 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
930 if (ELFRefKind == AllowedModifiers[i])
David Green85d6a552018-09-18 09:44:53 +0000931 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000932 }
933
934 return false;
935 }
936
937 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000938 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000939 }
940
941 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000942 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
943 AArch64MCExpr::VK_TPREL_G2,
944 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000945 }
946
947 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000948 return isMovWSymbol({
949 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000950 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
951 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000952 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000953 }
954
955 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000956 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
957 AArch64MCExpr::VK_TPREL_G0,
958 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000959 }
960
961 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000962 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000963 }
964
965 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000966 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000967 }
968
969 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000970 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
971 AArch64MCExpr::VK_TPREL_G1_NC,
972 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000973 }
974
975 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000976 return isMovWSymbol(
977 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
978 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000979 }
980
981 template<int RegWidth, int Shift>
982 bool isMOVZMovAlias() const {
983 if (!isImm()) return false;
984
985 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
986 if (!CE) return false;
987 uint64_t Value = CE->getValue();
988
Tim Northoverdaa1c012016-06-16 01:42:25 +0000989 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000990 }
991
992 template<int RegWidth, int Shift>
993 bool isMOVNMovAlias() const {
994 if (!isImm()) return false;
995
996 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
997 if (!CE) return false;
998 uint64_t Value = CE->getValue();
999
Tim Northoverdaa1c012016-06-16 01:42:25 +00001000 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +00001001 }
1002
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001003 bool isFPImm() const {
1004 return Kind == k_FPImm &&
1005 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt()) != -1;
1006 }
1007
Tim Northover3b0846e2014-05-24 12:50:23 +00001008 bool isBarrier() const { return Kind == k_Barrier; }
1009 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001010
Tim Northover3b0846e2014-05-24 12:50:23 +00001011 bool isMRSSystemRegister() const {
1012 if (!isSysReg()) return false;
1013
Tim Northover7cd58932015-01-22 17:23:04 +00001014 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +00001015 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001016
Tim Northover3b0846e2014-05-24 12:50:23 +00001017 bool isMSRSystemRegister() const {
1018 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +00001019 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +00001020 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001021
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001022 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001023 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +00001024 return (SysReg.PStateField == AArch64PState::PAN ||
Sjoerd Meijer173b7f02018-07-03 12:09:20 +00001025 SysReg.PStateField == AArch64PState::DIT ||
Oliver Stannard8459d342018-09-27 14:05:46 +00001026 SysReg.PStateField == AArch64PState::UAO ||
1027 SysReg.PStateField == AArch64PState::SSBS);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001028 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001029
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001030 bool isSystemPStateFieldWithImm0_15() const {
1031 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +00001032 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +00001033 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001034
Florian Hahnc4422242017-11-07 13:07:50 +00001035 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00001036 return Kind == k_Register;
1037 }
1038
1039 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001040 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
1041 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001042
Florian Hahnc4422242017-11-07 13:07:50 +00001043 bool isNeonVectorReg() const {
1044 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
1045 }
1046
1047 bool isNeonVectorRegLo() const {
1048 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001049 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
1050 Reg.RegNum);
1051 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001052
Sander de Smalencd6be962017-12-20 11:02:42 +00001053 template <unsigned Class> bool isSVEVectorReg() const {
1054 RegKind RK;
1055 switch (Class) {
1056 case AArch64::ZPRRegClassID:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00001057 case AArch64::ZPR_3bRegClassID:
1058 case AArch64::ZPR_4bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +00001059 RK = RegKind::SVEDataVector;
1060 break;
1061 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +00001062 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +00001063 RK = RegKind::SVEPredicateVector;
1064 break;
1065 default:
1066 llvm_unreachable("Unsupport register class");
1067 }
1068
1069 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +00001070 AArch64MCRegisterClasses[Class].contains(getReg());
1071 }
1072
Sander de Smalenfd54a782018-06-04 07:07:35 +00001073 template <unsigned Class> bool isFPRasZPR() const {
1074 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1075 AArch64MCRegisterClasses[Class].contains(getReg());
1076 }
1077
Sander de Smalencd6be962017-12-20 11:02:42 +00001078 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +00001079 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
1080 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
1081 return DiagnosticPredicateTy::NoMatch;
1082
1083 if (isSVEVectorReg<Class>() &&
1084 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
1085 return DiagnosticPredicateTy::Match;
1086
1087 return DiagnosticPredicateTy::NearMatch;
1088 }
1089
1090 template <int ElementWidth, unsigned Class>
1091 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
1092 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
1093 return DiagnosticPredicateTy::NoMatch;
1094
Sander de Smalene1eab422019-03-27 17:23:38 +00001095 if (isSVEVectorReg<Class>() && Reg.ElementWidth == ElementWidth)
Sander de Smalen22176a22018-05-16 15:45:17 +00001096 return DiagnosticPredicateTy::Match;
1097
1098 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00001099 }
1100
Sander de Smaleneb896b12018-04-25 09:26:47 +00001101 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +00001102 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
1103 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +00001104 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
1105 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
1106 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001107 return DiagnosticPredicateTy::NoMatch;
1108
Sander de Smalen5861c262018-04-30 07:24:38 +00001109 // Give a more specific diagnostic when the user has explicitly typed in
1110 // a shift-amount that does not match what is expected, but for which
1111 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
1112 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
1113 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
1114 ShiftExtendTy == AArch64_AM::SXTW) &&
1115 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
1116 return DiagnosticPredicateTy::NoMatch;
1117
1118 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001119 return DiagnosticPredicateTy::Match;
1120
1121 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +00001122 }
1123
Tim Northover3b0846e2014-05-24 12:50:23 +00001124 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001125 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001126 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
1127 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001128
Sander de Smalen0325e302018-07-02 07:34:52 +00001129 bool isGPR64as32() const {
1130 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1131 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(Reg.RegNum);
1132 }
1133
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001134 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001135 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001136 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
1137 Reg.RegNum);
1138 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001139
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001140 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001141 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001142 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1143 Reg.RegNum);
1144 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001145
Sam Parker5f934642017-08-31 09:27:04 +00001146 template<int64_t Angle, int64_t Remainder>
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001147 DiagnosticPredicate isComplexRotation() const {
1148 if (!isImm()) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001149
1150 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001151 if (!CE) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001152 uint64_t Value = CE->getValue();
1153
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001154 if (Value % Angle == Remainder && Value <= 270)
1155 return DiagnosticPredicateTy::Match;
1156 return DiagnosticPredicateTy::NearMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001157 }
1158
Sander de Smalen149916d2018-04-20 07:24:20 +00001159 template <unsigned RegClassID> bool isGPR64() const {
1160 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1161 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1162 }
1163
1164 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001165 DiagnosticPredicate isGPR64WithShiftExtend() const {
1166 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1167 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001168
Sander de Smalenfe17a782018-04-26 12:54:42 +00001169 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1170 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1171 return DiagnosticPredicateTy::Match;
1172 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001173 }
1174
Tim Northover3b0846e2014-05-24 12:50:23 +00001175 /// Is this a vector list with the type implicit (presumably attached to the
1176 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001177 template <RegKind VectorKind, unsigned NumRegs>
1178 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001179 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001180 VectorList.NumElements == 0 &&
1181 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001182 }
1183
Sander de Smalen650234b2018-04-12 11:40:52 +00001184 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1185 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001186 bool isTypedVectorList() const {
1187 if (Kind != k_VectorList)
1188 return false;
1189 if (VectorList.Count != NumRegs)
1190 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001191 if (VectorList.RegisterKind != VectorKind)
1192 return false;
1193 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001194 return false;
1195 return VectorList.NumElements == NumElements;
1196 }
1197
Sander de Smalenc33d6682018-06-04 06:40:55 +00001198 template <int Min, int Max>
1199 DiagnosticPredicate isVectorIndex() const {
1200 if (Kind != k_VectorIndex)
1201 return DiagnosticPredicateTy::NoMatch;
1202 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1203 return DiagnosticPredicateTy::Match;
1204 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001205 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001206
Tim Northover3b0846e2014-05-24 12:50:23 +00001207 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001208
Tim Northover3b0846e2014-05-24 12:50:23 +00001209 bool isTokenEqual(StringRef Str) const {
1210 return Kind == k_Token && getToken() == Str;
1211 }
1212 bool isSysCR() const { return Kind == k_SysCR; }
1213 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001214 bool isPSBHint() const { return Kind == k_PSBHint; }
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001215 bool isBTIHint() const { return Kind == k_BTIHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001216 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1217 bool isShifter() const {
1218 if (!isShiftExtend())
1219 return false;
1220
1221 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1222 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1223 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1224 ST == AArch64_AM::MSL);
1225 }
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001226
1227 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1228 if (Kind != k_FPImm)
1229 return DiagnosticPredicateTy::NoMatch;
1230
1231 if (getFPImmIsExact()) {
1232 // Lookup the immediate from table of supported immediates.
1233 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1234 assert(Desc && "Unknown enum value");
1235
1236 // Calculate its FP value.
1237 APFloat RealVal(APFloat::IEEEdouble());
1238 if (RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero) !=
1239 APFloat::opOK)
1240 llvm_unreachable("FP immediate is not exact");
1241
1242 if (getFPImm().bitwiseIsEqual(RealVal))
1243 return DiagnosticPredicateTy::Match;
1244 }
1245
1246 return DiagnosticPredicateTy::NearMatch;
1247 }
1248
1249 template <unsigned ImmA, unsigned ImmB>
1250 DiagnosticPredicate isExactFPImm() const {
1251 DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1252 if ((Res = isExactFPImm<ImmA>()))
1253 return DiagnosticPredicateTy::Match;
1254 if ((Res = isExactFPImm<ImmB>()))
1255 return DiagnosticPredicateTy::Match;
1256 return Res;
1257 }
1258
Tim Northover3b0846e2014-05-24 12:50:23 +00001259 bool isExtend() const {
1260 if (!isShiftExtend())
1261 return false;
1262
1263 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1264 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1265 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1266 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1267 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1268 ET == AArch64_AM::LSL) &&
1269 getShiftExtendAmount() <= 4;
1270 }
1271
1272 bool isExtend64() const {
1273 if (!isExtend())
1274 return false;
Eli Friedman723835382019-05-03 00:59:52 +00001275 // Make sure the extend expects a 32-bit source register.
Tim Northover3b0846e2014-05-24 12:50:23 +00001276 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
Eli Friedman723835382019-05-03 00:59:52 +00001277 return ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1278 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1279 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW;
Tim Northover3b0846e2014-05-24 12:50:23 +00001280 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001281
Tim Northover3b0846e2014-05-24 12:50:23 +00001282 bool isExtendLSL64() const {
1283 if (!isExtend())
1284 return false;
1285 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1286 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1287 ET == AArch64_AM::LSL) &&
1288 getShiftExtendAmount() <= 4;
1289 }
1290
1291 template<int Width> bool isMemXExtend() const {
1292 if (!isExtend())
1293 return false;
1294 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1295 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1296 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1297 getShiftExtendAmount() == 0);
1298 }
1299
1300 template<int Width> bool isMemWExtend() const {
1301 if (!isExtend())
1302 return false;
1303 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1304 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1305 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1306 getShiftExtendAmount() == 0);
1307 }
1308
1309 template <unsigned width>
1310 bool isArithmeticShifter() const {
1311 if (!isShifter())
1312 return false;
1313
1314 // An arithmetic shifter is LSL, LSR, or ASR.
1315 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1316 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1317 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1318 }
1319
1320 template <unsigned width>
1321 bool isLogicalShifter() const {
1322 if (!isShifter())
1323 return false;
1324
1325 // A logical shifter is LSL, LSR, ASR or ROR.
1326 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1327 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1328 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1329 getShiftExtendAmount() < width;
1330 }
1331
1332 bool isMovImm32Shifter() const {
1333 if (!isShifter())
1334 return false;
1335
1336 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1337 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1338 if (ST != AArch64_AM::LSL)
1339 return false;
1340 uint64_t Val = getShiftExtendAmount();
1341 return (Val == 0 || Val == 16);
1342 }
1343
1344 bool isMovImm64Shifter() const {
1345 if (!isShifter())
1346 return false;
1347
1348 // A MOVi shifter is LSL of 0 or 16.
1349 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1350 if (ST != AArch64_AM::LSL)
1351 return false;
1352 uint64_t Val = getShiftExtendAmount();
1353 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1354 }
1355
1356 bool isLogicalVecShifter() const {
1357 if (!isShifter())
1358 return false;
1359
1360 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1361 unsigned Shift = getShiftExtendAmount();
1362 return getShiftExtendType() == AArch64_AM::LSL &&
1363 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1364 }
1365
1366 bool isLogicalVecHalfWordShifter() const {
1367 if (!isLogicalVecShifter())
1368 return false;
1369
1370 // A logical vector shifter is a left shift by 0 or 8.
1371 unsigned Shift = getShiftExtendAmount();
1372 return getShiftExtendType() == AArch64_AM::LSL &&
1373 (Shift == 0 || Shift == 8);
1374 }
1375
1376 bool isMoveVecShifter() const {
1377 if (!isShiftExtend())
1378 return false;
1379
1380 // A logical vector shifter is a left shift by 8 or 16.
1381 unsigned Shift = getShiftExtendAmount();
1382 return getShiftExtendType() == AArch64_AM::MSL &&
1383 (Shift == 8 || Shift == 16);
1384 }
1385
1386 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1387 // to LDUR/STUR when the offset is not legal for the former but is for
1388 // the latter. As such, in addition to checking for being a legal unscaled
1389 // address, also check that it is not a legal scaled address. This avoids
1390 // ambiguity in the matcher.
1391 template<int Width>
1392 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001393 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001394 }
1395
1396 bool isAdrpLabel() const {
1397 // Validation was handled during parsing, so we just sanity check that
1398 // something didn't go haywire.
1399 if (!isImm())
1400 return false;
1401
1402 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1403 int64_t Val = CE->getValue();
1404 int64_t Min = - (4096 * (1LL << (21 - 1)));
1405 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1406 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1407 }
1408
1409 return true;
1410 }
1411
1412 bool isAdrLabel() const {
1413 // Validation was handled during parsing, so we just sanity check that
1414 // something didn't go haywire.
1415 if (!isImm())
1416 return false;
1417
1418 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1419 int64_t Val = CE->getValue();
1420 int64_t Min = - (1LL << (21 - 1));
1421 int64_t Max = ((1LL << (21 - 1)) - 1);
1422 return Val >= Min && Val <= Max;
1423 }
1424
1425 return true;
1426 }
1427
1428 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1429 // Add as immediates when possible. Null MCExpr = 0.
1430 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001431 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001432 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001433 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001435 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001436 }
1437
1438 void addRegOperands(MCInst &Inst, unsigned N) const {
1439 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001440 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001441 }
1442
1443 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1444 assert(N == 1 && "Invalid number of operands!");
1445 assert(
1446 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1447
1448 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1449 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1450 RI->getEncodingValue(getReg()));
1451
Jim Grosbache9119e42015-05-13 18:37:00 +00001452 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001453 }
1454
Sander de Smalen0325e302018-07-02 07:34:52 +00001455 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1456 assert(N == 1 && "Invalid number of operands!");
1457 assert(
1458 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(getReg()));
1459
1460 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1461 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID).getRegister(
1462 RI->getEncodingValue(getReg()));
1463
1464 Inst.addOperand(MCOperand::createReg(Reg));
1465 }
1466
Sander de Smalenfd54a782018-06-04 07:07:35 +00001467 template <int Width>
1468 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1469 unsigned Base;
1470 switch (Width) {
1471 case 8: Base = AArch64::B0; break;
1472 case 16: Base = AArch64::H0; break;
1473 case 32: Base = AArch64::S0; break;
1474 case 64: Base = AArch64::D0; break;
1475 case 128: Base = AArch64::Q0; break;
1476 default:
1477 llvm_unreachable("Unsupported width");
1478 }
1479 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1480 }
1481
Tim Northover3b0846e2014-05-24 12:50:23 +00001482 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1483 assert(N == 1 && "Invalid number of operands!");
1484 assert(
1485 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001486 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001487 }
1488
1489 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1490 assert(N == 1 && "Invalid number of operands!");
1491 assert(
1492 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001493 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001494 }
1495
1496 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1497 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001498 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001499 }
1500
Sander de Smalen525e3222018-04-12 13:19:32 +00001501 enum VecListIndexType {
1502 VecListIdx_DReg = 0,
1503 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001504 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001505 };
1506
1507 template <VecListIndexType RegTy, unsigned NumRegs>
1508 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001509 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001510 static const unsigned FirstRegs[][5] = {
1511 /* DReg */ { AArch64::Q0,
1512 AArch64::D0, AArch64::D0_D1,
1513 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1514 /* QReg */ { AArch64::Q0,
1515 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001516 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1517 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001518 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001519 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001520 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001521
Sander de Smalen7a210db2018-04-16 10:46:18 +00001522 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1523 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001524
Sander de Smalen525e3222018-04-12 13:19:32 +00001525 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1526 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1527 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001528 }
1529
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001530 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001531 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001532 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001533 }
1534
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001535 template <unsigned ImmIs0, unsigned ImmIs1>
1536 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1537 assert(N == 1 && "Invalid number of operands!");
1538 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1539 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1540 }
1541
Tim Northover3b0846e2014-05-24 12:50:23 +00001542 void addImmOperands(MCInst &Inst, unsigned N) const {
1543 assert(N == 1 && "Invalid number of operands!");
1544 // If this is a pageoff symrefexpr with an addend, adjust the addend
1545 // to be only the page-offset portion. Otherwise, just add the expr
1546 // as-is.
1547 addExpr(Inst, getImm());
1548 }
1549
Sander de Smalen62770792018-05-25 09:47:52 +00001550 template <int Shift>
1551 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001552 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001553 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1554 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1555 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1556 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001557 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001558 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001559 } else {
1560 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001561 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001562 }
1563 }
1564
Sander de Smalen62770792018-05-25 09:47:52 +00001565 template <int Shift>
1566 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001567 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001568 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1569 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1570 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1571 } else
1572 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001573 }
1574
Tim Northover3b0846e2014-05-24 12:50:23 +00001575 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1576 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001577 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001578 }
1579
1580 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1581 assert(N == 1 && "Invalid number of operands!");
1582 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1583 if (!MCE)
1584 addExpr(Inst, getImm());
1585 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001586 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001587 }
1588
1589 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1590 addImmOperands(Inst, N);
1591 }
1592
1593 template<int Scale>
1594 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1595 assert(N == 1 && "Invalid number of operands!");
1596 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1597
1598 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001599 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001600 return;
1601 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001602 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001603 }
1604
Sjoerd Meijera3dad802018-07-06 12:32:33 +00001605 void addUImm6Operands(MCInst &Inst, unsigned N) const {
1606 assert(N == 1 && "Invalid number of operands!");
1607 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1608 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1609 }
1610
Sander de Smalen5c625982018-04-13 12:56:14 +00001611 template <int Scale>
1612 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1613 assert(N == 1 && "Invalid number of operands!");
1614 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1615 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1616 }
1617
Sander de Smalena1c259c2018-01-29 13:05:38 +00001618 template <typename T>
1619 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001620 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001621 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001622 typename std::make_unsigned<T>::type Val = MCE->getValue();
1623 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001624 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001625 }
1626
Sander de Smalena1c259c2018-01-29 13:05:38 +00001627 template <typename T>
1628 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001629 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001630 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001631 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1632 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001633 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001634 }
1635
Tim Northover3b0846e2014-05-24 12:50:23 +00001636 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1637 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001638 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001639 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001640 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001641 }
1642
1643 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1644 // Branch operands don't encode the low bits, so shift them off
1645 // here. If it's a label, however, just put it on directly as there's
1646 // not enough information now to do anything.
1647 assert(N == 1 && "Invalid number of operands!");
1648 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1649 if (!MCE) {
1650 addExpr(Inst, getImm());
1651 return;
1652 }
1653 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001654 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001655 }
1656
1657 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1658 // Branch operands don't encode the low bits, so shift them off
1659 // here. If it's a label, however, just put it on directly as there's
1660 // not enough information now to do anything.
1661 assert(N == 1 && "Invalid number of operands!");
1662 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1663 if (!MCE) {
1664 addExpr(Inst, getImm());
1665 return;
1666 }
1667 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001668 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001669 }
1670
1671 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1672 // Branch operands don't encode the low bits, so shift them off
1673 // here. If it's a label, however, just put it on directly as there's
1674 // not enough information now to do anything.
1675 assert(N == 1 && "Invalid number of operands!");
1676 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1677 if (!MCE) {
1678 addExpr(Inst, getImm());
1679 return;
1680 }
1681 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001682 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001683 }
1684
1685 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1686 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001687 Inst.addOperand(MCOperand::createImm(
1688 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
Tim Northover3b0846e2014-05-24 12:50:23 +00001689 }
1690
1691 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1692 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001693 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001694 }
1695
1696 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1697 assert(N == 1 && "Invalid number of operands!");
1698
Jim Grosbache9119e42015-05-13 18:37:00 +00001699 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001700 }
1701
1702 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1703 assert(N == 1 && "Invalid number of operands!");
1704
Jim Grosbache9119e42015-05-13 18:37:00 +00001705 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001706 }
1707
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001708 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1709 assert(N == 1 && "Invalid number of operands!");
1710
1711 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1712 }
1713
1714 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001715 assert(N == 1 && "Invalid number of operands!");
1716
Jim Grosbache9119e42015-05-13 18:37:00 +00001717 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001718 }
1719
1720 void addSysCROperands(MCInst &Inst, unsigned N) const {
1721 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001722 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001723 }
1724
1725 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1726 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001727 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001728 }
1729
Oliver Stannarda34e4702015-12-01 10:48:51 +00001730 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1731 assert(N == 1 && "Invalid number of operands!");
1732 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1733 }
1734
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001735 void addBTIHintOperands(MCInst &Inst, unsigned N) const {
1736 assert(N == 1 && "Invalid number of operands!");
1737 Inst.addOperand(MCOperand::createImm(getBTIHint()));
1738 }
1739
Tim Northover3b0846e2014-05-24 12:50:23 +00001740 void addShifterOperands(MCInst &Inst, unsigned N) const {
1741 assert(N == 1 && "Invalid number of operands!");
1742 unsigned Imm =
1743 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001744 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001745 }
1746
1747 void addExtendOperands(MCInst &Inst, unsigned N) const {
1748 assert(N == 1 && "Invalid number of operands!");
1749 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1750 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1751 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001752 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001753 }
1754
1755 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1756 assert(N == 1 && "Invalid number of operands!");
1757 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1758 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1759 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001760 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001761 }
1762
1763 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1764 assert(N == 2 && "Invalid number of operands!");
1765 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1766 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001767 Inst.addOperand(MCOperand::createImm(IsSigned));
1768 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001769 }
1770
1771 // For 8-bit load/store instructions with a register offset, both the
1772 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1773 // they're disambiguated by whether the shift was explicit or implicit rather
1774 // than its size.
1775 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1776 assert(N == 2 && "Invalid number of operands!");
1777 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1778 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001779 Inst.addOperand(MCOperand::createImm(IsSigned));
1780 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001781 }
1782
1783 template<int Shift>
1784 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1785 assert(N == 1 && "Invalid number of operands!");
1786
1787 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1788 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001789 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001790 }
1791
1792 template<int Shift>
1793 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1794 assert(N == 1 && "Invalid number of operands!");
1795
1796 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1797 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001798 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001799 }
1800
Sam Parker5f934642017-08-31 09:27:04 +00001801 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1802 assert(N == 1 && "Invalid number of operands!");
1803 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1804 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1805 }
1806
1807 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1808 assert(N == 1 && "Invalid number of operands!");
1809 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1810 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1811 }
1812
Tim Northover3b0846e2014-05-24 12:50:23 +00001813 void print(raw_ostream &OS) const override;
1814
David Blaikie960ea3f2014-06-08 16:18:35 +00001815 static std::unique_ptr<AArch64Operand>
1816 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1817 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001818 Op->Tok.Data = Str.data();
1819 Op->Tok.Length = Str.size();
1820 Op->Tok.IsSuffix = IsSuffix;
1821 Op->StartLoc = S;
1822 Op->EndLoc = S;
1823 return Op;
1824 }
1825
David Blaikie960ea3f2014-06-08 16:18:35 +00001826 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001827 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
Sander de Smalen0325e302018-07-02 07:34:52 +00001828 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
Sander de Smalen149916d2018-04-20 07:24:20 +00001829 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1830 unsigned ShiftAmount = 0,
1831 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001832 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001833 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001834 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001835 Op->Reg.ElementWidth = 0;
Sander de Smalen0325e302018-07-02 07:34:52 +00001836 Op->Reg.EqualityTy = EqTy;
Sander de Smalen149916d2018-04-20 07:24:20 +00001837 Op->Reg.ShiftExtend.Type = ExtTy;
1838 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1839 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001840 Op->StartLoc = S;
1841 Op->EndLoc = E;
1842 return Op;
1843 }
1844
David Blaikie960ea3f2014-06-08 16:18:35 +00001845 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001846 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001847 SMLoc S, SMLoc E, MCContext &Ctx,
1848 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1849 unsigned ShiftAmount = 0,
1850 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001851 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1852 Kind == RegKind::SVEPredicateVector) &&
1853 "Invalid vector kind");
Sander de Smalen0325e302018-07-02 07:34:52 +00001854 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
Sander de Smalen149916d2018-04-20 07:24:20 +00001855 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001856 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001857 return Op;
1858 }
1859
1860 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001861 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001862 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1863 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001864 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001865 Op->VectorList.RegNum = RegNum;
1866 Op->VectorList.Count = Count;
1867 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001868 Op->VectorList.ElementWidth = ElementWidth;
1869 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001870 Op->StartLoc = S;
1871 Op->EndLoc = E;
1872 return Op;
1873 }
1874
David Blaikie960ea3f2014-06-08 16:18:35 +00001875 static std::unique_ptr<AArch64Operand>
1876 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1877 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001878 Op->VectorIndex.Val = Idx;
1879 Op->StartLoc = S;
1880 Op->EndLoc = E;
1881 return Op;
1882 }
1883
David Blaikie960ea3f2014-06-08 16:18:35 +00001884 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1885 SMLoc E, MCContext &Ctx) {
1886 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001887 Op->Imm.Val = Val;
1888 Op->StartLoc = S;
1889 Op->EndLoc = E;
1890 return Op;
1891 }
1892
David Blaikie960ea3f2014-06-08 16:18:35 +00001893 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1894 unsigned ShiftAmount,
1895 SMLoc S, SMLoc E,
1896 MCContext &Ctx) {
1897 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001898 Op->ShiftedImm .Val = Val;
1899 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1900 Op->StartLoc = S;
1901 Op->EndLoc = E;
1902 return Op;
1903 }
1904
David Blaikie960ea3f2014-06-08 16:18:35 +00001905 static std::unique_ptr<AArch64Operand>
1906 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1907 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001908 Op->CondCode.Code = Code;
1909 Op->StartLoc = S;
1910 Op->EndLoc = E;
1911 return Op;
1912 }
1913
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001914 static std::unique_ptr<AArch64Operand>
1915 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001916 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001917 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
1918 Op->FPImm.IsExact = IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +00001919 Op->StartLoc = S;
1920 Op->EndLoc = S;
1921 return Op;
1922 }
1923
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001924 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1925 StringRef Str,
1926 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001927 MCContext &Ctx) {
1928 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001929 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001930 Op->Barrier.Data = Str.data();
1931 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001932 Op->StartLoc = S;
1933 Op->EndLoc = S;
1934 return Op;
1935 }
1936
Tim Northover7cd58932015-01-22 17:23:04 +00001937 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1938 uint32_t MRSReg,
1939 uint32_t MSRReg,
1940 uint32_t PStateField,
1941 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001942 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001943 Op->SysReg.Data = Str.data();
1944 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001945 Op->SysReg.MRSReg = MRSReg;
1946 Op->SysReg.MSRReg = MSRReg;
1947 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001948 Op->StartLoc = S;
1949 Op->EndLoc = S;
1950 return Op;
1951 }
1952
David Blaikie960ea3f2014-06-08 16:18:35 +00001953 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1954 SMLoc E, MCContext &Ctx) {
1955 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001956 Op->SysCRImm.Val = Val;
1957 Op->StartLoc = S;
1958 Op->EndLoc = E;
1959 return Op;
1960 }
1961
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001962 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1963 StringRef Str,
1964 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001965 MCContext &Ctx) {
1966 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001967 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001968 Op->Barrier.Data = Str.data();
1969 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001970 Op->StartLoc = S;
1971 Op->EndLoc = S;
1972 return Op;
1973 }
1974
Oliver Stannarda34e4702015-12-01 10:48:51 +00001975 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1976 StringRef Str,
1977 SMLoc S,
1978 MCContext &Ctx) {
1979 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1980 Op->PSBHint.Val = Val;
1981 Op->PSBHint.Data = Str.data();
1982 Op->PSBHint.Length = Str.size();
1983 Op->StartLoc = S;
1984 Op->EndLoc = S;
1985 return Op;
1986 }
1987
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001988 static std::unique_ptr<AArch64Operand> CreateBTIHint(unsigned Val,
1989 StringRef Str,
1990 SMLoc S,
1991 MCContext &Ctx) {
1992 auto Op = make_unique<AArch64Operand>(k_BTIHint, Ctx);
1993 Op->BTIHint.Val = Val << 1 | 32;
1994 Op->BTIHint.Data = Str.data();
1995 Op->BTIHint.Length = Str.size();
1996 Op->StartLoc = S;
1997 Op->EndLoc = S;
1998 return Op;
1999 }
2000
David Blaikie960ea3f2014-06-08 16:18:35 +00002001 static std::unique_ptr<AArch64Operand>
2002 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
2003 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
2004 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00002005 Op->ShiftExtend.Type = ShOp;
2006 Op->ShiftExtend.Amount = Val;
2007 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
2008 Op->StartLoc = S;
2009 Op->EndLoc = E;
2010 return Op;
2011 }
2012};
2013
2014} // end anonymous namespace.
2015
2016void AArch64Operand::print(raw_ostream &OS) const {
2017 switch (Kind) {
2018 case k_FPImm:
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002019 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
2020 if (!getFPImmIsExact())
2021 OS << " (inexact)";
2022 OS << ">";
Tim Northover3b0846e2014-05-24 12:50:23 +00002023 break;
2024 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00002025 StringRef Name = getBarrierName();
2026 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00002027 OS << "<barrier " << Name << ">";
2028 else
2029 OS << "<barrier invalid #" << getBarrier() << ">";
2030 break;
2031 }
2032 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00002033 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00002034 break;
2035 case k_ShiftedImm: {
2036 unsigned Shift = getShiftedImmShift();
2037 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00002038 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00002039 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
2040 break;
2041 }
2042 case k_CondCode:
2043 OS << "<condcode " << getCondCode() << ">";
2044 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00002045 case k_VectorList: {
2046 OS << "<vectorlist ";
2047 unsigned Reg = getVectorListStart();
2048 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
2049 OS << Reg + i << " ";
2050 OS << ">";
2051 break;
2052 }
2053 case k_VectorIndex:
2054 OS << "<vectorindex " << getVectorIndex() << ">";
2055 break;
2056 case k_SysReg:
2057 OS << "<sysreg: " << getSysReg() << '>';
2058 break;
2059 case k_Token:
2060 OS << "'" << getToken() << "'";
2061 break;
2062 case k_SysCR:
2063 OS << "c" << getSysCR();
2064 break;
2065 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00002066 StringRef Name = getPrefetchName();
2067 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00002068 OS << "<prfop " << Name << ">";
2069 else
2070 OS << "<prfop invalid #" << getPrefetch() << ">";
2071 break;
2072 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00002073 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00002074 OS << getPSBHintName();
2075 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00002076 case k_Register:
2077 OS << "<register " << getReg() << ">";
2078 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
2079 break;
2080 LLVM_FALLTHROUGH;
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00002081 case k_BTIHint:
2082 OS << getBTIHintName();
2083 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00002084 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00002085 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
2086 << getShiftExtendAmount();
2087 if (!hasShiftExtendAmount())
2088 OS << "<imp>";
2089 OS << '>';
2090 break;
2091 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002092}
2093
2094/// @name Auto-generated Match Functions
2095/// {
2096
2097static unsigned MatchRegisterName(StringRef Name);
2098
2099/// }
2100
Florian Hahnc4422242017-11-07 13:07:50 +00002101static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00002102 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00002103 .Case("v0", AArch64::Q0)
2104 .Case("v1", AArch64::Q1)
2105 .Case("v2", AArch64::Q2)
2106 .Case("v3", AArch64::Q3)
2107 .Case("v4", AArch64::Q4)
2108 .Case("v5", AArch64::Q5)
2109 .Case("v6", AArch64::Q6)
2110 .Case("v7", AArch64::Q7)
2111 .Case("v8", AArch64::Q8)
2112 .Case("v9", AArch64::Q9)
2113 .Case("v10", AArch64::Q10)
2114 .Case("v11", AArch64::Q11)
2115 .Case("v12", AArch64::Q12)
2116 .Case("v13", AArch64::Q13)
2117 .Case("v14", AArch64::Q14)
2118 .Case("v15", AArch64::Q15)
2119 .Case("v16", AArch64::Q16)
2120 .Case("v17", AArch64::Q17)
2121 .Case("v18", AArch64::Q18)
2122 .Case("v19", AArch64::Q19)
2123 .Case("v20", AArch64::Q20)
2124 .Case("v21", AArch64::Q21)
2125 .Case("v22", AArch64::Q22)
2126 .Case("v23", AArch64::Q23)
2127 .Case("v24", AArch64::Q24)
2128 .Case("v25", AArch64::Q25)
2129 .Case("v26", AArch64::Q26)
2130 .Case("v27", AArch64::Q27)
2131 .Case("v28", AArch64::Q28)
2132 .Case("v29", AArch64::Q29)
2133 .Case("v30", AArch64::Q30)
2134 .Case("v31", AArch64::Q31)
2135 .Default(0);
2136}
2137
Sander de Smalen73937b72018-04-11 07:36:10 +00002138/// Returns an optional pair of (#elements, element-width) if Suffix
2139/// is a valid vector kind. Where the number of elements in a vector
2140/// or the vector width is implicit or explicitly unknown (but still a
2141/// valid suffix kind), 0 is used.
2142static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2143 RegKind VectorKind) {
2144 std::pair<int, int> Res = {-1, -1};
2145
2146 switch (VectorKind) {
2147 case RegKind::NeonVector:
2148 Res =
2149 StringSwitch<std::pair<int, int>>(Suffix.lower())
2150 .Case("", {0, 0})
2151 .Case(".1d", {1, 64})
2152 .Case(".1q", {1, 128})
2153 // '.2h' needed for fp16 scalar pairwise reductions
2154 .Case(".2h", {2, 16})
2155 .Case(".2s", {2, 32})
2156 .Case(".2d", {2, 64})
2157 // '.4b' is another special case for the ARMv8.2a dot product
2158 // operand
2159 .Case(".4b", {4, 8})
2160 .Case(".4h", {4, 16})
2161 .Case(".4s", {4, 32})
2162 .Case(".8b", {8, 8})
2163 .Case(".8h", {8, 16})
2164 .Case(".16b", {16, 8})
2165 // Accept the width neutral ones, too, for verbose syntax. If those
2166 // aren't used in the right places, the token operand won't match so
2167 // all will work out.
2168 .Case(".b", {0, 8})
2169 .Case(".h", {0, 16})
2170 .Case(".s", {0, 32})
2171 .Case(".d", {0, 64})
2172 .Default({-1, -1});
2173 break;
2174 case RegKind::SVEPredicateVector:
2175 case RegKind::SVEDataVector:
2176 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2177 .Case("", {0, 0})
2178 .Case(".b", {0, 8})
2179 .Case(".h", {0, 16})
2180 .Case(".s", {0, 32})
2181 .Case(".d", {0, 64})
2182 .Case(".q", {0, 128})
2183 .Default({-1, -1});
2184 break;
2185 default:
2186 llvm_unreachable("Unsupported RegKind");
2187 }
2188
2189 if (Res == std::make_pair(-1, -1))
2190 return Optional<std::pair<int, int>>();
2191
2192 return Optional<std::pair<int, int>>(Res);
2193}
2194
2195static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2196 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002197}
2198
Florian Hahn91f11e52017-11-07 16:45:48 +00002199static unsigned matchSVEDataVectorRegName(StringRef Name) {
2200 return StringSwitch<unsigned>(Name.lower())
2201 .Case("z0", AArch64::Z0)
2202 .Case("z1", AArch64::Z1)
2203 .Case("z2", AArch64::Z2)
2204 .Case("z3", AArch64::Z3)
2205 .Case("z4", AArch64::Z4)
2206 .Case("z5", AArch64::Z5)
2207 .Case("z6", AArch64::Z6)
2208 .Case("z7", AArch64::Z7)
2209 .Case("z8", AArch64::Z8)
2210 .Case("z9", AArch64::Z9)
2211 .Case("z10", AArch64::Z10)
2212 .Case("z11", AArch64::Z11)
2213 .Case("z12", AArch64::Z12)
2214 .Case("z13", AArch64::Z13)
2215 .Case("z14", AArch64::Z14)
2216 .Case("z15", AArch64::Z15)
2217 .Case("z16", AArch64::Z16)
2218 .Case("z17", AArch64::Z17)
2219 .Case("z18", AArch64::Z18)
2220 .Case("z19", AArch64::Z19)
2221 .Case("z20", AArch64::Z20)
2222 .Case("z21", AArch64::Z21)
2223 .Case("z22", AArch64::Z22)
2224 .Case("z23", AArch64::Z23)
2225 .Case("z24", AArch64::Z24)
2226 .Case("z25", AArch64::Z25)
2227 .Case("z26", AArch64::Z26)
2228 .Case("z27", AArch64::Z27)
2229 .Case("z28", AArch64::Z28)
2230 .Case("z29", AArch64::Z29)
2231 .Case("z30", AArch64::Z30)
2232 .Case("z31", AArch64::Z31)
2233 .Default(0);
2234}
2235
Sander de Smalencd6be962017-12-20 11:02:42 +00002236static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2237 return StringSwitch<unsigned>(Name.lower())
2238 .Case("p0", AArch64::P0)
2239 .Case("p1", AArch64::P1)
2240 .Case("p2", AArch64::P2)
2241 .Case("p3", AArch64::P3)
2242 .Case("p4", AArch64::P4)
2243 .Case("p5", AArch64::P5)
2244 .Case("p6", AArch64::P6)
2245 .Case("p7", AArch64::P7)
2246 .Case("p8", AArch64::P8)
2247 .Case("p9", AArch64::P9)
2248 .Case("p10", AArch64::P10)
2249 .Case("p11", AArch64::P11)
2250 .Case("p12", AArch64::P12)
2251 .Case("p13", AArch64::P13)
2252 .Case("p14", AArch64::P14)
2253 .Case("p15", AArch64::P15)
2254 .Default(0);
2255}
2256
Tim Northover3b0846e2014-05-24 12:50:23 +00002257bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2258 SMLoc &EndLoc) {
2259 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002260 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002261 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002262 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002263}
2264
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002265// Matches a register name or register alias previously defined by '.req'
2266unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002267 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002268 unsigned RegNum = 0;
2269 if ((RegNum = matchSVEDataVectorRegName(Name)))
2270 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2271
Sander de Smalencd6be962017-12-20 11:02:42 +00002272 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2273 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2274
Sander de Smalenc067c302017-12-20 09:45:45 +00002275 if ((RegNum = MatchNeonVectorRegName(Name)))
2276 return Kind == RegKind::NeonVector ? RegNum : 0;
2277
2278 // The parsed register must be of RegKind Scalar
2279 if ((RegNum = MatchRegisterName(Name)))
2280 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002281
Florian Hahnc4422242017-11-07 13:07:50 +00002282 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002283 // Handle a few common aliases of registers.
2284 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2285 .Case("fp", AArch64::FP)
2286 .Case("lr", AArch64::LR)
2287 .Case("x31", AArch64::XZR)
2288 .Case("w31", AArch64::WZR)
2289 .Default(0))
2290 return Kind == RegKind::Scalar ? RegNum : 0;
2291
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002292 // Check for aliases registered via .req. Canonicalize to lower case.
2293 // That's more consistent since register names are case insensitive, and
2294 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2295 auto Entry = RegisterReqs.find(Name.lower());
2296 if (Entry == RegisterReqs.end())
2297 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002298
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002299 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002300 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002301 RegNum = Entry->getValue().second;
2302 }
2303 return RegNum;
2304}
2305
Sander de Smalen50d87022018-04-19 07:35:08 +00002306/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002307/// Identifier when called, and if it is a register name the token is eaten and
2308/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002309OperandMatchResultTy
2310AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002311 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002312 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002313 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002314 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002315
2316 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002317 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2318 if (Reg == 0)
2319 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002320
Sander de Smalen50d87022018-04-19 07:35:08 +00002321 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002322 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002323 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002324}
2325
Tim Northover3b0846e2014-05-24 12:50:23 +00002326/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002327OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002328AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002329 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002330 SMLoc S = getLoc();
2331
2332 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2333 Error(S, "Expected cN operand where 0 <= N <= 15");
2334 return MatchOperand_ParseFail;
2335 }
2336
2337 StringRef Tok = Parser.getTok().getIdentifier();
2338 if (Tok[0] != 'c' && Tok[0] != 'C') {
2339 Error(S, "Expected cN operand where 0 <= N <= 15");
2340 return MatchOperand_ParseFail;
2341 }
2342
2343 uint32_t CRNum;
2344 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2345 if (BadNum || CRNum > 15) {
2346 Error(S, "Expected cN operand where 0 <= N <= 15");
2347 return MatchOperand_ParseFail;
2348 }
2349
2350 Parser.Lex(); // Eat identifier token.
2351 Operands.push_back(
2352 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2353 return MatchOperand_Success;
2354}
2355
2356/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002357template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002358OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002359AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002360 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002361 SMLoc S = getLoc();
2362 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002363
2364 auto LookupByName = [](StringRef N) {
2365 if (IsSVEPrefetch) {
2366 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2367 return Optional<unsigned>(Res->Encoding);
2368 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2369 return Optional<unsigned>(Res->Encoding);
2370 return Optional<unsigned>();
2371 };
2372
2373 auto LookupByEncoding = [](unsigned E) {
2374 if (IsSVEPrefetch) {
2375 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2376 return Optional<StringRef>(Res->Name);
2377 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2378 return Optional<StringRef>(Res->Name);
2379 return Optional<StringRef>();
2380 };
2381 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2382
Tim Northover3b0846e2014-05-24 12:50:23 +00002383 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002384 // Eat optional hash.
2385 if (parseOptionalToken(AsmToken::Hash) ||
2386 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002387 const MCExpr *ImmVal;
2388 if (getParser().parseExpression(ImmVal))
2389 return MatchOperand_ParseFail;
2390
2391 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2392 if (!MCE) {
2393 TokError("immediate value expected for prefetch operand");
2394 return MatchOperand_ParseFail;
2395 }
2396 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002397 if (prfop > MaxVal) {
2398 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2399 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002400 return MatchOperand_ParseFail;
2401 }
2402
Sander de Smalen93380372018-05-14 11:54:41 +00002403 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002404 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002405 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002406 return MatchOperand_Success;
2407 }
2408
2409 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002410 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002411 return MatchOperand_ParseFail;
2412 }
2413
Sander de Smalen93380372018-05-14 11:54:41 +00002414 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002415 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002416 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002417 return MatchOperand_ParseFail;
2418 }
2419
2420 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002421 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002422 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002423 return MatchOperand_Success;
2424}
2425
Oliver Stannarda34e4702015-12-01 10:48:51 +00002426/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002427OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002428AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2429 MCAsmParser &Parser = getParser();
2430 SMLoc S = getLoc();
2431 const AsmToken &Tok = Parser.getTok();
2432 if (Tok.isNot(AsmToken::Identifier)) {
2433 TokError("invalid operand for instruction");
2434 return MatchOperand_ParseFail;
2435 }
2436
Tim Northovere6ae6762016-07-05 21:23:04 +00002437 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2438 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002439 TokError("invalid operand for instruction");
2440 return MatchOperand_ParseFail;
2441 }
2442
2443 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002444 Operands.push_back(AArch64Operand::CreatePSBHint(
2445 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002446 return MatchOperand_Success;
2447}
2448
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00002449/// tryParseBTIHint - Try to parse a BTI operand, mapped to Hint command
2450OperandMatchResultTy
2451AArch64AsmParser::tryParseBTIHint(OperandVector &Operands) {
2452 MCAsmParser &Parser = getParser();
2453 SMLoc S = getLoc();
2454 const AsmToken &Tok = Parser.getTok();
2455 if (Tok.isNot(AsmToken::Identifier)) {
2456 TokError("invalid operand for instruction");
2457 return MatchOperand_ParseFail;
2458 }
2459
2460 auto BTI = AArch64BTIHint::lookupBTIByName(Tok.getString());
2461 if (!BTI) {
2462 TokError("invalid operand for instruction");
2463 return MatchOperand_ParseFail;
2464 }
2465
2466 Parser.Lex(); // Eat identifier token.
2467 Operands.push_back(AArch64Operand::CreateBTIHint(
2468 BTI->Encoding, Tok.getString(), S, getContext()));
2469 return MatchOperand_Success;
2470}
2471
Tim Northover3b0846e2014-05-24 12:50:23 +00002472/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2473/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002474OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002475AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002476 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002477 SMLoc S = getLoc();
Simon Pilgrim12521b22019-05-08 16:27:24 +00002478 const MCExpr *Expr = nullptr;
Tim Northover3b0846e2014-05-24 12:50:23 +00002479
2480 if (Parser.getTok().is(AsmToken::Hash)) {
2481 Parser.Lex(); // Eat hash token.
2482 }
2483
2484 if (parseSymbolicImmVal(Expr))
2485 return MatchOperand_ParseFail;
2486
2487 AArch64MCExpr::VariantKind ELFRefKind;
2488 MCSymbolRefExpr::VariantKind DarwinRefKind;
2489 int64_t Addend;
2490 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2491 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2492 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2493 // No modifier was specified at all; this is the syntax for an ELF basic
2494 // ADRP relocation (unfortunately).
2495 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002496 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002497 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2498 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2499 Addend != 0) {
2500 Error(S, "gotpage label reference not allowed an addend");
2501 return MatchOperand_ParseFail;
2502 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2503 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2504 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2505 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2506 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2507 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2508 // The operand must be an @page or @gotpage qualified symbolref.
2509 Error(S, "page or gotpage label reference expected");
2510 return MatchOperand_ParseFail;
2511 }
2512 }
2513
2514 // We have either a label reference possibly with addend or an immediate. The
2515 // addend is a raw value here. The linker will adjust it to only reference the
2516 // page.
2517 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2518 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2519
2520 return MatchOperand_Success;
2521}
2522
2523/// tryParseAdrLabel - Parse and validate a source label for the ADR
2524/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002525OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002526AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2527 SMLoc S = getLoc();
Simon Pilgrim12521b22019-05-08 16:27:24 +00002528 const MCExpr *Expr = nullptr;
Tim Northover3b0846e2014-05-24 12:50:23 +00002529
David Green9dd1d452018-08-22 11:31:39 +00002530 // Leave anything with a bracket to the default for SVE
2531 if (getParser().getTok().is(AsmToken::LBrac))
2532 return MatchOperand_NoMatch;
2533
2534 if (getParser().getTok().is(AsmToken::Hash))
2535 getParser().Lex(); // Eat hash token.
2536
2537 if (parseSymbolicImmVal(Expr))
2538 return MatchOperand_ParseFail;
2539
2540 AArch64MCExpr::VariantKind ELFRefKind;
2541 MCSymbolRefExpr::VariantKind DarwinRefKind;
2542 int64_t Addend;
2543 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2544 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2545 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2546 // No modifier was specified at all; this is the syntax for an ELF basic
2547 // ADR relocation (unfortunately).
2548 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS, getContext());
2549 } else {
2550 Error(S, "unexpected adr label");
Sander de Smalenc69944c2018-07-09 09:58:24 +00002551 return MatchOperand_ParseFail;
David Green9dd1d452018-08-22 11:31:39 +00002552 }
Sander de Smalenc69944c2018-07-09 09:58:24 +00002553 }
David Green9dd1d452018-08-22 11:31:39 +00002554
2555 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2556 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2557 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002558}
2559
2560/// tryParseFPImm - A floating point immediate expression operand.
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002561template<bool AddFPZeroAsLiteral>
Alex Bradbury58eba092016-11-01 16:32:05 +00002562OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002563AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002564 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002565 SMLoc S = getLoc();
2566
Nirav Davee833c6c2016-11-08 18:31:04 +00002567 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002568
2569 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002570 bool isNegative = parseOptionalToken(AsmToken::Minus);
2571
Tim Northover3b0846e2014-05-24 12:50:23 +00002572 const AsmToken &Tok = Parser.getTok();
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002573 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2574 if (!Hash)
2575 return MatchOperand_NoMatch;
2576 TokError("invalid floating point immediate");
2577 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002578 }
2579
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002580 // Parse hexadecimal representation.
2581 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2582 if (Tok.getIntVal() > 255 || isNegative) {
2583 TokError("encoded floating point value out of range");
2584 return MatchOperand_ParseFail;
2585 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002586
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002587 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2588 Operands.push_back(
2589 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2590 } else {
2591 // Parse FP representation.
2592 APFloat RealVal(APFloat::IEEEdouble());
2593 auto Status =
2594 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2595 if (isNegative)
2596 RealVal.changeSign();
2597
2598 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2599 Operands.push_back(
2600 AArch64Operand::CreateToken("#0", false, S, getContext()));
2601 Operands.push_back(
2602 AArch64Operand::CreateToken(".0", false, S, getContext()));
2603 } else
2604 Operands.push_back(AArch64Operand::CreateFPImm(
2605 RealVal, Status == APFloat::opOK, S, getContext()));
2606 }
2607
2608 Parser.Lex(); // Eat the token.
2609
2610 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002611}
2612
Sander de Smalen62770792018-05-25 09:47:52 +00002613/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2614/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002615OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002616AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002617 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002618 SMLoc S = getLoc();
2619
2620 if (Parser.getTok().is(AsmToken::Hash))
2621 Parser.Lex(); // Eat '#'
2622 else if (Parser.getTok().isNot(AsmToken::Integer))
2623 // Operand should start from # or should be integer, emit error otherwise.
2624 return MatchOperand_NoMatch;
2625
Simon Pilgrim12521b22019-05-08 16:27:24 +00002626 const MCExpr *Imm = nullptr;
Tim Northover3b0846e2014-05-24 12:50:23 +00002627 if (parseSymbolicImmVal(Imm))
2628 return MatchOperand_ParseFail;
2629 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002630 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002631 Operands.push_back(
2632 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002633 return MatchOperand_Success;
2634 }
2635
2636 // Eat ','
2637 Parser.Lex();
2638
2639 // The optional operand must be "lsl #N" where N is non-negative.
2640 if (!Parser.getTok().is(AsmToken::Identifier) ||
2641 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2642 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2643 return MatchOperand_ParseFail;
2644 }
2645
2646 // Eat 'lsl'
2647 Parser.Lex();
2648
Nirav Davee833c6c2016-11-08 18:31:04 +00002649 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002650
2651 if (Parser.getTok().isNot(AsmToken::Integer)) {
2652 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2653 return MatchOperand_ParseFail;
2654 }
2655
2656 int64_t ShiftAmount = Parser.getTok().getIntVal();
2657
2658 if (ShiftAmount < 0) {
2659 Error(Parser.getTok().getLoc(), "positive shift amount required");
2660 return MatchOperand_ParseFail;
2661 }
2662 Parser.Lex(); // Eat the number
2663
Sander de Smalen62770792018-05-25 09:47:52 +00002664 // Just in case the optional lsl #0 is used for immediates other than zero.
Simon Pilgrim12521b22019-05-08 16:27:24 +00002665 if (ShiftAmount == 0 && Imm != nullptr) {
Sander de Smalen62770792018-05-25 09:47:52 +00002666 SMLoc E = Parser.getTok().getLoc();
2667 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2668 return MatchOperand_Success;
2669 }
2670
Tim Northover3b0846e2014-05-24 12:50:23 +00002671 SMLoc E = Parser.getTok().getLoc();
2672 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2673 S, E, getContext()));
2674 return MatchOperand_Success;
2675}
2676
2677/// parseCondCodeString - Parse a Condition Code string.
2678AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2679 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2680 .Case("eq", AArch64CC::EQ)
2681 .Case("ne", AArch64CC::NE)
2682 .Case("cs", AArch64CC::HS)
2683 .Case("hs", AArch64CC::HS)
2684 .Case("cc", AArch64CC::LO)
2685 .Case("lo", AArch64CC::LO)
2686 .Case("mi", AArch64CC::MI)
2687 .Case("pl", AArch64CC::PL)
2688 .Case("vs", AArch64CC::VS)
2689 .Case("vc", AArch64CC::VC)
2690 .Case("hi", AArch64CC::HI)
2691 .Case("ls", AArch64CC::LS)
2692 .Case("ge", AArch64CC::GE)
2693 .Case("lt", AArch64CC::LT)
2694 .Case("gt", AArch64CC::GT)
2695 .Case("le", AArch64CC::LE)
2696 .Case("al", AArch64CC::AL)
2697 .Case("nv", AArch64CC::NV)
2698 .Default(AArch64CC::Invalid);
Sander de Smalene31e6d42018-07-04 08:50:49 +00002699
2700 if (CC == AArch64CC::Invalid &&
2701 getSTI().getFeatureBits()[AArch64::FeatureSVE])
2702 CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2703 .Case("none", AArch64CC::EQ)
2704 .Case("any", AArch64CC::NE)
2705 .Case("nlast", AArch64CC::HS)
2706 .Case("last", AArch64CC::LO)
2707 .Case("first", AArch64CC::MI)
2708 .Case("nfrst", AArch64CC::PL)
2709 .Case("pmore", AArch64CC::HI)
2710 .Case("plast", AArch64CC::LS)
2711 .Case("tcont", AArch64CC::GE)
2712 .Case("tstop", AArch64CC::LT)
2713 .Default(AArch64CC::Invalid);
2714
Tim Northover3b0846e2014-05-24 12:50:23 +00002715 return CC;
2716}
2717
2718/// parseCondCode - Parse a Condition Code operand.
2719bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2720 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002721 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002722 SMLoc S = getLoc();
2723 const AsmToken &Tok = Parser.getTok();
2724 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2725
2726 StringRef Cond = Tok.getString();
2727 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2728 if (CC == AArch64CC::Invalid)
2729 return TokError("invalid condition code");
2730 Parser.Lex(); // Eat identifier token.
2731
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002732 if (invertCondCode) {
2733 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2734 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002735 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002736 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002737
2738 Operands.push_back(
2739 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2740 return false;
2741}
2742
2743/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2744/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002745OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002746AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002747 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002748 const AsmToken &Tok = Parser.getTok();
2749 std::string LowerID = Tok.getString().lower();
2750 AArch64_AM::ShiftExtendType ShOp =
2751 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2752 .Case("lsl", AArch64_AM::LSL)
2753 .Case("lsr", AArch64_AM::LSR)
2754 .Case("asr", AArch64_AM::ASR)
2755 .Case("ror", AArch64_AM::ROR)
2756 .Case("msl", AArch64_AM::MSL)
2757 .Case("uxtb", AArch64_AM::UXTB)
2758 .Case("uxth", AArch64_AM::UXTH)
2759 .Case("uxtw", AArch64_AM::UXTW)
2760 .Case("uxtx", AArch64_AM::UXTX)
2761 .Case("sxtb", AArch64_AM::SXTB)
2762 .Case("sxth", AArch64_AM::SXTH)
2763 .Case("sxtw", AArch64_AM::SXTW)
2764 .Case("sxtx", AArch64_AM::SXTX)
2765 .Default(AArch64_AM::InvalidShiftExtend);
2766
2767 if (ShOp == AArch64_AM::InvalidShiftExtend)
2768 return MatchOperand_NoMatch;
2769
2770 SMLoc S = Tok.getLoc();
2771 Parser.Lex();
2772
Nirav Davee833c6c2016-11-08 18:31:04 +00002773 bool Hash = parseOptionalToken(AsmToken::Hash);
2774
Tim Northover3b0846e2014-05-24 12:50:23 +00002775 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2776 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2777 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2778 ShOp == AArch64_AM::MSL) {
2779 // We expect a number here.
2780 TokError("expected #imm after shift specifier");
2781 return MatchOperand_ParseFail;
2782 }
2783
Chad Rosier2ff37b82016-12-27 16:58:09 +00002784 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002785 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2786 Operands.push_back(
2787 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2788 return MatchOperand_Success;
2789 }
2790
Chad Rosier2ff37b82016-12-27 16:58:09 +00002791 // Make sure we do actually have a number, identifier or a parenthesized
2792 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002793 SMLoc E = Parser.getTok().getLoc();
2794 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002795 !Parser.getTok().is(AsmToken::LParen) &&
2796 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002797 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002798 return MatchOperand_ParseFail;
2799 }
2800
2801 const MCExpr *ImmVal;
2802 if (getParser().parseExpression(ImmVal))
2803 return MatchOperand_ParseFail;
2804
2805 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2806 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002807 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002808 return MatchOperand_ParseFail;
2809 }
2810
Jim Grosbach57fd2622014-09-23 22:16:02 +00002811 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002812 Operands.push_back(AArch64Operand::CreateShiftExtend(
2813 ShOp, MCE->getValue(), true, S, E, getContext()));
2814 return MatchOperand_Success;
2815}
2816
Oliver Stannard89b16042018-09-26 13:52:27 +00002817static const struct Extension {
2818 const char *Name;
2819 const FeatureBitset Features;
2820} ExtensionMap[] = {
Diogo N. Sampaio9c906732018-12-06 15:39:17 +00002821 {"crc", {AArch64::FeatureCRC}},
2822 {"sm4", {AArch64::FeatureSM4}},
2823 {"sha3", {AArch64::FeatureSHA3}},
2824 {"sha2", {AArch64::FeatureSHA2}},
2825 {"aes", {AArch64::FeatureAES}},
2826 {"crypto", {AArch64::FeatureCrypto}},
2827 {"fp", {AArch64::FeatureFPARMv8}},
2828 {"simd", {AArch64::FeatureNEON}},
2829 {"ras", {AArch64::FeatureRAS}},
2830 {"lse", {AArch64::FeatureLSE}},
Diogo N. Sampaio1eb31c82019-01-09 11:24:15 +00002831 {"predres", {AArch64::FeaturePredRes}},
Diogo N. Sampaio9c906732018-12-06 15:39:17 +00002832 {"ccdp", {AArch64::FeatureCacheDeepPersist}},
2833 {"mte", {AArch64::FeatureMTE}},
2834 {"tlb-rmi", {AArch64::FeatureTLB_RMI}},
2835 {"pan-rwv", {AArch64::FeaturePAN_RWV}},
2836 {"ccpp", {AArch64::FeatureCCPP}},
Martin Storsjo74d93f92018-12-31 10:22:04 +00002837 {"sve", {AArch64::FeatureSVE}},
Cullen Rhodes6dcef8f2019-05-13 10:10:24 +00002838 {"sve2", {AArch64::FeatureSVE2}},
2839 {"sve2-aes", {AArch64::FeatureSVE2AES}},
2840 {"sve2-sm4", {AArch64::FeatureSVE2SM4}},
2841 {"sve2-sha3", {AArch64::FeatureSVE2SHA3}},
2842 {"bitperm", {AArch64::FeatureSVE2BitPerm}},
Diogo N. Sampaio9c906732018-12-06 15:39:17 +00002843 // FIXME: Unsupported extensions
2844 {"pan", {}},
2845 {"lor", {}},
2846 {"rdma", {}},
2847 {"profile", {}},
Oliver Stannard89b16042018-09-26 13:52:27 +00002848};
2849
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002850static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2851 if (FBS[AArch64::HasV8_1aOps])
2852 Str += "ARMv8.1a";
2853 else if (FBS[AArch64::HasV8_2aOps])
2854 Str += "ARMv8.2a";
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002855 else if (FBS[AArch64::HasV8_3aOps])
2856 Str += "ARMv8.3a";
2857 else if (FBS[AArch64::HasV8_4aOps])
2858 Str += "ARMv8.4a";
Oliver Stannard89b16042018-09-26 13:52:27 +00002859 else if (FBS[AArch64::HasV8_5aOps])
2860 Str += "ARMv8.5a";
2861 else {
2862 auto ext = std::find_if(std::begin(ExtensionMap),
2863 std::end(ExtensionMap),
2864 [&](const Extension& e)
2865 // Use & in case multiple features are enabled
2866 { return (FBS & e.Features) != FeatureBitset(); }
2867 );
2868
2869 Str += ext != std::end(ExtensionMap) ? ext->Name : "(unknown)";
2870 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002871}
2872
2873void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2874 SMLoc S) {
2875 const uint16_t Op2 = Encoding & 7;
2876 const uint16_t Cm = (Encoding & 0x78) >> 3;
2877 const uint16_t Cn = (Encoding & 0x780) >> 7;
2878 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2879
2880 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2881
2882 Operands.push_back(
2883 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2884 Operands.push_back(
2885 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2886 Operands.push_back(
2887 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2888 Expr = MCConstantExpr::create(Op2, getContext());
2889 Operands.push_back(
2890 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2891}
2892
Tim Northover3b0846e2014-05-24 12:50:23 +00002893/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2894/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2895bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2896 OperandVector &Operands) {
2897 if (Name.find('.') != StringRef::npos)
2898 return TokError("invalid operand");
2899
2900 Mnemonic = Name;
2901 Operands.push_back(
2902 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2903
Rafael Espindola961d4692014-11-11 05:18:41 +00002904 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002905 const AsmToken &Tok = Parser.getTok();
2906 StringRef Op = Tok.getString();
2907 SMLoc S = Tok.getLoc();
2908
Tim Northover3b0846e2014-05-24 12:50:23 +00002909 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002910 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2911 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002912 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002913 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2914 std::string Str("IC " + std::string(IC->Name) + " requires ");
2915 setRequiredFeatureString(IC->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(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002919 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002920 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2921 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002922 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002923 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2924 std::string Str("DC " + std::string(DC->Name) + " requires ");
2925 setRequiredFeatureString(DC->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(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002929 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002930 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2931 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002932 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002933 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2934 std::string Str("AT " + std::string(AT->Name) + " requires ");
2935 setRequiredFeatureString(AT->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(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002939 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002940 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2941 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002942 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002943 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2944 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2945 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2946 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002947 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002948 createSysAlias(TLBI->Encoding, Operands, S);
Oliver Stannard224428c2018-09-27 13:47:40 +00002949 } else if (Mnemonic == "cfp" || Mnemonic == "dvp" || Mnemonic == "cpp") {
2950 const AArch64PRCTX::PRCTX *PRCTX = AArch64PRCTX::lookupPRCTXByName(Op);
2951 if (!PRCTX)
2952 return TokError("invalid operand for prediction restriction instruction");
2953 else if (!PRCTX->haveFeatures(getSTI().getFeatureBits())) {
2954 std::string Str(
2955 Mnemonic.upper() + std::string(PRCTX->Name) + " requires ");
2956 setRequiredFeatureString(PRCTX->getRequiredFeatures(), Str);
2957 return TokError(Str.c_str());
2958 }
2959 uint16_t PRCTX_Op2 =
2960 Mnemonic == "cfp" ? 4 :
2961 Mnemonic == "dvp" ? 5 :
2962 Mnemonic == "cpp" ? 7 :
2963 0;
2964 assert(PRCTX_Op2 && "Invalid mnemonic for prediction restriction instruction");
2965 createSysAlias(PRCTX->Encoding << 3 | PRCTX_Op2 , Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002966 }
2967
Tim Northover3b0846e2014-05-24 12:50:23 +00002968 Parser.Lex(); // Eat operand.
2969
2970 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2971 bool HasRegister = false;
2972
2973 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002974 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002975 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2976 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002977 HasRegister = true;
2978 }
2979
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002980 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002981 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002982 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002983 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002984
Nirav Davee833c6c2016-11-08 18:31:04 +00002985 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2986 return true;
2987
Tim Northover3b0846e2014-05-24 12:50:23 +00002988 return false;
2989}
2990
Alex Bradbury58eba092016-11-01 16:32:05 +00002991OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002992AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002993 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002994 const AsmToken &Tok = Parser.getTok();
2995
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002996 if (Mnemonic == "tsb" && Tok.isNot(AsmToken::Identifier)) {
2997 TokError("'csync' operand expected");
2998 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002999 // Can be either a #imm style literal or an option name
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003000 } else if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003001 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00003002 const MCExpr *ImmVal;
3003 SMLoc ExprLoc = getLoc();
3004 if (getParser().parseExpression(ImmVal))
3005 return MatchOperand_ParseFail;
3006 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3007 if (!MCE) {
3008 Error(ExprLoc, "immediate value expected for barrier operand");
3009 return MatchOperand_ParseFail;
3010 }
3011 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
3012 Error(ExprLoc, "barrier operand out of range");
3013 return MatchOperand_ParseFail;
3014 }
Tim Northovere6ae6762016-07-05 21:23:04 +00003015 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
3016 Operands.push_back(AArch64Operand::CreateBarrier(
3017 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003018 return MatchOperand_Success;
3019 }
3020
3021 if (Tok.isNot(AsmToken::Identifier)) {
3022 TokError("invalid operand for instruction");
3023 return MatchOperand_ParseFail;
3024 }
3025
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003026 auto TSB = AArch64TSB::lookupTSBByName(Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003027 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00003028 auto DB = AArch64DB::lookupDBByName(Tok.getString());
3029 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003030 TokError("'sy' or #imm operand expected");
3031 return MatchOperand_ParseFail;
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003032 // The only valid named option for TSB is 'csync'
3033 } else if (Mnemonic == "tsb" && (!TSB || TSB->Encoding != AArch64TSB::csync)) {
3034 TokError("'csync' operand expected");
3035 return MatchOperand_ParseFail;
3036 } else if (!DB && !TSB) {
Sjoerd Meijere5b85572017-04-24 08:22:20 +00003037 TokError("invalid barrier option name");
3038 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003039 }
3040
Tim Northovere6ae6762016-07-05 21:23:04 +00003041 Operands.push_back(AArch64Operand::CreateBarrier(
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003042 DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003043 Parser.Lex(); // Consume the option
3044
3045 return MatchOperand_Success;
3046}
3047
Alex Bradbury58eba092016-11-01 16:32:05 +00003048OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003049AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003050 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003051 const AsmToken &Tok = Parser.getTok();
3052
3053 if (Tok.isNot(AsmToken::Identifier))
3054 return MatchOperand_NoMatch;
3055
Tim Northovere6ae6762016-07-05 21:23:04 +00003056 int MRSReg, MSRReg;
3057 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
3058 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
3059 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
3060 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
3061 } else
3062 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00003063
Tim Northovere6ae6762016-07-05 21:23:04 +00003064 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
3065 unsigned PStateImm = -1;
3066 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
3067 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00003068
Tim Northovere6ae6762016-07-05 21:23:04 +00003069 Operands.push_back(
3070 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
3071 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003072 Parser.Lex(); // Eat identifier
3073
3074 return MatchOperand_Success;
3075}
3076
Florian Hahnc4422242017-11-07 13:07:50 +00003077/// tryParseNeonVectorRegister - Parse a vector register operand.
3078bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003079 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003080 if (Parser.getTok().isNot(AsmToken::Identifier))
3081 return true;
3082
3083 SMLoc S = getLoc();
3084 // Check for a vector register specifier first.
3085 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003086 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00003087 OperandMatchResultTy Res =
3088 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
3089 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00003090 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00003091
3092 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
3093 if (!KindRes)
3094 return true;
3095
3096 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00003097 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00003098 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
3099 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00003100
Tim Northover3b0846e2014-05-24 12:50:23 +00003101 // If there was an explicit qualifier, that goes on as a literal text
3102 // operand.
3103 if (!Kind.empty())
3104 Operands.push_back(
3105 AArch64Operand::CreateToken(Kind, false, S, getContext()));
3106
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003107 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3108}
3109
3110OperandMatchResultTy
3111AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00003112 SMLoc SIdx = getLoc();
3113 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003114 const MCExpr *ImmVal;
3115 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003116 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00003117 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3118 if (!MCE) {
3119 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003120 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00003121 }
3122
3123 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003124
Nirav Davee833c6c2016-11-08 18:31:04 +00003125 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003126 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00003127
3128 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
3129 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003130 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003131 }
3132
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003133 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00003134}
3135
Sander de Smalen73937b72018-04-11 07:36:10 +00003136// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00003137// optional kind specifier. If it is a register specifier, eat the token
3138// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00003139OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00003140AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00003141 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00003142 MCAsmParser &Parser = getParser();
3143 const AsmToken &Tok = Parser.getTok();
3144
Florian Hahn91f11e52017-11-07 16:45:48 +00003145 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00003146 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003147
3148 StringRef Name = Tok.getString();
3149 // If there is a kind specifier, it's separated from the register name by
3150 // a '.'.
3151 size_t Start = 0, Next = Name.find('.');
3152 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00003153 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00003154
3155 if (RegNum) {
3156 if (Next != StringRef::npos) {
3157 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00003158 if (!isValidVectorKind(Kind, MatchKind)) {
3159 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00003160 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00003161 }
3162 }
Sander de Smalen8e607342017-11-15 15:44:43 +00003163 Parser.Lex(); // Eat the register token.
3164
3165 Reg = RegNum;
3166 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00003167 }
3168
Sander de Smalen8e607342017-11-15 15:44:43 +00003169 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003170}
3171
Sander de Smalencd6be962017-12-20 11:02:42 +00003172/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
3173OperandMatchResultTy
3174AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
3175 // Check for a SVE predicate register specifier first.
3176 const SMLoc S = getLoc();
3177 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003178 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00003179 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00003180 if (Res != MatchOperand_Success)
3181 return Res;
3182
Sander de Smalen73937b72018-04-11 07:36:10 +00003183 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
3184 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00003185 return MatchOperand_NoMatch;
3186
Sander de Smalen73937b72018-04-11 07:36:10 +00003187 unsigned ElementWidth = KindRes->second;
3188 Operands.push_back(AArch64Operand::CreateVectorReg(
3189 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
3190 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00003191
Sander de Smalen7868e742018-01-09 11:17:06 +00003192 // Not all predicates are followed by a '/m' or '/z'.
3193 MCAsmParser &Parser = getParser();
3194 if (Parser.getTok().isNot(AsmToken::Slash))
3195 return MatchOperand_Success;
3196
3197 // But when they do they shouldn't have an element type suffix.
3198 if (!Kind.empty()) {
3199 Error(S, "not expecting size suffix");
3200 return MatchOperand_ParseFail;
3201 }
3202
3203 // Add a literal slash as operand
3204 Operands.push_back(
3205 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
3206
3207 Parser.Lex(); // Eat the slash.
3208
3209 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00003210 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00003211 if (Pred != "z" && Pred != "m") {
3212 Error(getLoc(), "expecting 'm' or 'z' predication");
3213 return MatchOperand_ParseFail;
3214 }
3215
3216 // Add zero/merge token.
3217 const char *ZM = Pred == "z" ? "z" : "m";
3218 Operands.push_back(
3219 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
3220
3221 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00003222 return MatchOperand_Success;
3223}
3224
Sander de Smalen50d87022018-04-19 07:35:08 +00003225/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00003226bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003227 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00003228 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00003229 return false;
3230
Sander de Smalen149916d2018-04-20 07:24:20 +00003231 // Otherwise try for a scalar register.
3232 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
3233 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003234
Sander de Smalen149916d2018-04-20 07:24:20 +00003235 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003236}
3237
3238bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003239 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003240 bool HasELFModifier = false;
3241 AArch64MCExpr::VariantKind RefKind;
3242
Nirav Davee833c6c2016-11-08 18:31:04 +00003243 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003244 HasELFModifier = true;
3245
Nirav Davee833c6c2016-11-08 18:31:04 +00003246 if (Parser.getTok().isNot(AsmToken::Identifier))
3247 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003248
3249 std::string LowerCase = Parser.getTok().getIdentifier().lower();
3250 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
3251 .Case("lo12", AArch64MCExpr::VK_LO12)
3252 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
3253 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
3254 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
3255 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
3256 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
3257 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
3258 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
3259 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
3260 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
3261 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
3262 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
3263 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
3264 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3265 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3266 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3267 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3268 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3269 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3270 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3271 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3272 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3273 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3274 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3275 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3276 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3277 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3278 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3279 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3280 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3281 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3282 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3283 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3284 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3285 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003286 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3287 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00003288 .Default(AArch64MCExpr::VK_INVALID);
3289
Nirav Davee833c6c2016-11-08 18:31:04 +00003290 if (RefKind == AArch64MCExpr::VK_INVALID)
3291 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003292
3293 Parser.Lex(); // Eat identifier
3294
Nirav Davee833c6c2016-11-08 18:31:04 +00003295 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003296 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003297 }
3298
3299 if (getParser().parseExpression(ImmVal))
3300 return true;
3301
3302 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003303 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003304
3305 return false;
3306}
3307
Sander de Smalen650234b2018-04-12 11:40:52 +00003308template <RegKind VectorKind>
3309OperandMatchResultTy
3310AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3311 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003312 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003313 if (!Parser.getTok().is(AsmToken::LCurly))
3314 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003315
3316 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003317 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003318 bool NoMatchIsError) {
3319 auto RegTok = Parser.getTok();
3320 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3321 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003322 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003323 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003324 llvm_unreachable("Expected a valid vector kind");
3325 }
3326
Sander de Smalen650234b2018-04-12 11:40:52 +00003327 if (RegTok.isNot(AsmToken::Identifier) ||
3328 ParseRes == MatchOperand_ParseFail ||
3329 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3330 Error(Loc, "vector register expected");
3331 return MatchOperand_ParseFail;
3332 }
3333
3334 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003335 };
3336
Tim Northover3b0846e2014-05-24 12:50:23 +00003337 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003338 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003339 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003340
Tim Northover3b0846e2014-05-24 12:50:23 +00003341 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003342 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003343 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3344
3345 // Put back the original left bracket if there was no match, so that
3346 // different types of list-operands can be matched (e.g. SVE, Neon).
3347 if (ParseRes == MatchOperand_NoMatch)
3348 Parser.getLexer().UnLex(LCurly);
3349
3350 if (ParseRes != MatchOperand_Success)
3351 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003352
Tim Northover3b0846e2014-05-24 12:50:23 +00003353 int64_t PrevReg = FirstReg;
3354 unsigned Count = 1;
3355
Nirav Davee833c6c2016-11-08 18:31:04 +00003356 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003357 SMLoc Loc = getLoc();
3358 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003359
Sander de Smalen50d87022018-04-19 07:35:08 +00003360 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003361 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3362 if (ParseRes != MatchOperand_Success)
3363 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003364
Tim Northover3b0846e2014-05-24 12:50:23 +00003365 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003366 if (Kind != NextKind) {
3367 Error(Loc, "mismatched register size suffix");
3368 return MatchOperand_ParseFail;
3369 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003370
3371 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3372
3373 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003374 Error(Loc, "invalid number of vectors");
3375 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003376 }
3377
3378 Count += Space;
3379 }
3380 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003381 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003382 SMLoc Loc = getLoc();
3383 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003384 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003385 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3386 if (ParseRes != MatchOperand_Success)
3387 return ParseRes;
3388
Tim Northover3b0846e2014-05-24 12:50:23 +00003389 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003390 if (Kind != NextKind) {
3391 Error(Loc, "mismatched register size suffix");
3392 return MatchOperand_ParseFail;
3393 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003394
3395 // Registers must be incremental (with wraparound at 31)
3396 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003397 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3398 Error(Loc, "registers must be sequential");
3399 return MatchOperand_ParseFail;
3400 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003401
3402 PrevReg = Reg;
3403 ++Count;
3404 }
3405 }
3406
Nirav Davee833c6c2016-11-08 18:31:04 +00003407 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003408 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003409
Sander de Smalen650234b2018-04-12 11:40:52 +00003410 if (Count > 4) {
3411 Error(S, "invalid number of vectors");
3412 return MatchOperand_ParseFail;
3413 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003414
3415 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003416 unsigned ElementWidth = 0;
3417 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003418 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003419 std::tie(NumElements, ElementWidth) = *VK;
3420 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003421
3422 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003423 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3424 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003425
Sander de Smalen650234b2018-04-12 11:40:52 +00003426 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003427}
3428
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003429/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3430bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003431 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3432 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003433 return true;
3434
3435 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3436}
3437
Alex Bradbury58eba092016-11-01 16:32:05 +00003438OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003439AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003440 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003441
Sander de Smalen50d87022018-04-19 07:35:08 +00003442 unsigned RegNum;
3443 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3444 if (Res != MatchOperand_Success)
3445 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003446
Nirav Davee833c6c2016-11-08 18:31:04 +00003447 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003448 Operands.push_back(AArch64Operand::CreateReg(
3449 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003450 return MatchOperand_Success;
3451 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003452
Nirav Davee833c6c2016-11-08 18:31:04 +00003453 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003454
Sander de Smalen50d87022018-04-19 07:35:08 +00003455 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003456 Error(getLoc(), "index must be absent or #0");
3457 return MatchOperand_ParseFail;
3458 }
3459
3460 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003461 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003462 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3463 Error(getLoc(), "index must be absent or #0");
3464 return MatchOperand_ParseFail;
3465 }
3466
Sander de Smalen50d87022018-04-19 07:35:08 +00003467 Operands.push_back(AArch64Operand::CreateReg(
3468 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003469 return MatchOperand_Success;
3470}
3471
Sander de Smalen0325e302018-07-02 07:34:52 +00003472template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
Sander de Smalen149916d2018-04-20 07:24:20 +00003473OperandMatchResultTy
3474AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3475 SMLoc StartLoc = getLoc();
3476
3477 unsigned RegNum;
3478 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3479 if (Res != MatchOperand_Success)
3480 return Res;
3481
3482 // No shift/extend is the default.
3483 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3484 Operands.push_back(AArch64Operand::CreateReg(
Sander de Smalen0325e302018-07-02 07:34:52 +00003485 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
Sander de Smalen149916d2018-04-20 07:24:20 +00003486 return MatchOperand_Success;
3487 }
3488
3489 // Eat the comma
3490 getParser().Lex();
3491
3492 // Match the shift
3493 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3494 Res = tryParseOptionalShiftExtend(ExtOpnd);
3495 if (Res != MatchOperand_Success)
3496 return Res;
3497
3498 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
Sander de Smalen0325e302018-07-02 07:34:52 +00003499 Operands.push_back(AArch64Operand::CreateReg(
3500 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3501 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3502 Ext->hasShiftExtendAmount()));
Sander de Smalen149916d2018-04-20 07:24:20 +00003503
3504 return MatchOperand_Success;
3505}
3506
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003507bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
Sander de Smalen5c625982018-04-13 12:56:14 +00003508 MCAsmParser &Parser = getParser();
3509
3510 // Some SVE instructions have a decoration after the immediate, i.e.
3511 // "mul vl". We parse them here and add tokens, which must be present in the
3512 // asm string in the tablegen instruction.
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003513 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3514 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
Sander de Smalen5c625982018-04-13 12:56:14 +00003515 if (!Parser.getTok().getString().equals_lower("mul") ||
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003516 !(NextIsVL || NextIsHash))
Sander de Smalen5c625982018-04-13 12:56:14 +00003517 return true;
3518
Sander de Smalen5c625982018-04-13 12:56:14 +00003519 Operands.push_back(
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003520 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
Sander de Smalen5c625982018-04-13 12:56:14 +00003521 Parser.Lex(); // Eat the "mul"
3522
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003523 if (NextIsVL) {
3524 Operands.push_back(
3525 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3526 Parser.Lex(); // Eat the "vl"
3527 return false;
3528 }
Sander de Smalen5c625982018-04-13 12:56:14 +00003529
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003530 if (NextIsHash) {
3531 Parser.Lex(); // Eat the #
3532 SMLoc S = getLoc();
3533
3534 // Parse immediate operand.
3535 const MCExpr *ImmVal;
3536 if (!Parser.parseExpression(ImmVal))
3537 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3538 Operands.push_back(AArch64Operand::CreateImm(
3539 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3540 getContext()));
3541 return MatchOperand_Success;
3542 }
3543 }
3544
3545 return Error(getLoc(), "expected 'vl' or '#<imm>'");
Sander de Smalen5c625982018-04-13 12:56:14 +00003546}
3547
Tim Northover3b0846e2014-05-24 12:50:23 +00003548/// parseOperand - Parse a arm instruction operand. For now this parses the
3549/// operand regardless of the mnemonic.
3550bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3551 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003552 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003553
3554 OperandMatchResultTy ResTy =
3555 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3556
Tim Northover3b0846e2014-05-24 12:50:23 +00003557 // Check if the current operand has a custom associated parser, if so, try to
3558 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003559 if (ResTy == MatchOperand_Success)
3560 return false;
3561 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3562 // there was a match, but an error occurred, in which case, just return that
3563 // the operand parsing failed.
3564 if (ResTy == MatchOperand_ParseFail)
3565 return true;
3566
3567 // Nothing custom, so do general case parsing.
3568 SMLoc S, E;
3569 switch (getLexer().getKind()) {
3570 default: {
3571 SMLoc S = getLoc();
3572 const MCExpr *Expr;
3573 if (parseSymbolicImmVal(Expr))
3574 return Error(S, "invalid operand");
3575
3576 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3577 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3578 return false;
3579 }
3580 case AsmToken::LBrac: {
3581 SMLoc Loc = Parser.getTok().getLoc();
3582 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3583 getContext()));
3584 Parser.Lex(); // Eat '['
3585
3586 // There's no comma after a '[', so we can parse the next operand
3587 // immediately.
3588 return parseOperand(Operands, false, false);
3589 }
3590 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003591 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003592 case AsmToken::Identifier: {
3593 // If we're expecting a Condition Code operand, then just parse that.
3594 if (isCondCode)
3595 return parseCondCode(Operands, invertCondCode);
3596
3597 // If it's a register name, parse it.
3598 if (!parseRegister(Operands))
3599 return false;
3600
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003601 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3602 // by SVE instructions.
3603 if (!parseOptionalMulOperand(Operands))
Sander de Smalen5c625982018-04-13 12:56:14 +00003604 return false;
3605
Tim Northover3b0846e2014-05-24 12:50:23 +00003606 // This could be an optional "shift" or "extend" operand.
3607 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3608 // We can only continue if no tokens were eaten.
3609 if (GotShift != MatchOperand_NoMatch)
3610 return GotShift;
3611
3612 // This was not a register so parse other operands that start with an
3613 // identifier (like labels) as expressions and create them as immediates.
3614 const MCExpr *IdVal;
3615 S = getLoc();
3616 if (getParser().parseExpression(IdVal))
3617 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003618 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3619 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3620 return false;
3621 }
3622 case AsmToken::Integer:
3623 case AsmToken::Real:
3624 case AsmToken::Hash: {
3625 // #42 -> immediate.
3626 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003627
3628 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003629
3630 // Parse a negative sign
3631 bool isNegative = false;
3632 if (Parser.getTok().is(AsmToken::Minus)) {
3633 isNegative = true;
3634 // We need to consume this token only when we have a Real, otherwise
3635 // we let parseSymbolicImmVal take care of it
3636 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3637 Parser.Lex();
3638 }
3639
3640 // The only Real that should come through here is a literal #0.0 for
3641 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3642 // so convert the value.
3643 const AsmToken &Tok = Parser.getTok();
3644 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003645 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003646 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3647 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3648 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
Sander de Smalen8fcc3f52018-07-03 09:07:23 +00003649 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
Tim Northover3b0846e2014-05-24 12:50:23 +00003650 return TokError("unexpected floating point literal");
3651 else if (IntVal != 0 || isNegative)
3652 return TokError("expected floating-point constant #0.0");
3653 Parser.Lex(); // Eat the token.
3654
3655 Operands.push_back(
3656 AArch64Operand::CreateToken("#0", false, S, getContext()));
3657 Operands.push_back(
3658 AArch64Operand::CreateToken(".0", false, S, getContext()));
3659 return false;
3660 }
3661
3662 const MCExpr *ImmVal;
3663 if (parseSymbolicImmVal(ImmVal))
3664 return true;
3665
3666 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3667 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3668 return false;
3669 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003670 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003671 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003672 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003673 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003674 Parser.Lex(); // Eat '='
3675 const MCExpr *SubExprVal;
3676 if (getParser().parseExpression(SubExprVal))
3677 return true;
3678
David Peixottoae5ba762014-07-18 16:05:14 +00003679 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003680 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003681 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003682
3683 bool IsXReg =
3684 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3685 Operands[1]->getReg());
3686
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003687 MCContext& Ctx = getContext();
3688 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3689 // 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 +00003690 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003691 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3692 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3693 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3694 ShiftAmt += 16;
3695 Imm >>= 16;
3696 }
3697 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3698 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3699 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003700 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003701 if (ShiftAmt)
3702 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3703 ShiftAmt, true, S, E, Ctx));
3704 return false;
3705 }
David Peixottoae5ba762014-07-18 16:05:14 +00003706 APInt Simm = APInt(64, Imm << ShiftAmt);
3707 // check if the immediate is an unsigned or signed 32-bit int for W regs
3708 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3709 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003710 }
3711 // 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 +00003712 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003713 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003714 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3715 return false;
3716 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003717 }
3718}
3719
Sander de Smalen0325e302018-07-02 07:34:52 +00003720bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3721 const MCParsedAsmOperand &Op2) const {
3722 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3723 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3724 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3725 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3726 return MCTargetAsmParser::regsEqual(Op1, Op2);
3727
3728 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3729 "Testing equality of non-scalar registers not supported");
3730
3731 // Check if a registers match their sub/super register classes.
3732 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3733 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3734 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3735 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3736 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3737 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3738 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3739 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3740
3741 return false;
3742}
3743
Tim Northover3b0846e2014-05-24 12:50:23 +00003744/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3745/// operands.
3746bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3747 StringRef Name, SMLoc NameLoc,
3748 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003749 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003750 Name = StringSwitch<StringRef>(Name.lower())
3751 .Case("beq", "b.eq")
3752 .Case("bne", "b.ne")
3753 .Case("bhs", "b.hs")
3754 .Case("bcs", "b.cs")
3755 .Case("blo", "b.lo")
3756 .Case("bcc", "b.cc")
3757 .Case("bmi", "b.mi")
3758 .Case("bpl", "b.pl")
3759 .Case("bvs", "b.vs")
3760 .Case("bvc", "b.vc")
3761 .Case("bhi", "b.hi")
3762 .Case("bls", "b.ls")
3763 .Case("bge", "b.ge")
3764 .Case("blt", "b.lt")
3765 .Case("bgt", "b.gt")
3766 .Case("ble", "b.le")
3767 .Case("bal", "b.al")
3768 .Case("bnv", "b.nv")
3769 .Default(Name);
3770
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003771 // First check for the AArch64-specific .req directive.
3772 if (Parser.getTok().is(AsmToken::Identifier) &&
3773 Parser.getTok().getIdentifier() == ".req") {
3774 parseDirectiveReq(Name, NameLoc);
3775 // We always return 'error' for this, as we're done with this
3776 // statement and don't need to match the 'instruction."
3777 return true;
3778 }
3779
Tim Northover3b0846e2014-05-24 12:50:23 +00003780 // Create the leading tokens for the mnemonic, split by '.' characters.
3781 size_t Start = 0, Next = Name.find('.');
3782 StringRef Head = Name.slice(Start, Next);
3783
Oliver Stannard224428c2018-09-27 13:47:40 +00003784 // IC, DC, AT, TLBI and Prediction invalidation instructions are aliases for
3785 // the SYS instruction.
3786 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi" ||
3787 Head == "cfp" || Head == "dvp" || Head == "cpp")
Nirav Davee833c6c2016-11-08 18:31:04 +00003788 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003789
3790 Operands.push_back(
3791 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3792 Mnemonic = Head;
3793
3794 // Handle condition codes for a branch mnemonic
3795 if (Head == "b" && Next != StringRef::npos) {
3796 Start = Next;
3797 Next = Name.find('.', Start + 1);
3798 Head = Name.slice(Start + 1, Next);
3799
3800 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3801 (Head.data() - Name.data()));
3802 AArch64CC::CondCode CC = parseCondCodeString(Head);
3803 if (CC == AArch64CC::Invalid)
3804 return Error(SuffixLoc, "invalid condition code");
3805 Operands.push_back(
3806 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3807 Operands.push_back(
3808 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3809 }
3810
3811 // Add the remaining tokens in the mnemonic.
3812 while (Next != StringRef::npos) {
3813 Start = Next;
3814 Next = Name.find('.', Start + 1);
3815 Head = Name.slice(Start, Next);
3816 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3817 (Head.data() - Name.data()) + 1);
3818 Operands.push_back(
3819 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3820 }
3821
3822 // Conditional compare instructions have a Condition Code operand, which needs
3823 // to be parsed and an immediate operand created.
3824 bool condCodeFourthOperand =
3825 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3826 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3827 Head == "csinc" || Head == "csinv" || Head == "csneg");
3828
3829 // These instructions are aliases to some of the conditional select
3830 // instructions. However, the condition code is inverted in the aliased
3831 // instruction.
3832 //
3833 // FIXME: Is this the correct way to handle these? Or should the parser
3834 // generate the aliased instructions directly?
3835 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3836 bool condCodeThirdOperand =
3837 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3838
3839 // Read the remaining operands.
3840 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003841
Oliver Stannardc4190282018-10-02 10:04:39 +00003842 unsigned N = 1;
3843 do {
Tim Northover3b0846e2014-05-24 12:50:23 +00003844 // Parse and remember the operand.
3845 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3846 (N == 3 && condCodeThirdOperand) ||
3847 (N == 2 && condCodeSecondOperand),
3848 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003849 return true;
3850 }
3851
3852 // After successfully parsing some operands there are two special cases to
3853 // consider (i.e. notional operands not separated by commas). Both are due
3854 // to memory specifiers:
3855 // + An RBrac will end an address for load/store/prefetch
3856 // + An '!' will indicate a pre-indexed operation.
3857 //
3858 // It's someone else's responsibility to make sure these tokens are sane
3859 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003860
Nirav Davee833c6c2016-11-08 18:31:04 +00003861 SMLoc RLoc = Parser.getTok().getLoc();
3862 if (parseOptionalToken(AsmToken::RBrac))
3863 Operands.push_back(
3864 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3865 SMLoc ELoc = Parser.getTok().getLoc();
3866 if (parseOptionalToken(AsmToken::Exclaim))
3867 Operands.push_back(
3868 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003869
3870 ++N;
Oliver Stannardc4190282018-10-02 10:04:39 +00003871 } while (parseOptionalToken(AsmToken::Comma));
Tim Northover3b0846e2014-05-24 12:50:23 +00003872 }
3873
Nirav Davee833c6c2016-11-08 18:31:04 +00003874 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3875 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003876
Tim Northover3b0846e2014-05-24 12:50:23 +00003877 return false;
3878}
3879
Sander de Smalen9b333092018-07-30 15:42:46 +00003880static inline bool isMatchingOrAlias(unsigned ZReg, unsigned Reg) {
3881 assert((ZReg >= AArch64::Z0) && (ZReg <= AArch64::Z31));
3882 return (ZReg == ((Reg - AArch64::B0) + AArch64::Z0)) ||
3883 (ZReg == ((Reg - AArch64::H0) + AArch64::Z0)) ||
3884 (ZReg == ((Reg - AArch64::S0) + AArch64::Z0)) ||
3885 (ZReg == ((Reg - AArch64::D0) + AArch64::Z0)) ||
3886 (ZReg == ((Reg - AArch64::Q0) + AArch64::Z0)) ||
3887 (ZReg == ((Reg - AArch64::Z0) + AArch64::Z0));
3888}
3889
Tim Northover3b0846e2014-05-24 12:50:23 +00003890// FIXME: This entire function is a giant hack to provide us with decent
3891// operand range validation/diagnostics until TableGen/MC can be extended
3892// to support autogeneration of this kind of validation.
Sander de Smalen9b333092018-07-30 15:42:46 +00003893bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
3894 SmallVectorImpl<SMLoc> &Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003895 const MCRegisterInfo *RI = getContext().getRegisterInfo();
Sander de Smalen9b333092018-07-30 15:42:46 +00003896 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
3897
3898 // A prefix only applies to the instruction following it. Here we extract
3899 // prefix information for the next instruction before validating the current
3900 // one so that in the case of failure we don't erronously continue using the
3901 // current prefix.
3902 PrefixInfo Prefix = NextPrefix;
3903 NextPrefix = PrefixInfo::CreateFromInst(Inst, MCID.TSFlags);
3904
3905 // Before validating the instruction in isolation we run through the rules
3906 // applicable when it follows a prefix instruction.
3907 // NOTE: brk & hlt can be prefixed but require no additional validation.
3908 if (Prefix.isActive() &&
3909 (Inst.getOpcode() != AArch64::BRK) &&
3910 (Inst.getOpcode() != AArch64::HLT)) {
3911
3912 // Prefixed intructions must have a destructive operand.
3913 if ((MCID.TSFlags & AArch64::DestructiveInstTypeMask) ==
3914 AArch64::NotDestructive)
3915 return Error(IDLoc, "instruction is unpredictable when following a"
3916 " movprfx, suggest replacing movprfx with mov");
3917
3918 // Destination operands must match.
3919 if (Inst.getOperand(0).getReg() != Prefix.getDstReg())
3920 return Error(Loc[0], "instruction is unpredictable when following a"
3921 " movprfx writing to a different destination");
3922
3923 // Destination operand must not be used in any other location.
3924 for (unsigned i = 1; i < Inst.getNumOperands(); ++i) {
3925 if (Inst.getOperand(i).isReg() &&
3926 (MCID.getOperandConstraint(i, MCOI::TIED_TO) == -1) &&
3927 isMatchingOrAlias(Prefix.getDstReg(), Inst.getOperand(i).getReg()))
3928 return Error(Loc[0], "instruction is unpredictable when following a"
3929 " movprfx and destination also used as non-destructive"
3930 " source");
3931 }
3932
3933 auto PPRRegClass = AArch64MCRegisterClasses[AArch64::PPRRegClassID];
3934 if (Prefix.isPredicated()) {
3935 int PgIdx = -1;
3936
3937 // Find the instructions general predicate.
3938 for (unsigned i = 1; i < Inst.getNumOperands(); ++i)
3939 if (Inst.getOperand(i).isReg() &&
3940 PPRRegClass.contains(Inst.getOperand(i).getReg())) {
3941 PgIdx = i;
3942 break;
3943 }
3944
3945 // Instruction must be predicated if the movprfx is predicated.
3946 if (PgIdx == -1 ||
3947 (MCID.TSFlags & AArch64::ElementSizeMask) == AArch64::ElementSizeNone)
3948 return Error(IDLoc, "instruction is unpredictable when following a"
3949 " predicated movprfx, suggest using unpredicated movprfx");
3950
3951 // Instruction must use same general predicate as the movprfx.
3952 if (Inst.getOperand(PgIdx).getReg() != Prefix.getPgReg())
3953 return Error(IDLoc, "instruction is unpredictable when following a"
3954 " predicated movprfx using a different general predicate");
3955
3956 // Instruction element type must match the movprfx.
3957 if ((MCID.TSFlags & AArch64::ElementSizeMask) != Prefix.getElementSize())
3958 return Error(IDLoc, "instruction is unpredictable when following a"
3959 " predicated movprfx with a different element size");
3960 }
3961 }
3962
Tim Northover3b0846e2014-05-24 12:50:23 +00003963 // Check for indexed addressing modes w/ the base register being the
3964 // same as a destination/source register or pair load where
3965 // the Rt == Rt2. All of those are undefined behaviour.
3966 switch (Inst.getOpcode()) {
3967 case AArch64::LDPSWpre:
3968 case AArch64::LDPWpost:
3969 case AArch64::LDPWpre:
3970 case AArch64::LDPXpost:
3971 case AArch64::LDPXpre: {
3972 unsigned Rt = Inst.getOperand(1).getReg();
3973 unsigned Rt2 = Inst.getOperand(2).getReg();
3974 unsigned Rn = Inst.getOperand(3).getReg();
3975 if (RI->isSubRegisterEq(Rn, Rt))
3976 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3977 "is also a destination");
3978 if (RI->isSubRegisterEq(Rn, Rt2))
3979 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3980 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003981 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003982 }
3983 case AArch64::LDPDi:
3984 case AArch64::LDPQi:
3985 case AArch64::LDPSi:
3986 case AArch64::LDPSWi:
3987 case AArch64::LDPWi:
3988 case AArch64::LDPXi: {
3989 unsigned Rt = Inst.getOperand(0).getReg();
3990 unsigned Rt2 = Inst.getOperand(1).getReg();
3991 if (Rt == Rt2)
3992 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3993 break;
3994 }
3995 case AArch64::LDPDpost:
3996 case AArch64::LDPDpre:
3997 case AArch64::LDPQpost:
3998 case AArch64::LDPQpre:
3999 case AArch64::LDPSpost:
4000 case AArch64::LDPSpre:
4001 case AArch64::LDPSWpost: {
4002 unsigned Rt = Inst.getOperand(1).getReg();
4003 unsigned Rt2 = Inst.getOperand(2).getReg();
4004 if (Rt == Rt2)
4005 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
4006 break;
4007 }
4008 case AArch64::STPDpost:
4009 case AArch64::STPDpre:
4010 case AArch64::STPQpost:
4011 case AArch64::STPQpre:
4012 case AArch64::STPSpost:
4013 case AArch64::STPSpre:
4014 case AArch64::STPWpost:
4015 case AArch64::STPWpre:
4016 case AArch64::STPXpost:
4017 case AArch64::STPXpre: {
4018 unsigned Rt = Inst.getOperand(1).getReg();
4019 unsigned Rt2 = Inst.getOperand(2).getReg();
4020 unsigned Rn = Inst.getOperand(3).getReg();
4021 if (RI->isSubRegisterEq(Rn, Rt))
4022 return Error(Loc[0], "unpredictable STP instruction, writeback base "
4023 "is also a source");
4024 if (RI->isSubRegisterEq(Rn, Rt2))
4025 return Error(Loc[1], "unpredictable STP instruction, writeback base "
4026 "is also a source");
4027 break;
4028 }
4029 case AArch64::LDRBBpre:
4030 case AArch64::LDRBpre:
4031 case AArch64::LDRHHpre:
4032 case AArch64::LDRHpre:
4033 case AArch64::LDRSBWpre:
4034 case AArch64::LDRSBXpre:
4035 case AArch64::LDRSHWpre:
4036 case AArch64::LDRSHXpre:
4037 case AArch64::LDRSWpre:
4038 case AArch64::LDRWpre:
4039 case AArch64::LDRXpre:
4040 case AArch64::LDRBBpost:
4041 case AArch64::LDRBpost:
4042 case AArch64::LDRHHpost:
4043 case AArch64::LDRHpost:
4044 case AArch64::LDRSBWpost:
4045 case AArch64::LDRSBXpost:
4046 case AArch64::LDRSHWpost:
4047 case AArch64::LDRSHXpost:
4048 case AArch64::LDRSWpost:
4049 case AArch64::LDRWpost:
4050 case AArch64::LDRXpost: {
4051 unsigned Rt = Inst.getOperand(1).getReg();
4052 unsigned Rn = Inst.getOperand(2).getReg();
4053 if (RI->isSubRegisterEq(Rn, Rt))
4054 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
4055 "is also a source");
4056 break;
4057 }
4058 case AArch64::STRBBpost:
4059 case AArch64::STRBpost:
4060 case AArch64::STRHHpost:
4061 case AArch64::STRHpost:
4062 case AArch64::STRWpost:
4063 case AArch64::STRXpost:
4064 case AArch64::STRBBpre:
4065 case AArch64::STRBpre:
4066 case AArch64::STRHHpre:
4067 case AArch64::STRHpre:
4068 case AArch64::STRWpre:
4069 case AArch64::STRXpre: {
4070 unsigned Rt = Inst.getOperand(1).getReg();
4071 unsigned Rn = Inst.getOperand(2).getReg();
4072 if (RI->isSubRegisterEq(Rn, Rt))
4073 return Error(Loc[0], "unpredictable STR instruction, writeback base "
4074 "is also a source");
4075 break;
4076 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004077 case AArch64::STXRB:
4078 case AArch64::STXRH:
4079 case AArch64::STXRW:
4080 case AArch64::STXRX:
4081 case AArch64::STLXRB:
4082 case AArch64::STLXRH:
4083 case AArch64::STLXRW:
4084 case AArch64::STLXRX: {
4085 unsigned Rs = Inst.getOperand(0).getReg();
4086 unsigned Rt = Inst.getOperand(1).getReg();
4087 unsigned Rn = Inst.getOperand(2).getReg();
4088 if (RI->isSubRegisterEq(Rt, Rs) ||
4089 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
4090 return Error(Loc[0],
4091 "unpredictable STXR instruction, status is also a source");
4092 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00004093 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004094 case AArch64::STXPW:
4095 case AArch64::STXPX:
4096 case AArch64::STLXPW:
4097 case AArch64::STLXPX: {
4098 unsigned Rs = Inst.getOperand(0).getReg();
4099 unsigned Rt1 = Inst.getOperand(1).getReg();
4100 unsigned Rt2 = Inst.getOperand(2).getReg();
4101 unsigned Rn = Inst.getOperand(3).getReg();
4102 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
4103 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
4104 return Error(Loc[0],
4105 "unpredictable STXP instruction, status is also a source");
4106 break;
4107 }
4108 }
4109
Tim Northover3b0846e2014-05-24 12:50:23 +00004110
4111 // Now check immediate ranges. Separate from the above as there is overlap
4112 // in the instructions being checked and this keeps the nested conditionals
4113 // to a minimum.
4114 switch (Inst.getOpcode()) {
4115 case AArch64::ADDSWri:
4116 case AArch64::ADDSXri:
4117 case AArch64::ADDWri:
4118 case AArch64::ADDXri:
4119 case AArch64::SUBSWri:
4120 case AArch64::SUBSXri:
4121 case AArch64::SUBWri:
4122 case AArch64::SUBXri: {
4123 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
4124 // some slight duplication here.
4125 if (Inst.getOperand(2).isExpr()) {
4126 const MCExpr *Expr = Inst.getOperand(2).getExpr();
4127 AArch64MCExpr::VariantKind ELFRefKind;
4128 MCSymbolRefExpr::VariantKind DarwinRefKind;
4129 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00004130 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
4131
4132 // Only allow these with ADDXri.
4133 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
4134 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
4135 Inst.getOpcode() == AArch64::ADDXri)
4136 return false;
4137
4138 // Only allow these with ADDXri/ADDWri
4139 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
4140 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
4141 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
4142 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
4143 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
4144 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
4145 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00004146 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
4147 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
4148 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00004149 (Inst.getOpcode() == AArch64::ADDXri ||
4150 Inst.getOpcode() == AArch64::ADDWri))
4151 return false;
4152
4153 // Don't allow symbol refs in the immediate field otherwise
4154 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
4155 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
4156 // 'cmp w0, 'borked')
4157 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00004158 }
Diana Picusc93518d2016-10-11 09:17:47 +00004159 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00004160 }
4161 return false;
4162 }
4163 default:
4164 return false;
4165 }
4166}
4167
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004168static std::string AArch64MnemonicSpellCheck(StringRef S,
4169 const FeatureBitset &FBS,
Craig Topper05515562017-10-26 06:46:41 +00004170 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004171
4172bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
Sander de Smalen0325e302018-07-02 07:34:52 +00004173 uint64_t ErrorInfo,
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004174 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004175 switch (ErrCode) {
Sander de Smalen0325e302018-07-02 07:34:52 +00004176 case Match_InvalidTiedOperand: {
4177 RegConstraintEqualityTy EqTy =
4178 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
4179 .getRegEqualityTy();
4180 switch (EqTy) {
4181 case RegConstraintEqualityTy::EqualsSubReg:
4182 return Error(Loc, "operand must be 64-bit form of destination register");
4183 case RegConstraintEqualityTy::EqualsSuperReg:
4184 return Error(Loc, "operand must be 32-bit form of destination register");
4185 case RegConstraintEqualityTy::EqualsReg:
4186 return Error(Loc, "operand must match destination register");
4187 }
Simon Pilgrim6dc45e62018-07-05 09:48:01 +00004188 llvm_unreachable("Unknown RegConstraintEqualityTy");
Sander de Smalen0325e302018-07-02 07:34:52 +00004189 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004190 case Match_MissingFeature:
4191 return Error(Loc,
4192 "instruction requires a CPU feature not currently enabled");
4193 case Match_InvalidOperand:
4194 return Error(Loc, "invalid operand for instruction");
4195 case Match_InvalidSuffix:
4196 return Error(Loc, "invalid type suffix for instruction");
4197 case Match_InvalidCondCode:
4198 return Error(Loc, "expected AArch64 condition code");
4199 case Match_AddSubRegExtendSmall:
4200 return Error(Loc,
Eli Friedman723835382019-05-03 00:59:52 +00004201 "expected '[su]xt[bhw]' with optional integer in range [0, 4]");
Tim Northover3b0846e2014-05-24 12:50:23 +00004202 case Match_AddSubRegExtendLarge:
4203 return Error(Loc,
4204 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
4205 case Match_AddSubSecondSource:
4206 return Error(Loc,
4207 "expected compatible register, symbol or integer in range [0, 4095]");
4208 case Match_LogicalSecondSource:
4209 return Error(Loc, "expected compatible register or logical immediate");
4210 case Match_InvalidMovImm32Shift:
4211 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
4212 case Match_InvalidMovImm64Shift:
4213 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
4214 case Match_AddSubRegShift32:
4215 return Error(Loc,
4216 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
4217 case Match_AddSubRegShift64:
4218 return Error(Loc,
4219 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
4220 case Match_InvalidFPImm:
4221 return Error(Loc,
4222 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00004223 case Match_InvalidMemoryIndexedSImm6:
4224 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00004225 case Match_InvalidMemoryIndexedSImm5:
4226 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00004227 case Match_InvalidMemoryIndexed1SImm4:
4228 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00004229 case Match_InvalidMemoryIndexed2SImm4:
4230 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00004231 case Match_InvalidMemoryIndexed3SImm4:
4232 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00004233 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00004234 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004235 case Match_InvalidMemoryIndexed16SImm4:
4236 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00004237 case Match_InvalidMemoryIndexed1SImm6:
4238 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen592718f2018-07-05 07:54:10 +00004239 case Match_InvalidMemoryIndexedSImm8:
4240 return Error(Loc, "index must be an integer in range [-128, 127].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004241 case Match_InvalidMemoryIndexedSImm9:
4242 return Error(Loc, "index must be an integer in range [-256, 255].");
Oliver Stannardc4190282018-10-02 10:04:39 +00004243 case Match_InvalidMemoryIndexed16SImm9:
4244 return Error(Loc, "index must be a multiple of 16 in range [-4096, 4080].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004245 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00004246 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004247 case Match_InvalidMemoryIndexed4SImm7:
4248 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
4249 case Match_InvalidMemoryIndexed8SImm7:
4250 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
4251 case Match_InvalidMemoryIndexed16SImm7:
4252 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00004253 case Match_InvalidMemoryIndexed8UImm5:
4254 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
4255 case Match_InvalidMemoryIndexed4UImm5:
4256 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
4257 case Match_InvalidMemoryIndexed2UImm5:
4258 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00004259 case Match_InvalidMemoryIndexed8UImm6:
4260 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
Oliver Stannardc4190282018-10-02 10:04:39 +00004261 case Match_InvalidMemoryIndexed16UImm6:
4262 return Error(Loc, "index must be a multiple of 16 in range [0, 1008].");
Sander de Smalend8e76492018-05-08 10:46:55 +00004263 case Match_InvalidMemoryIndexed4UImm6:
4264 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
4265 case Match_InvalidMemoryIndexed2UImm6:
4266 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
4267 case Match_InvalidMemoryIndexed1UImm6:
4268 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004269 case Match_InvalidMemoryWExtend8:
4270 return Error(Loc,
4271 "expected 'uxtw' or 'sxtw' with optional shift of #0");
4272 case Match_InvalidMemoryWExtend16:
4273 return Error(Loc,
4274 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
4275 case Match_InvalidMemoryWExtend32:
4276 return Error(Loc,
4277 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
4278 case Match_InvalidMemoryWExtend64:
4279 return Error(Loc,
4280 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
4281 case Match_InvalidMemoryWExtend128:
4282 return Error(Loc,
4283 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
4284 case Match_InvalidMemoryXExtend8:
4285 return Error(Loc,
4286 "expected 'lsl' or 'sxtx' with optional shift of #0");
4287 case Match_InvalidMemoryXExtend16:
4288 return Error(Loc,
4289 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
4290 case Match_InvalidMemoryXExtend32:
4291 return Error(Loc,
4292 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
4293 case Match_InvalidMemoryXExtend64:
4294 return Error(Loc,
4295 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
4296 case Match_InvalidMemoryXExtend128:
4297 return Error(Loc,
4298 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
4299 case Match_InvalidMemoryIndexed1:
4300 return Error(Loc, "index must be an integer in range [0, 4095].");
4301 case Match_InvalidMemoryIndexed2:
4302 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
4303 case Match_InvalidMemoryIndexed4:
4304 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
4305 case Match_InvalidMemoryIndexed8:
4306 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
4307 case Match_InvalidMemoryIndexed16:
4308 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004309 case Match_InvalidImm0_1:
4310 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004311 case Match_InvalidImm0_7:
4312 return Error(Loc, "immediate must be an integer in range [0, 7].");
4313 case Match_InvalidImm0_15:
4314 return Error(Loc, "immediate must be an integer in range [0, 15].");
4315 case Match_InvalidImm0_31:
4316 return Error(Loc, "immediate must be an integer in range [0, 31].");
4317 case Match_InvalidImm0_63:
4318 return Error(Loc, "immediate must be an integer in range [0, 63].");
4319 case Match_InvalidImm0_127:
4320 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004321 case Match_InvalidImm0_255:
4322 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004323 case Match_InvalidImm0_65535:
4324 return Error(Loc, "immediate must be an integer in range [0, 65535].");
4325 case Match_InvalidImm1_8:
4326 return Error(Loc, "immediate must be an integer in range [1, 8].");
4327 case Match_InvalidImm1_16:
4328 return Error(Loc, "immediate must be an integer in range [1, 16].");
4329 case Match_InvalidImm1_32:
4330 return Error(Loc, "immediate must be an integer in range [1, 32].");
4331 case Match_InvalidImm1_64:
4332 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00004333 case Match_InvalidSVEAddSubImm8:
4334 return Error(Loc, "immediate must be an integer in range [0, 255]"
4335 " with a shift amount of 0");
4336 case Match_InvalidSVEAddSubImm16:
4337 case Match_InvalidSVEAddSubImm32:
4338 case Match_InvalidSVEAddSubImm64:
4339 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
4340 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004341 case Match_InvalidSVECpyImm8:
4342 return Error(Loc, "immediate must be an integer in range [-128, 255]"
4343 " with a shift amount of 0");
4344 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00004345 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4346 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004347 case Match_InvalidSVECpyImm32:
4348 case Match_InvalidSVECpyImm64:
4349 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4350 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004351 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004352 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004353 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00004354 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004355 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00004356 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004357 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004358 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004359 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004360 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004361 case Match_InvalidSVEIndexRange0_63:
4362 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4363 case Match_InvalidSVEIndexRange0_31:
4364 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4365 case Match_InvalidSVEIndexRange0_15:
4366 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4367 case Match_InvalidSVEIndexRange0_7:
4368 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4369 case Match_InvalidSVEIndexRange0_3:
4370 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004371 case Match_InvalidLabel:
4372 return Error(Loc, "expected label or encodable integer pc offset");
4373 case Match_MRS:
4374 return Error(Loc, "expected readable system register");
4375 case Match_MSR:
4376 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00004377 case Match_InvalidComplexRotationEven:
4378 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4379 case Match_InvalidComplexRotationOdd:
4380 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004381 case Match_MnemonicFail: {
4382 std::string Suggestion = AArch64MnemonicSpellCheck(
4383 ((AArch64Operand &)*Operands[0]).getToken(),
4384 ComputeAvailableFeatures(STI->getFeatureBits()));
4385 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4386 }
Sander de Smalen367694b2018-04-20 08:54:49 +00004387 case Match_InvalidGPR64shifted8:
4388 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4389 case Match_InvalidGPR64shifted16:
4390 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4391 case Match_InvalidGPR64shifted32:
4392 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4393 case Match_InvalidGPR64shifted64:
4394 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4395 case Match_InvalidGPR64NoXZRshifted8:
4396 return Error(Loc, "register must be x0..x30 without shift");
4397 case Match_InvalidGPR64NoXZRshifted16:
4398 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4399 case Match_InvalidGPR64NoXZRshifted32:
4400 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4401 case Match_InvalidGPR64NoXZRshifted64:
4402 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004403 case Match_InvalidZPR32UXTW8:
4404 case Match_InvalidZPR32SXTW8:
4405 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4406 case Match_InvalidZPR32UXTW16:
4407 case Match_InvalidZPR32SXTW16:
4408 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4409 case Match_InvalidZPR32UXTW32:
4410 case Match_InvalidZPR32SXTW32:
4411 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4412 case Match_InvalidZPR32UXTW64:
4413 case Match_InvalidZPR32SXTW64:
4414 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4415 case Match_InvalidZPR64UXTW8:
4416 case Match_InvalidZPR64SXTW8:
4417 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4418 case Match_InvalidZPR64UXTW16:
4419 case Match_InvalidZPR64SXTW16:
4420 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4421 case Match_InvalidZPR64UXTW32:
4422 case Match_InvalidZPR64SXTW32:
4423 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4424 case Match_InvalidZPR64UXTW64:
4425 case Match_InvalidZPR64SXTW64:
4426 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
Sander de Smalenc69944c2018-07-09 09:58:24 +00004427 case Match_InvalidZPR32LSL8:
4428 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s'");
4429 case Match_InvalidZPR32LSL16:
4430 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #1'");
4431 case Match_InvalidZPR32LSL32:
4432 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #2'");
4433 case Match_InvalidZPR32LSL64:
4434 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004435 case Match_InvalidZPR64LSL8:
4436 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4437 case Match_InvalidZPR64LSL16:
4438 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4439 case Match_InvalidZPR64LSL32:
4440 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4441 case Match_InvalidZPR64LSL64:
4442 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00004443 case Match_InvalidZPR0:
Sander de Smalene1eab422019-03-27 17:23:38 +00004444 return Error(Loc, "expected register without element width suffix");
Sander de Smalen22176a22018-05-16 15:45:17 +00004445 case Match_InvalidZPR8:
4446 case Match_InvalidZPR16:
4447 case Match_InvalidZPR32:
4448 case Match_InvalidZPR64:
4449 case Match_InvalidZPR128:
4450 return Error(Loc, "invalid element width");
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004451 case Match_InvalidZPR_3b8:
4452 return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b");
4453 case Match_InvalidZPR_3b16:
4454 return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h");
4455 case Match_InvalidZPR_3b32:
4456 return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s");
4457 case Match_InvalidZPR_4b16:
4458 return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h");
4459 case Match_InvalidZPR_4b32:
4460 return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s");
4461 case Match_InvalidZPR_4b64:
4462 return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004463 case Match_InvalidSVEPattern:
4464 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004465 case Match_InvalidSVEPredicateAnyReg:
4466 case Match_InvalidSVEPredicateBReg:
4467 case Match_InvalidSVEPredicateHReg:
4468 case Match_InvalidSVEPredicateSReg:
4469 case Match_InvalidSVEPredicateDReg:
4470 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004471 case Match_InvalidSVEPredicate3bAnyReg:
4472 case Match_InvalidSVEPredicate3bBReg:
4473 case Match_InvalidSVEPredicate3bHReg:
4474 case Match_InvalidSVEPredicate3bSReg:
4475 case Match_InvalidSVEPredicate3bDReg:
4476 return Error(Loc, "restricted predicate has range [0, 7].");
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004477 case Match_InvalidSVEExactFPImmOperandHalfOne:
4478 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4479 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4480 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4481 case Match_InvalidSVEExactFPImmOperandZeroOne:
4482 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004483 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004484 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004485 }
4486}
4487
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004488static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004489
4490bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4491 OperandVector &Operands,
4492 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004493 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004494 bool MatchingInlineAsm) {
4495 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004496 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4497 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004498
David Blaikie960ea3f2014-06-08 16:18:35 +00004499 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004500 unsigned NumOperands = Operands.size();
4501
4502 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004503 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4504 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004505 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004506 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004507 if (Op3CE) {
4508 uint64_t Op3Val = Op3CE->getValue();
4509 uint64_t NewOp3Val = 0;
4510 uint64_t NewOp4Val = 0;
4511 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004512 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004513 NewOp3Val = (32 - Op3Val) & 0x1f;
4514 NewOp4Val = 31 - Op3Val;
4515 } else {
4516 NewOp3Val = (64 - Op3Val) & 0x3f;
4517 NewOp4Val = 63 - Op3Val;
4518 }
4519
Jim Grosbach13760bd2015-05-30 01:25:56 +00004520 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4521 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004522
4523 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004524 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004525 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004526 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4527 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4528 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004529 }
4530 }
Tim Northover03b99f62015-04-30 18:28:58 +00004531 } else if (NumOperands == 4 && Tok == "bfc") {
4532 // FIXME: Horrible hack to handle BFC->BFM alias.
4533 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4534 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4535 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4536
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004537 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004538 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4539 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4540
4541 if (LSBCE && WidthCE) {
4542 uint64_t LSB = LSBCE->getValue();
4543 uint64_t Width = WidthCE->getValue();
4544
4545 uint64_t RegWidth = 0;
4546 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4547 Op1.getReg()))
4548 RegWidth = 64;
4549 else
4550 RegWidth = 32;
4551
4552 if (LSB >= RegWidth)
4553 return Error(LSBOp.getStartLoc(),
4554 "expected integer in range [0, 31]");
4555 if (Width < 1 || Width > RegWidth)
4556 return Error(WidthOp.getStartLoc(),
4557 "expected integer in range [1, 32]");
4558
4559 uint64_t ImmR = 0;
4560 if (RegWidth == 32)
4561 ImmR = (32 - LSB) & 0x1f;
4562 else
4563 ImmR = (64 - LSB) & 0x3f;
4564
4565 uint64_t ImmS = Width - 1;
4566
4567 if (ImmR != 0 && ImmS >= ImmR)
4568 return Error(WidthOp.getStartLoc(),
4569 "requested insert overflows register");
4570
Jim Grosbach13760bd2015-05-30 01:25:56 +00004571 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4572 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004573 Operands[0] = AArch64Operand::CreateToken(
4574 "bfm", false, Op.getStartLoc(), getContext());
4575 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004576 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4577 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004578 Operands[3] = AArch64Operand::CreateImm(
4579 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4580 Operands.emplace_back(
4581 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4582 WidthOp.getEndLoc(), getContext()));
4583 }
4584 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004585 } else if (NumOperands == 5) {
4586 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4587 // UBFIZ -> UBFM aliases.
4588 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004589 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4590 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4591 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004592
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004593 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004594 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4595 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004596
4597 if (Op3CE && Op4CE) {
4598 uint64_t Op3Val = Op3CE->getValue();
4599 uint64_t Op4Val = Op4CE->getValue();
4600
4601 uint64_t RegWidth = 0;
4602 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004603 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004604 RegWidth = 64;
4605 else
4606 RegWidth = 32;
4607
4608 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004609 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004610 "expected integer in range [0, 31]");
4611 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004612 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004613 "expected integer in range [1, 32]");
4614
4615 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004616 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004617 NewOp3Val = (32 - Op3Val) & 0x1f;
4618 else
4619 NewOp3Val = (64 - Op3Val) & 0x3f;
4620
4621 uint64_t NewOp4Val = Op4Val - 1;
4622
4623 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004624 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004625 "requested insert overflows register");
4626
4627 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004628 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004629 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004630 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004631 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004632 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004633 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004634 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004635 if (Tok == "bfi")
4636 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004637 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004638 else if (Tok == "sbfiz")
4639 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004640 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004641 else if (Tok == "ubfiz")
4642 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004643 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004644 else
4645 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004646 }
4647 }
4648
4649 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4650 // UBFX -> UBFM aliases.
4651 } else if (NumOperands == 5 &&
4652 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004653 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4654 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4655 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004656
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004657 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004658 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4659 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004660
4661 if (Op3CE && Op4CE) {
4662 uint64_t Op3Val = Op3CE->getValue();
4663 uint64_t Op4Val = Op4CE->getValue();
4664
4665 uint64_t RegWidth = 0;
4666 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004667 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004668 RegWidth = 64;
4669 else
4670 RegWidth = 32;
4671
4672 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004673 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004674 "expected integer in range [0, 31]");
4675 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004676 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004677 "expected integer in range [1, 32]");
4678
4679 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4680
4681 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004682 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004683 "requested extract overflows register");
4684
4685 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004686 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004687 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004688 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004689 if (Tok == "bfxil")
4690 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004691 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004692 else if (Tok == "sbfx")
4693 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004694 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004695 else if (Tok == "ubfx")
4696 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004697 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004698 else
4699 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004700 }
4701 }
4702 }
4703 }
Tim Northover9097a072017-12-18 10:36:00 +00004704
4705 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4706 // instruction for FP registers correctly in some rare circumstances. Convert
4707 // it to a safe instruction and warn (because silently changing someone's
4708 // assembly is rude).
4709 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4710 NumOperands == 4 && Tok == "movi") {
4711 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4712 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4713 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4714 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4715 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4716 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4717 if (Suffix.lower() == ".2d" &&
4718 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4719 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4720 " correctly on this CPU, converting to equivalent movi.16b");
4721 // Switch the suffix to .16b.
4722 unsigned Idx = Op1.isToken() ? 1 : 2;
4723 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4724 getContext());
4725 }
4726 }
4727 }
4728
Tim Northover3b0846e2014-05-24 12:50:23 +00004729 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4730 // InstAlias can't quite handle this since the reg classes aren't
4731 // subclasses.
4732 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4733 // The source register can be Wn here, but the matcher expects a
4734 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004735 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004736 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004737 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004738 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4739 Op.getStartLoc(), Op.getEndLoc(),
4740 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004741 }
4742 }
4743 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4744 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004745 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004746 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004747 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004748 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004749 // The source register can be Wn here, but the matcher expects a
4750 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004751 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004752 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004753 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004754 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4755 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004756 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004757 }
4758 }
4759 }
4760 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4761 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004762 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004763 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004764 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004765 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004766 // The source register can be Wn here, but the matcher expects a
4767 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004768 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004769 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004770 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004771 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4772 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004773 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004774 }
4775 }
4776 }
4777
Tim Northover3b0846e2014-05-24 12:50:23 +00004778 MCInst Inst;
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004779 FeatureBitset MissingFeatures;
Tim Northover3b0846e2014-05-24 12:50:23 +00004780 // First try to match against the secondary set of tables containing the
4781 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4782 unsigned MatchResult =
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004783 MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
4784 MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004785
4786 // If that fails, try against the alternate table containing long-form NEON:
4787 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004788 if (MatchResult != Match_Success) {
4789 // But first, save the short-form match result: we can use it in case the
4790 // long-form match also fails.
4791 auto ShortFormNEONErrorInfo = ErrorInfo;
4792 auto ShortFormNEONMatchResult = MatchResult;
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004793 auto ShortFormNEONMissingFeatures = MissingFeatures;
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004794
Tim Northover3b0846e2014-05-24 12:50:23 +00004795 MatchResult =
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004796 MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
4797 MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004798
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004799 // Now, both matches failed, and the long-form match failed on the mnemonic
4800 // suffix token operand. The short-form match failure is probably more
4801 // relevant: use it instead.
4802 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004803 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004804 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4805 MatchResult = ShortFormNEONMatchResult;
4806 ErrorInfo = ShortFormNEONErrorInfo;
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004807 MissingFeatures = ShortFormNEONMissingFeatures;
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004808 }
4809 }
4810
Tim Northover3b0846e2014-05-24 12:50:23 +00004811 switch (MatchResult) {
4812 case Match_Success: {
4813 // Perform range checking and other semantic validations
4814 SmallVector<SMLoc, 8> OperandLocs;
4815 NumOperands = Operands.size();
4816 for (unsigned i = 1; i < NumOperands; ++i)
4817 OperandLocs.push_back(Operands[i]->getStartLoc());
Sander de Smalen9b333092018-07-30 15:42:46 +00004818 if (validateInstruction(Inst, IDLoc, OperandLocs))
Tim Northover3b0846e2014-05-24 12:50:23 +00004819 return true;
4820
4821 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004822 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004823 return false;
4824 }
4825 case Match_MissingFeature: {
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004826 assert(MissingFeatures.any() && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004827 // Special case the error message for the very common case where only
4828 // a single subtarget feature is missing (neon, e.g.).
4829 std::string Msg = "instruction requires:";
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004830 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
4831 if (MissingFeatures[i]) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004832 Msg += " ";
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004833 Msg += getSubtargetFeatureName(i);
Tim Northover3b0846e2014-05-24 12:50:23 +00004834 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004835 }
4836 return Error(IDLoc, Msg);
4837 }
4838 case Match_MnemonicFail:
Sander de Smalen0325e302018-07-02 07:34:52 +00004839 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004840 case Match_InvalidOperand: {
4841 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004842
Tim Northover26bb14e2014-08-18 11:49:42 +00004843 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004844 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004845 return Error(IDLoc, "too few operands for instruction",
4846 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004847
David Blaikie960ea3f2014-06-08 16:18:35 +00004848 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004849 if (ErrorLoc == SMLoc())
4850 ErrorLoc = IDLoc;
4851 }
4852 // If the match failed on a suffix token operand, tweak the diagnostic
4853 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004854 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4855 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004856 MatchResult = Match_InvalidSuffix;
4857
Sander de Smalen0325e302018-07-02 07:34:52 +00004858 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004859 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004860 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004861 case Match_InvalidMemoryIndexed1:
4862 case Match_InvalidMemoryIndexed2:
4863 case Match_InvalidMemoryIndexed4:
4864 case Match_InvalidMemoryIndexed8:
4865 case Match_InvalidMemoryIndexed16:
4866 case Match_InvalidCondCode:
4867 case Match_AddSubRegExtendSmall:
4868 case Match_AddSubRegExtendLarge:
4869 case Match_AddSubSecondSource:
4870 case Match_LogicalSecondSource:
4871 case Match_AddSubRegShift32:
4872 case Match_AddSubRegShift64:
4873 case Match_InvalidMovImm32Shift:
4874 case Match_InvalidMovImm64Shift:
4875 case Match_InvalidFPImm:
4876 case Match_InvalidMemoryWExtend8:
4877 case Match_InvalidMemoryWExtend16:
4878 case Match_InvalidMemoryWExtend32:
4879 case Match_InvalidMemoryWExtend64:
4880 case Match_InvalidMemoryWExtend128:
4881 case Match_InvalidMemoryXExtend8:
4882 case Match_InvalidMemoryXExtend16:
4883 case Match_InvalidMemoryXExtend32:
4884 case Match_InvalidMemoryXExtend64:
4885 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004886 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004887 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004888 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004889 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004890 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004891 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004892 case Match_InvalidMemoryIndexed4SImm7:
4893 case Match_InvalidMemoryIndexed8SImm7:
4894 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004895 case Match_InvalidMemoryIndexed8UImm5:
4896 case Match_InvalidMemoryIndexed4UImm5:
4897 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004898 case Match_InvalidMemoryIndexed1UImm6:
4899 case Match_InvalidMemoryIndexed2UImm6:
4900 case Match_InvalidMemoryIndexed4UImm6:
4901 case Match_InvalidMemoryIndexed8UImm6:
Oliver Stannardc4190282018-10-02 10:04:39 +00004902 case Match_InvalidMemoryIndexed16UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004903 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004904 case Match_InvalidMemoryIndexedSImm5:
Sander de Smalen592718f2018-07-05 07:54:10 +00004905 case Match_InvalidMemoryIndexedSImm8:
Tim Northover3b0846e2014-05-24 12:50:23 +00004906 case Match_InvalidMemoryIndexedSImm9:
Oliver Stannardc4190282018-10-02 10:04:39 +00004907 case Match_InvalidMemoryIndexed16SImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004908 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004909 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004910 case Match_InvalidImm0_7:
4911 case Match_InvalidImm0_15:
4912 case Match_InvalidImm0_31:
4913 case Match_InvalidImm0_63:
4914 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004915 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004916 case Match_InvalidImm0_65535:
4917 case Match_InvalidImm1_8:
4918 case Match_InvalidImm1_16:
4919 case Match_InvalidImm1_32:
4920 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004921 case Match_InvalidSVEAddSubImm8:
4922 case Match_InvalidSVEAddSubImm16:
4923 case Match_InvalidSVEAddSubImm32:
4924 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004925 case Match_InvalidSVECpyImm8:
4926 case Match_InvalidSVECpyImm16:
4927 case Match_InvalidSVECpyImm32:
4928 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004929 case Match_InvalidIndexRange1_1:
4930 case Match_InvalidIndexRange0_15:
4931 case Match_InvalidIndexRange0_7:
4932 case Match_InvalidIndexRange0_3:
4933 case Match_InvalidIndexRange0_1:
4934 case Match_InvalidSVEIndexRange0_63:
4935 case Match_InvalidSVEIndexRange0_31:
4936 case Match_InvalidSVEIndexRange0_15:
4937 case Match_InvalidSVEIndexRange0_7:
4938 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004939 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004940 case Match_InvalidComplexRotationEven:
4941 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004942 case Match_InvalidGPR64shifted8:
4943 case Match_InvalidGPR64shifted16:
4944 case Match_InvalidGPR64shifted32:
4945 case Match_InvalidGPR64shifted64:
4946 case Match_InvalidGPR64NoXZRshifted8:
4947 case Match_InvalidGPR64NoXZRshifted16:
4948 case Match_InvalidGPR64NoXZRshifted32:
4949 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004950 case Match_InvalidZPR32UXTW8:
4951 case Match_InvalidZPR32UXTW16:
4952 case Match_InvalidZPR32UXTW32:
4953 case Match_InvalidZPR32UXTW64:
4954 case Match_InvalidZPR32SXTW8:
4955 case Match_InvalidZPR32SXTW16:
4956 case Match_InvalidZPR32SXTW32:
4957 case Match_InvalidZPR32SXTW64:
4958 case Match_InvalidZPR64UXTW8:
4959 case Match_InvalidZPR64SXTW8:
4960 case Match_InvalidZPR64UXTW16:
4961 case Match_InvalidZPR64SXTW16:
4962 case Match_InvalidZPR64UXTW32:
4963 case Match_InvalidZPR64SXTW32:
4964 case Match_InvalidZPR64UXTW64:
4965 case Match_InvalidZPR64SXTW64:
Sander de Smalenc69944c2018-07-09 09:58:24 +00004966 case Match_InvalidZPR32LSL8:
4967 case Match_InvalidZPR32LSL16:
4968 case Match_InvalidZPR32LSL32:
4969 case Match_InvalidZPR32LSL64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004970 case Match_InvalidZPR64LSL8:
4971 case Match_InvalidZPR64LSL16:
4972 case Match_InvalidZPR64LSL32:
4973 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004974 case Match_InvalidZPR0:
4975 case Match_InvalidZPR8:
4976 case Match_InvalidZPR16:
4977 case Match_InvalidZPR32:
4978 case Match_InvalidZPR64:
4979 case Match_InvalidZPR128:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004980 case Match_InvalidZPR_3b8:
4981 case Match_InvalidZPR_3b16:
4982 case Match_InvalidZPR_3b32:
4983 case Match_InvalidZPR_4b16:
4984 case Match_InvalidZPR_4b32:
4985 case Match_InvalidZPR_4b64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004986 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004987 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004988 case Match_InvalidSVEPredicateBReg:
4989 case Match_InvalidSVEPredicateHReg:
4990 case Match_InvalidSVEPredicateSReg:
4991 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004992 case Match_InvalidSVEPredicate3bAnyReg:
4993 case Match_InvalidSVEPredicate3bBReg:
4994 case Match_InvalidSVEPredicate3bHReg:
4995 case Match_InvalidSVEPredicate3bSReg:
4996 case Match_InvalidSVEPredicate3bDReg:
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004997 case Match_InvalidSVEExactFPImmOperandHalfOne:
4998 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4999 case Match_InvalidSVEExactFPImmOperandZeroOne:
Tim Northover3b0846e2014-05-24 12:50:23 +00005000 case Match_MSR:
5001 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00005002 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00005003 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00005004 // Any time we get here, there's nothing fancy to do. Just get the
5005 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00005006 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00005007 if (ErrorLoc == SMLoc())
5008 ErrorLoc = IDLoc;
Sander de Smalen0325e302018-07-02 07:34:52 +00005009 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00005010 }
5011 }
5012
5013 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00005014}
5015
5016/// ParseDirective parses the arm specific directives
5017bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00005018 const MCObjectFileInfo::Environment Format =
5019 getContext().getObjectFileInfo()->getObjectFileType();
5020 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005021
Tim Northover3b0846e2014-05-24 12:50:23 +00005022 StringRef IDVal = DirectiveID.getIdentifier();
5023 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005024 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00005025 parseDirectiveArch(Loc);
5026 else if (IDVal == ".cpu")
5027 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00005028 else if (IDVal == ".tlsdesccall")
5029 parseDirectiveTLSDescCall(Loc);
5030 else if (IDVal == ".ltorg" || IDVal == ".pool")
5031 parseDirectiveLtorg(Loc);
5032 else if (IDVal == ".unreq")
5033 parseDirectiveUnreq(Loc);
Martin Storsjo3e3d39d2018-07-31 09:26:52 +00005034 else if (IDVal == ".inst")
5035 parseDirectiveInst(Loc);
Luke Cheesemanf57d7d82018-12-18 10:37:42 +00005036 else if (IDVal == ".cfi_negate_ra_state")
5037 parseDirectiveCFINegateRAState();
Luke Cheeseman41a9e532018-12-21 10:45:08 +00005038 else if (IDVal == ".cfi_b_key_frame")
5039 parseDirectiveCFIBKeyFrame();
Martin Storsjo20187772018-12-30 21:06:32 +00005040 else if (IDVal == ".arch_extension")
5041 parseDirectiveArchExtension(Loc);
Martin Storsjod4590c32018-08-01 06:50:18 +00005042 else if (IsMachO) {
5043 if (IDVal == MCLOHDirectiveName())
5044 parseDirectiveLOH(IDVal, Loc);
5045 else
5046 return true;
5047 } else
Nirav Davee833c6c2016-11-08 18:31:04 +00005048 return true;
5049 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00005050}
5051
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005052static void ExpandCryptoAEK(AArch64::ArchKind ArchKind,
5053 SmallVector<StringRef, 4> &RequestedExtensions) {
5054 const bool NoCrypto =
5055 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
5056 "nocrypto") != std::end(RequestedExtensions));
5057 const bool Crypto =
5058 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
5059 "crypto") != std::end(RequestedExtensions));
5060
5061 if (!NoCrypto && Crypto) {
5062 switch (ArchKind) {
5063 default:
5064 // Map 'generic' (and others) to sha2 and aes, because
5065 // that was the traditional meaning of crypto.
5066 case AArch64::ArchKind::ARMV8_1A:
5067 case AArch64::ArchKind::ARMV8_2A:
5068 case AArch64::ArchKind::ARMV8_3A:
5069 RequestedExtensions.push_back("sha2");
5070 RequestedExtensions.push_back("aes");
5071 break;
5072 case AArch64::ArchKind::ARMV8_4A:
Oliver Stannard7c3c4ba2018-09-26 12:48:21 +00005073 case AArch64::ArchKind::ARMV8_5A:
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005074 RequestedExtensions.push_back("sm4");
5075 RequestedExtensions.push_back("sha3");
5076 RequestedExtensions.push_back("sha2");
5077 RequestedExtensions.push_back("aes");
5078 break;
5079 }
5080 } else if (NoCrypto) {
5081 switch (ArchKind) {
5082 default:
5083 // Map 'generic' (and others) to sha2 and aes, because
5084 // that was the traditional meaning of crypto.
5085 case AArch64::ArchKind::ARMV8_1A:
5086 case AArch64::ArchKind::ARMV8_2A:
5087 case AArch64::ArchKind::ARMV8_3A:
5088 RequestedExtensions.push_back("nosha2");
5089 RequestedExtensions.push_back("noaes");
5090 break;
5091 case AArch64::ArchKind::ARMV8_4A:
Oliver Stannard7c3c4ba2018-09-26 12:48:21 +00005092 case AArch64::ArchKind::ARMV8_5A:
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005093 RequestedExtensions.push_back("nosm4");
5094 RequestedExtensions.push_back("nosha3");
5095 RequestedExtensions.push_back("nosha2");
5096 RequestedExtensions.push_back("noaes");
5097 break;
5098 }
5099 }
5100}
5101
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005102/// parseDirectiveArch
5103/// ::= .arch token
5104bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
5105 SMLoc ArchLoc = getLoc();
5106
5107 StringRef Arch, ExtensionString;
5108 std::tie(Arch, ExtensionString) =
5109 getParser().parseStringToEndOfStatement().trim().split('+');
5110
Florian Hahn67ddd1d2017-07-27 16:27:56 +00005111 AArch64::ArchKind ID = AArch64::parseArch(Arch);
5112 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00005113 return Error(ArchLoc, "unknown arch name");
5114
5115 if (parseToken(AsmToken::EndOfStatement))
5116 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005117
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005118 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00005119 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005120 AArch64::getArchFeatures(ID, AArch64Features);
5121 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
5122 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005123
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005124 MCSubtargetInfo &STI = copySTI();
5125 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
5126 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
5127
5128 SmallVector<StringRef, 4> RequestedExtensions;
5129 if (!ExtensionString.empty())
5130 ExtensionString.split(RequestedExtensions, '+');
5131
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005132 ExpandCryptoAEK(ID, RequestedExtensions);
5133
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005134 FeatureBitset Features = STI.getFeatureBits();
5135 for (auto Name : RequestedExtensions) {
5136 bool EnableFeature = true;
5137
5138 if (Name.startswith_lower("no")) {
5139 EnableFeature = false;
5140 Name = Name.substr(2);
5141 }
5142
5143 for (const auto &Extension : ExtensionMap) {
5144 if (Extension.Name != Name)
5145 continue;
5146
5147 if (Extension.Features.none())
5148 report_fatal_error("unsupported architectural extension: " + Name);
5149
5150 FeatureBitset ToggleFeatures = EnableFeature
5151 ? (~Features & Extension.Features)
5152 : ( Features & Extension.Features);
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00005153 FeatureBitset Features =
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005154 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5155 setAvailableFeatures(Features);
5156 break;
5157 }
5158 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005159 return false;
5160}
5161
Martin Storsjo20187772018-12-30 21:06:32 +00005162/// parseDirectiveArchExtension
5163/// ::= .arch_extension [no]feature
5164bool AArch64AsmParser::parseDirectiveArchExtension(SMLoc L) {
Sander de Smalen772e4732019-04-04 09:11:17 +00005165 SMLoc ExtLoc = getLoc();
Martin Storsjo20187772018-12-30 21:06:32 +00005166
Sander de Smalen772e4732019-04-04 09:11:17 +00005167 StringRef Name = getParser().parseStringToEndOfStatement().trim();
Martin Storsjo20187772018-12-30 21:06:32 +00005168
5169 if (parseToken(AsmToken::EndOfStatement,
5170 "unexpected token in '.arch_extension' directive"))
5171 return true;
5172
5173 bool EnableFeature = true;
5174 if (Name.startswith_lower("no")) {
5175 EnableFeature = false;
5176 Name = Name.substr(2);
5177 }
5178
5179 MCSubtargetInfo &STI = copySTI();
5180 FeatureBitset Features = STI.getFeatureBits();
5181 for (const auto &Extension : ExtensionMap) {
5182 if (Extension.Name != Name)
5183 continue;
5184
5185 if (Extension.Features.none())
5186 return Error(ExtLoc, "unsupported architectural extension: " + Name);
5187
5188 FeatureBitset ToggleFeatures = EnableFeature
5189 ? (~Features & Extension.Features)
5190 : (Features & Extension.Features);
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00005191 FeatureBitset Features =
Martin Storsjo20187772018-12-30 21:06:32 +00005192 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5193 setAvailableFeatures(Features);
5194 return false;
5195 }
5196
5197 return Error(ExtLoc, "unknown architectural extension: " + Name);
5198}
5199
Tim Northover8b96c7e2017-05-15 19:42:15 +00005200static SMLoc incrementLoc(SMLoc L, int Offset) {
5201 return SMLoc::getFromPointer(L.getPointer() + Offset);
5202}
5203
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005204/// parseDirectiveCPU
5205/// ::= .cpu id
5206bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005207 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005208
5209 StringRef CPU, ExtensionString;
5210 std::tie(CPU, ExtensionString) =
5211 getParser().parseStringToEndOfStatement().trim().split('+');
5212
Nirav Davee833c6c2016-11-08 18:31:04 +00005213 if (parseToken(AsmToken::EndOfStatement))
5214 return true;
5215
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005216 SmallVector<StringRef, 4> RequestedExtensions;
5217 if (!ExtensionString.empty())
5218 ExtensionString.split(RequestedExtensions, '+');
5219
5220 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
5221 // once that is tablegen'ed
5222 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005223 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005224 return false;
5225 }
5226
5227 MCSubtargetInfo &STI = copySTI();
5228 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00005229 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005230
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005231 ExpandCryptoAEK(llvm::AArch64::getCPUArchKind(CPU), RequestedExtensions);
5232
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005233 FeatureBitset Features = STI.getFeatureBits();
5234 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005235 // Advance source location past '+'.
5236 CurLoc = incrementLoc(CurLoc, 1);
5237
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005238 bool EnableFeature = true;
5239
5240 if (Name.startswith_lower("no")) {
5241 EnableFeature = false;
5242 Name = Name.substr(2);
5243 }
5244
Tim Northover8b96c7e2017-05-15 19:42:15 +00005245 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005246 for (const auto &Extension : ExtensionMap) {
5247 if (Extension.Name != Name)
5248 continue;
5249
5250 if (Extension.Features.none())
5251 report_fatal_error("unsupported architectural extension: " + Name);
5252
5253 FeatureBitset ToggleFeatures = EnableFeature
5254 ? (~Features & Extension.Features)
5255 : ( Features & Extension.Features);
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00005256 FeatureBitset Features =
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005257 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5258 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00005259 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005260
5261 break;
5262 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00005263
5264 if (!FoundExtension)
5265 Error(CurLoc, "unsupported architectural extension");
5266
5267 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005268 }
5269 return false;
5270}
5271
Chad Rosierdcd2a302014-10-22 20:35:57 +00005272/// parseDirectiveInst
5273/// ::= .inst opcode [, ...]
5274bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005275 if (getLexer().is(AsmToken::EndOfStatement))
5276 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005277
Nirav Davee833c6c2016-11-08 18:31:04 +00005278 auto parseOp = [&]() -> bool {
5279 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00005280 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00005281 if (check(getParser().parseExpression(Expr), L, "expected expression"))
5282 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005283 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00005284 if (check(!Value, L, "expected constant expression"))
5285 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005286 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00005287 return false;
5288 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00005289
Nirav Davee833c6c2016-11-08 18:31:04 +00005290 if (parseMany(parseOp))
5291 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005292 return false;
5293}
5294
Tim Northover3b0846e2014-05-24 12:50:23 +00005295// parseDirectiveTLSDescCall:
5296// ::= .tlsdesccall symbol
5297bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
5298 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00005299 if (check(getParser().parseIdentifier(Name), L,
5300 "expected symbol after directive") ||
5301 parseToken(AsmToken::EndOfStatement))
5302 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005303
Jim Grosbach6f482002015-05-18 18:43:14 +00005304 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00005305 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
5306 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00005307
5308 MCInst Inst;
5309 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00005310 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00005311
Akira Hatanakabd9fc282015-11-14 05:20:05 +00005312 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00005313 return false;
5314}
5315
5316/// ::= .loh <lohName | lohId> label1, ..., labelN
5317/// The number of arguments depends on the loh identifier.
5318bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00005319 MCLOHType Kind;
5320 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5321 if (getParser().getTok().isNot(AsmToken::Integer))
5322 return TokError("expected an identifier or a number in directive");
5323 // We successfully get a numeric value for the identifier.
5324 // Check if it is valid.
5325 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00005326 if (Id <= -1U && !isValidMCLOHType(Id))
5327 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00005328 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00005329 } else {
5330 StringRef Name = getTok().getIdentifier();
5331 // We successfully parse an identifier.
5332 // Check if it is a recognized one.
5333 int Id = MCLOHNameToId(Name);
5334
5335 if (Id == -1)
5336 return TokError("invalid identifier in directive");
5337 Kind = (MCLOHType)Id;
5338 }
5339 // Consume the identifier.
5340 Lex();
5341 // Get the number of arguments of this LOH.
5342 int NbArgs = MCLOHIdToNbArgs(Kind);
5343
5344 assert(NbArgs != -1 && "Invalid number of arguments");
5345
5346 SmallVector<MCSymbol *, 3> Args;
5347 for (int Idx = 0; Idx < NbArgs; ++Idx) {
5348 StringRef Name;
5349 if (getParser().parseIdentifier(Name))
5350 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00005351 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00005352
5353 if (Idx + 1 == NbArgs)
5354 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00005355 if (parseToken(AsmToken::Comma,
5356 "unexpected token in '" + Twine(IDVal) + "' directive"))
5357 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005358 }
Nirav Davee833c6c2016-11-08 18:31:04 +00005359 if (parseToken(AsmToken::EndOfStatement,
5360 "unexpected token in '" + Twine(IDVal) + "' directive"))
5361 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005362
5363 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
5364 return false;
5365}
5366
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005367/// parseDirectiveLtorg
5368/// ::= .ltorg | .pool
5369bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005370 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5371 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005372 getTargetStreamer().emitCurrentConstantPool();
5373 return false;
5374}
5375
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005376/// parseDirectiveReq
5377/// ::= name .req registername
5378bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005379 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005380 Parser.Lex(); // Eat the '.req' token.
5381 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00005382 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00005383 unsigned RegNum;
5384 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005385
Sander de Smalen50d87022018-04-19 07:35:08 +00005386 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005387 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00005388 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005389 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00005390
Sander de Smalen50d87022018-04-19 07:35:08 +00005391 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00005392 return true;
5393
Sander de Smalen50d87022018-04-19 07:35:08 +00005394 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00005395 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005396 }
5397
Sander de Smalen50d87022018-04-19 07:35:08 +00005398 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005399 StringRef Kind;
5400 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005401 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00005402 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005403
Sander de Smalen50d87022018-04-19 07:35:08 +00005404 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00005405 return true;
5406
Sander de Smalen50d87022018-04-19 07:35:08 +00005407 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00005408 return Error(SRegLoc,
5409 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00005410 }
5411
Sander de Smalen50d87022018-04-19 07:35:08 +00005412 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00005413 StringRef Kind;
5414 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005415 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00005416
Sander de Smalen50d87022018-04-19 07:35:08 +00005417 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00005418 return true;
5419
Sander de Smalen50d87022018-04-19 07:35:08 +00005420 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00005421 return Error(SRegLoc,
5422 "sve predicate register without type specifier expected");
5423 }
5424
Sander de Smalen50d87022018-04-19 07:35:08 +00005425 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00005426 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005427
5428 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00005429 if (parseToken(AsmToken::EndOfStatement,
5430 "unexpected input in .req directive"))
5431 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005432
Sander de Smalen8e607342017-11-15 15:44:43 +00005433 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00005434 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005435 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
5436
Nirav Dave2364748a2016-09-16 18:30:20 +00005437 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005438}
5439
5440/// parseDirectiveUneq
5441/// ::= .unreq registername
5442bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005443 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00005444 if (getTok().isNot(AsmToken::Identifier))
5445 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005446 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
5447 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00005448 if (parseToken(AsmToken::EndOfStatement))
5449 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005450 return false;
5451}
5452
Luke Cheesemanf57d7d82018-12-18 10:37:42 +00005453bool AArch64AsmParser::parseDirectiveCFINegateRAState() {
5454 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5455 return true;
5456 getStreamer().EmitCFINegateRAState();
5457 return false;
5458}
5459
Luke Cheeseman41a9e532018-12-21 10:45:08 +00005460/// parseDirectiveCFIBKeyFrame
5461/// ::= .cfi_b_key
5462bool AArch64AsmParser::parseDirectiveCFIBKeyFrame() {
5463 if (parseToken(AsmToken::EndOfStatement,
5464 "unexpected token in '.cfi_b_key_frame'"))
5465 return true;
5466 getStreamer().EmitCFIBKeyFrame();
5467 return false;
5468}
5469
Tim Northover3b0846e2014-05-24 12:50:23 +00005470bool
5471AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
5472 AArch64MCExpr::VariantKind &ELFRefKind,
5473 MCSymbolRefExpr::VariantKind &DarwinRefKind,
5474 int64_t &Addend) {
5475 ELFRefKind = AArch64MCExpr::VK_INVALID;
5476 DarwinRefKind = MCSymbolRefExpr::VK_None;
5477 Addend = 0;
5478
5479 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5480 ELFRefKind = AE->getKind();
5481 Expr = AE->getSubExpr();
5482 }
5483
5484 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5485 if (SE) {
5486 // It's a simple symbol reference with no addend.
5487 DarwinRefKind = SE->getKind();
5488 return true;
5489 }
5490
David Green85d6a552018-09-18 09:44:53 +00005491 // Check that it looks like a symbol + an addend
5492 MCValue Res;
5493 bool Relocatable = Expr->evaluateAsRelocatable(Res, nullptr, nullptr);
Eli Friedman48397102018-12-20 19:46:14 +00005494 if (!Relocatable || Res.getSymB())
Tim Northover3b0846e2014-05-24 12:50:23 +00005495 return false;
5496
Eli Friedman48397102018-12-20 19:46:14 +00005497 // Treat expressions with an ELFRefKind (like ":abs_g1:3", or
5498 // ":abs_g1:x" where x is constant) as symbolic even if there is no symbol.
5499 if (!Res.getSymA() && ELFRefKind == AArch64MCExpr::VK_INVALID)
5500 return false;
5501
5502 if (Res.getSymA())
5503 DarwinRefKind = Res.getSymA()->getKind();
David Green85d6a552018-09-18 09:44:53 +00005504 Addend = Res.getConstant();
Tim Northover3b0846e2014-05-24 12:50:23 +00005505
5506 // It's some symbol reference + a constant addend, but really
5507 // shouldn't use both Darwin and ELF syntax.
5508 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5509 DarwinRefKind == MCSymbolRefExpr::VK_None;
5510}
5511
5512/// Force static initialization.
5513extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00005514 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5515 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5516 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northoverff6875a2019-05-14 11:25:44 +00005517 RegisterMCAsmParser<AArch64AsmParser> W(getTheARM64_32Target());
5518 RegisterMCAsmParser<AArch64AsmParser> V(getTheAArch64_32Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00005519}
5520
5521#define GET_REGISTER_MATCHER
5522#define GET_SUBTARGET_FEATURE_NAME
5523#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00005524#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00005525#include "AArch64GenAsmMatcher.inc"
5526
5527// Define this matcher function after the auto-generated include so we
5528// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00005529unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00005530 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005531 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00005532 // If the kind is a token for a literal immediate, check if our asm
5533 // operand matches. This is for InstAliases which have a fixed-value
5534 // immediate in the syntax.
5535 int64_t ExpectedVal;
5536 switch (Kind) {
5537 default:
5538 return Match_InvalidOperand;
5539 case MCK__35_0:
5540 ExpectedVal = 0;
5541 break;
5542 case MCK__35_1:
5543 ExpectedVal = 1;
5544 break;
5545 case MCK__35_12:
5546 ExpectedVal = 12;
5547 break;
5548 case MCK__35_16:
5549 ExpectedVal = 16;
5550 break;
5551 case MCK__35_2:
5552 ExpectedVal = 2;
5553 break;
5554 case MCK__35_24:
5555 ExpectedVal = 24;
5556 break;
5557 case MCK__35_3:
5558 ExpectedVal = 3;
5559 break;
5560 case MCK__35_32:
5561 ExpectedVal = 32;
5562 break;
5563 case MCK__35_4:
5564 ExpectedVal = 4;
5565 break;
5566 case MCK__35_48:
5567 ExpectedVal = 48;
5568 break;
5569 case MCK__35_6:
5570 ExpectedVal = 6;
5571 break;
5572 case MCK__35_64:
5573 ExpectedVal = 64;
5574 break;
5575 case MCK__35_8:
5576 ExpectedVal = 8;
5577 break;
5578 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005579 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005580 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005581 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005582 if (!CE)
5583 return Match_InvalidOperand;
5584 if (CE->getValue() == ExpectedVal)
5585 return Match_Success;
5586 return Match_InvalidOperand;
5587}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005588
Alex Bradbury58eba092016-11-01 16:32:05 +00005589OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005590AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5591
5592 SMLoc S = getLoc();
5593
5594 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5595 Error(S, "expected register");
5596 return MatchOperand_ParseFail;
5597 }
5598
Sander de Smalen50d87022018-04-19 07:35:08 +00005599 unsigned FirstReg;
5600 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5601 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005602 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005603
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005604 const MCRegisterClass &WRegClass =
5605 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5606 const MCRegisterClass &XRegClass =
5607 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5608
5609 bool isXReg = XRegClass.contains(FirstReg),
5610 isWReg = WRegClass.contains(FirstReg);
5611 if (!isXReg && !isWReg) {
5612 Error(S, "expected first even register of a "
5613 "consecutive same-size even/odd register pair");
5614 return MatchOperand_ParseFail;
5615 }
5616
5617 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5618 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5619
5620 if (FirstEncoding & 0x1) {
5621 Error(S, "expected first even register of a "
5622 "consecutive same-size even/odd register pair");
5623 return MatchOperand_ParseFail;
5624 }
5625
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005626 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005627 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005628 return MatchOperand_ParseFail;
5629 }
5630 // Eat the comma
5631 getParser().Lex();
5632
5633 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005634 unsigned SecondReg;
5635 Res = tryParseScalarRegister(SecondReg);
5636 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005637 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005638
Eugene Zelenko049b0172017-01-06 00:30:53 +00005639 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005640 (isXReg && !XRegClass.contains(SecondReg)) ||
5641 (isWReg && !WRegClass.contains(SecondReg))) {
5642 Error(E,"expected second odd register of a "
5643 "consecutive same-size even/odd register pair");
5644 return MatchOperand_ParseFail;
5645 }
Joel Jones504bf332016-10-24 13:37:13 +00005646
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005647 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005648 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005649 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5650 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5651 } else {
5652 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5653 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5654 }
5655
Florian Hahnc4422242017-11-07 13:07:50 +00005656 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5657 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005658
5659 return MatchOperand_Success;
5660}
Florian Hahn91f11e52017-11-07 16:45:48 +00005661
Sander de Smaleneb896b12018-04-25 09:26:47 +00005662template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005663OperandMatchResultTy
5664AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005665 const SMLoc S = getLoc();
5666 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005667 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005668 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005669
Sander de Smalen8e607342017-11-15 15:44:43 +00005670 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005671 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005672
5673 if (Res != MatchOperand_Success)
5674 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005675
5676 if (ParseSuffix && Kind.empty())
5677 return MatchOperand_NoMatch;
5678
Sander de Smalen73937b72018-04-11 07:36:10 +00005679 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5680 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005681 return MatchOperand_NoMatch;
5682
Sander de Smalen73937b72018-04-11 07:36:10 +00005683 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005684
5685 // No shift/extend is the default.
5686 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5687 Operands.push_back(AArch64Operand::CreateVectorReg(
5688 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5689
Sander de Smalenc33d6682018-06-04 06:40:55 +00005690 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5691 if (Res == MatchOperand_ParseFail)
5692 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005693 return MatchOperand_Success;
5694 }
5695
5696 // Eat the comma
5697 getParser().Lex();
5698
5699 // Match the shift
5700 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5701 Res = tryParseOptionalShiftExtend(ExtOpnd);
5702 if (Res != MatchOperand_Success)
5703 return Res;
5704
5705 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005706 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005707 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5708 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5709 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005710
5711 return MatchOperand_Success;
5712}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005713
5714OperandMatchResultTy
5715AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5716 MCAsmParser &Parser = getParser();
5717
5718 SMLoc SS = getLoc();
5719 const AsmToken &TokE = Parser.getTok();
5720 bool IsHash = TokE.is(AsmToken::Hash);
5721
5722 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5723 return MatchOperand_NoMatch;
5724
5725 int64_t Pattern;
5726 if (IsHash) {
5727 Parser.Lex(); // Eat hash
5728
5729 // Parse the immediate operand.
5730 const MCExpr *ImmVal;
5731 SS = getLoc();
5732 if (Parser.parseExpression(ImmVal))
5733 return MatchOperand_ParseFail;
5734
5735 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5736 if (!MCE)
5737 return MatchOperand_ParseFail;
5738
5739 Pattern = MCE->getValue();
5740 } else {
5741 // Parse the pattern
5742 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5743 if (!Pat)
5744 return MatchOperand_NoMatch;
5745
5746 Parser.Lex();
5747 Pattern = Pat->Encoding;
5748 assert(Pattern >= 0 && Pattern < 32);
5749 }
5750
5751 Operands.push_back(
5752 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5753 SS, getLoc(), getContext()));
5754
5755 return MatchOperand_Success;
5756}