blob: 7345ff38edb58b6495bf2825942fa2070e387bc7 [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
Alex Bradbury0a59f182018-05-23 11:17:20 +0000244 // Alias .hword/.word/xword to the target-independent .2byte/.4byte/.8byte
245 // directives as they have the same form and semantics:
246 /// ::= (.hword | .word | .xword ) [ expression (, expression)* ]
247 Parser.addAliasForDirective(".hword", ".2byte");
248 Parser.addAliasForDirective(".word", ".4byte");
249 Parser.addAliasForDirective(".xword", ".8byte");
250
Tim Northover3b0846e2014-05-24 12:50:23 +0000251 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000252 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000253 }
254
Sander de Smalen0325e302018-07-02 07:34:52 +0000255 bool regsEqual(const MCParsedAsmOperand &Op1,
256 const MCParsedAsmOperand &Op2) const override;
Tim Northover3b0846e2014-05-24 12:50:23 +0000257 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
258 SMLoc NameLoc, OperandVector &Operands) override;
259 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
260 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000261 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000262 unsigned Kind) override;
263
264 static bool classifySymbolRef(const MCExpr *Expr,
265 AArch64MCExpr::VariantKind &ELFRefKind,
266 MCSymbolRefExpr::VariantKind &DarwinRefKind,
267 int64_t &Addend);
268};
Tim Northover3b0846e2014-05-24 12:50:23 +0000269
270/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
271/// instruction.
272class AArch64Operand : public MCParsedAsmOperand {
273private:
274 enum KindTy {
275 k_Immediate,
276 k_ShiftedImm,
277 k_CondCode,
278 k_Register,
279 k_VectorList,
280 k_VectorIndex,
281 k_Token,
282 k_SysReg,
283 k_SysCR,
284 k_Prefetch,
285 k_ShiftExtend,
286 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000287 k_Barrier,
288 k_PSBHint,
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000289 k_BTIHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000290 } Kind;
291
292 SMLoc StartLoc, EndLoc;
293
294 struct TokOp {
295 const char *Data;
296 unsigned Length;
297 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
298 };
299
Sander de Smalen149916d2018-04-20 07:24:20 +0000300 // Separate shift/extend operand.
301 struct ShiftExtendOp {
302 AArch64_AM::ShiftExtendType Type;
303 unsigned Amount;
304 bool HasExplicitAmount;
305 };
306
Tim Northover3b0846e2014-05-24 12:50:23 +0000307 struct RegOp {
308 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000309 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000310 int ElementWidth;
Sander de Smalen149916d2018-04-20 07:24:20 +0000311
Sander de Smalen0325e302018-07-02 07:34:52 +0000312 // The register may be allowed as a different register class,
313 // e.g. for GPR64as32 or GPR32as64.
314 RegConstraintEqualityTy EqualityTy;
315
Sander de Smalen149916d2018-04-20 07:24:20 +0000316 // In some cases the shift/extend needs to be explicitly parsed together
317 // with the register, rather than as a separate operand. This is needed
318 // for addressing modes where the instruction as a whole dictates the
319 // scaling/extend, rather than specific bits in the instruction.
320 // By parsing them as a single operand, we avoid the need to pass an
321 // extra operand in all CodeGen patterns (because all operands need to
322 // have an associated value), and we avoid the need to update TableGen to
323 // accept operands that have no associated bits in the instruction.
324 //
325 // An added benefit of parsing them together is that the assembler
326 // can give a sensible diagnostic if the scaling is not correct.
327 //
328 // The default is 'lsl #0' (HasExplicitAmount = false) if no
329 // ShiftExtend is specified.
330 ShiftExtendOp ShiftExtend;
Tim Northover3b0846e2014-05-24 12:50:23 +0000331 };
332
333 struct VectorListOp {
334 unsigned RegNum;
335 unsigned Count;
336 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000337 unsigned ElementWidth;
338 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000339 };
340
341 struct VectorIndexOp {
342 unsigned Val;
343 };
344
345 struct ImmOp {
346 const MCExpr *Val;
347 };
348
349 struct ShiftedImmOp {
350 const MCExpr *Val;
351 unsigned ShiftAmount;
352 };
353
354 struct CondCodeOp {
355 AArch64CC::CondCode Code;
356 };
357
358 struct FPImmOp {
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000359 uint64_t Val; // APFloat value bitcasted to uint64_t.
360 bool IsExact; // describes whether parsed value was exact.
Tim Northover3b0846e2014-05-24 12:50:23 +0000361 };
362
363 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000364 const char *Data;
365 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000366 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000367 };
368
369 struct SysRegOp {
370 const char *Data;
371 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000372 uint32_t MRSReg;
373 uint32_t MSRReg;
374 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000375 };
376
377 struct SysCRImmOp {
378 unsigned Val;
379 };
380
381 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000382 const char *Data;
383 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000384 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000385 };
386
Oliver Stannarda34e4702015-12-01 10:48:51 +0000387 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000388 const char *Data;
389 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000390 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000391 };
392
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000393 struct BTIHintOp {
394 const char *Data;
395 unsigned Length;
396 unsigned Val;
397 };
398
Tim Northover3b0846e2014-05-24 12:50:23 +0000399 struct ExtendOp {
400 unsigned Val;
401 };
402
403 union {
404 struct TokOp Tok;
405 struct RegOp Reg;
406 struct VectorListOp VectorList;
407 struct VectorIndexOp VectorIndex;
408 struct ImmOp Imm;
409 struct ShiftedImmOp ShiftedImm;
410 struct CondCodeOp CondCode;
411 struct FPImmOp FPImm;
412 struct BarrierOp Barrier;
413 struct SysRegOp SysReg;
414 struct SysCRImmOp SysCRImm;
415 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000416 struct PSBHintOp PSBHint;
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000417 struct BTIHintOp BTIHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000418 struct ShiftExtendOp ShiftExtend;
419 };
420
421 // Keep the MCContext around as the MCExprs may need manipulated during
422 // the add<>Operands() calls.
423 MCContext &Ctx;
424
David Blaikie960ea3f2014-06-08 16:18:35 +0000425public:
David Blaikie9f380a32015-03-16 18:06:57 +0000426 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000427
Tim Northover3b0846e2014-05-24 12:50:23 +0000428 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
429 Kind = o.Kind;
430 StartLoc = o.StartLoc;
431 EndLoc = o.EndLoc;
432 switch (Kind) {
433 case k_Token:
434 Tok = o.Tok;
435 break;
436 case k_Immediate:
437 Imm = o.Imm;
438 break;
439 case k_ShiftedImm:
440 ShiftedImm = o.ShiftedImm;
441 break;
442 case k_CondCode:
443 CondCode = o.CondCode;
444 break;
445 case k_FPImm:
446 FPImm = o.FPImm;
447 break;
448 case k_Barrier:
449 Barrier = o.Barrier;
450 break;
451 case k_Register:
452 Reg = o.Reg;
453 break;
454 case k_VectorList:
455 VectorList = o.VectorList;
456 break;
457 case k_VectorIndex:
458 VectorIndex = o.VectorIndex;
459 break;
460 case k_SysReg:
461 SysReg = o.SysReg;
462 break;
463 case k_SysCR:
464 SysCRImm = o.SysCRImm;
465 break;
466 case k_Prefetch:
467 Prefetch = o.Prefetch;
468 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000469 case k_PSBHint:
470 PSBHint = o.PSBHint;
471 break;
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000472 case k_BTIHint:
473 BTIHint = o.BTIHint;
474 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000475 case k_ShiftExtend:
476 ShiftExtend = o.ShiftExtend;
477 break;
478 }
479 }
480
481 /// getStartLoc - Get the location of the first token of this operand.
482 SMLoc getStartLoc() const override { return StartLoc; }
483 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000484 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000485
486 StringRef getToken() const {
487 assert(Kind == k_Token && "Invalid access!");
488 return StringRef(Tok.Data, Tok.Length);
489 }
490
491 bool isTokenSuffix() const {
492 assert(Kind == k_Token && "Invalid access!");
493 return Tok.IsSuffix;
494 }
495
496 const MCExpr *getImm() const {
497 assert(Kind == k_Immediate && "Invalid access!");
498 return Imm.Val;
499 }
500
501 const MCExpr *getShiftedImmVal() const {
502 assert(Kind == k_ShiftedImm && "Invalid access!");
503 return ShiftedImm.Val;
504 }
505
506 unsigned getShiftedImmShift() const {
507 assert(Kind == k_ShiftedImm && "Invalid access!");
508 return ShiftedImm.ShiftAmount;
509 }
510
511 AArch64CC::CondCode getCondCode() const {
512 assert(Kind == k_CondCode && "Invalid access!");
513 return CondCode.Code;
514 }
515
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000516 APFloat getFPImm() const {
517 assert (Kind == k_FPImm && "Invalid access!");
518 return APFloat(APFloat::IEEEdouble(), APInt(64, FPImm.Val, true));
519 }
520
521 bool getFPImmIsExact() const {
522 assert (Kind == k_FPImm && "Invalid access!");
523 return FPImm.IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +0000524 }
525
526 unsigned getBarrier() const {
527 assert(Kind == k_Barrier && "Invalid access!");
528 return Barrier.Val;
529 }
530
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000531 StringRef getBarrierName() const {
532 assert(Kind == k_Barrier && "Invalid access!");
533 return StringRef(Barrier.Data, Barrier.Length);
534 }
535
Tim Northover3b0846e2014-05-24 12:50:23 +0000536 unsigned getReg() const override {
537 assert(Kind == k_Register && "Invalid access!");
538 return Reg.RegNum;
539 }
540
Sander de Smalen0325e302018-07-02 07:34:52 +0000541 RegConstraintEqualityTy getRegEqualityTy() const {
542 assert(Kind == k_Register && "Invalid access!");
543 return Reg.EqualityTy;
544 }
545
Tim Northover3b0846e2014-05-24 12:50:23 +0000546 unsigned getVectorListStart() const {
547 assert(Kind == k_VectorList && "Invalid access!");
548 return VectorList.RegNum;
549 }
550
551 unsigned getVectorListCount() const {
552 assert(Kind == k_VectorList && "Invalid access!");
553 return VectorList.Count;
554 }
555
556 unsigned getVectorIndex() const {
557 assert(Kind == k_VectorIndex && "Invalid access!");
558 return VectorIndex.Val;
559 }
560
561 StringRef getSysReg() const {
562 assert(Kind == k_SysReg && "Invalid access!");
563 return StringRef(SysReg.Data, SysReg.Length);
564 }
565
Tim Northover3b0846e2014-05-24 12:50:23 +0000566 unsigned getSysCR() const {
567 assert(Kind == k_SysCR && "Invalid access!");
568 return SysCRImm.Val;
569 }
570
571 unsigned getPrefetch() const {
572 assert(Kind == k_Prefetch && "Invalid access!");
573 return Prefetch.Val;
574 }
575
Oliver Stannarda34e4702015-12-01 10:48:51 +0000576 unsigned getPSBHint() const {
577 assert(Kind == k_PSBHint && "Invalid access!");
578 return PSBHint.Val;
579 }
580
581 StringRef getPSBHintName() const {
582 assert(Kind == k_PSBHint && "Invalid access!");
583 return StringRef(PSBHint.Data, PSBHint.Length);
584 }
585
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000586 unsigned getBTIHint() const {
587 assert(Kind == k_BTIHint && "Invalid access!");
588 return BTIHint.Val;
589 }
590
591 StringRef getBTIHintName() const {
592 assert(Kind == k_BTIHint && "Invalid access!");
593 return StringRef(BTIHint.Data, BTIHint.Length);
594 }
595
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000596 StringRef getPrefetchName() const {
597 assert(Kind == k_Prefetch && "Invalid access!");
598 return StringRef(Prefetch.Data, Prefetch.Length);
599 }
600
Tim Northover3b0846e2014-05-24 12:50:23 +0000601 AArch64_AM::ShiftExtendType getShiftExtendType() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000602 if (Kind == k_ShiftExtend)
603 return ShiftExtend.Type;
604 if (Kind == k_Register)
605 return Reg.ShiftExtend.Type;
606 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000607 }
608
609 unsigned getShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000610 if (Kind == k_ShiftExtend)
611 return ShiftExtend.Amount;
612 if (Kind == k_Register)
613 return Reg.ShiftExtend.Amount;
614 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000615 }
616
617 bool hasShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000618 if (Kind == k_ShiftExtend)
619 return ShiftExtend.HasExplicitAmount;
620 if (Kind == k_Register)
621 return Reg.ShiftExtend.HasExplicitAmount;
622 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000623 }
624
625 bool isImm() const override { return Kind == k_Immediate; }
626 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000627
Sjoerd Meijera3dad802018-07-06 12:32:33 +0000628 bool isUImm6() const {
629 if (!isImm())
630 return false;
631 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
632 if (!MCE)
633 return false;
634 int64_t Val = MCE->getValue();
635 return (Val >= 0 && Val < 64);
636 }
637
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000638 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
639
Sander de Smalen50ded902018-04-29 17:33:38 +0000640 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
641 return isImmScaled<Bits, Scale>(true);
642 }
643
644 template <int Bits, int Scale> DiagnosticPredicate isUImmScaled() const {
645 return isImmScaled<Bits, Scale>(false);
646 }
647
Sander de Smalenfe17a782018-04-26 12:54:42 +0000648 template <int Bits, int Scale>
Sander de Smalen50ded902018-04-29 17:33:38 +0000649 DiagnosticPredicate isImmScaled(bool Signed) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000650 if (!isImm())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000651 return DiagnosticPredicateTy::NoMatch;
652
Tim Northover3b0846e2014-05-24 12:50:23 +0000653 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
654 if (!MCE)
Sander de Smalenfe17a782018-04-26 12:54:42 +0000655 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000656
Sander de Smalen50ded902018-04-29 17:33:38 +0000657 int64_t MinVal, MaxVal;
658 if (Signed) {
659 int64_t Shift = Bits - 1;
660 MinVal = (int64_t(1) << Shift) * -Scale;
661 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
662 } else {
663 MinVal = 0;
664 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
665 }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000666
Tim Northover3b0846e2014-05-24 12:50:23 +0000667 int64_t Val = MCE->getValue();
Sander de Smalenfe17a782018-04-26 12:54:42 +0000668 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
669 return DiagnosticPredicateTy::Match;
670
671 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +0000672 }
673
Sander de Smalen0325e302018-07-02 07:34:52 +0000674 DiagnosticPredicate isSVEPattern() const {
Sander de Smalen245e0e62018-01-22 10:46:00 +0000675 if (!isImm())
Sander de Smalen0325e302018-07-02 07:34:52 +0000676 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000677 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
678 if (!MCE)
Sander de Smalen0325e302018-07-02 07:34:52 +0000679 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000680 int64_t Val = MCE->getValue();
Sander de Smalen0325e302018-07-02 07:34:52 +0000681 if (Val >= 0 && Val < 32)
682 return DiagnosticPredicateTy::Match;
683 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000684 }
685
David Green85d6a552018-09-18 09:44:53 +0000686 bool isSymbolicUImm12Offset(const MCExpr *Expr) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000687 AArch64MCExpr::VariantKind ELFRefKind;
688 MCSymbolRefExpr::VariantKind DarwinRefKind;
689 int64_t Addend;
690 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
691 Addend)) {
692 // If we don't understand the expression, assume the best and
693 // let the fixup and relocation code deal with it.
694 return true;
695 }
696
697 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
698 ELFRefKind == AArch64MCExpr::VK_LO12 ||
699 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
700 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
701 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
702 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
703 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
704 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000705 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
706 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
707 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000708 // Note that we don't range-check the addend. It's adjusted modulo page
709 // size when converted, so there is no "out of range" condition when using
710 // @pageoff.
David Green85d6a552018-09-18 09:44:53 +0000711 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000712 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
713 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
714 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
715 return Addend == 0;
716 }
717
718 return false;
719 }
720
721 template <int Scale> bool isUImm12Offset() const {
722 if (!isImm())
723 return false;
724
725 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
726 if (!MCE)
David Green85d6a552018-09-18 09:44:53 +0000727 return isSymbolicUImm12Offset(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +0000728
729 int64_t Val = MCE->getValue();
730 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
731 }
732
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000733 template <int N, int M>
734 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000735 if (!isImm())
736 return false;
737 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
738 if (!MCE)
739 return false;
740 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000741 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000742 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000743
Sander de Smalena1c259c2018-01-29 13:05:38 +0000744 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
745 // a logical immediate can always be represented when inverted.
746 template <typename T>
747 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000748 if (!isImm())
749 return false;
750 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
751 if (!MCE)
752 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000753
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000754 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000755 int64_t SVal = typename std::make_signed<T>::type(Val);
756 int64_t UVal = typename std::make_unsigned<T>::type(Val);
757 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000758 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000759
Sander de Smalena1c259c2018-01-29 13:05:38 +0000760 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000761 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000762
Tim Northover3b0846e2014-05-24 12:50:23 +0000763 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000764
Sander de Smalen62770792018-05-25 09:47:52 +0000765 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
766 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
767 /// immediate that can be shifted by 'Shift'.
768 template <unsigned Width>
769 Optional<std::pair<int64_t, unsigned> > getShiftedVal() const {
770 if (isShiftedImm() && Width == getShiftedImmShift())
771 if (auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
772 return std::make_pair(CE->getValue(), Width);
773
774 if (isImm())
775 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
776 int64_t Val = CE->getValue();
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000777 if ((Val != 0) && (uint64_t(Val >> Width) << Width) == uint64_t(Val))
Sander de Smalen62770792018-05-25 09:47:52 +0000778 return std::make_pair(Val >> Width, Width);
779 else
780 return std::make_pair(Val, 0u);
781 }
782
783 return {};
784 }
785
Tim Northover3b0846e2014-05-24 12:50:23 +0000786 bool isAddSubImm() const {
787 if (!isShiftedImm() && !isImm())
788 return false;
789
790 const MCExpr *Expr;
791
792 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
793 if (isShiftedImm()) {
794 unsigned Shift = ShiftedImm.ShiftAmount;
795 Expr = ShiftedImm.Val;
796 if (Shift != 0 && Shift != 12)
797 return false;
798 } else {
799 Expr = getImm();
800 }
801
802 AArch64MCExpr::VariantKind ELFRefKind;
803 MCSymbolRefExpr::VariantKind DarwinRefKind;
804 int64_t Addend;
805 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
806 DarwinRefKind, Addend)) {
807 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
808 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
809 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
810 || ELFRefKind == AArch64MCExpr::VK_LO12
811 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
812 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
813 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
814 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
815 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
816 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000817 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
818 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
819 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000820 }
821
Sander de Smalen98686c62018-05-29 10:39:49 +0000822 // If it's a constant, it should be a real immediate in range.
Sander de Smalen62770792018-05-25 09:47:52 +0000823 if (auto ShiftedVal = getShiftedVal<12>())
824 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
Diana Picusc93518d2016-10-11 09:17:47 +0000825
826 // If it's an expression, we hope for the best and let the fixup/relocation
827 // code deal with it.
828 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000829 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000830
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000831 bool isAddSubImmNeg() const {
832 if (!isShiftedImm() && !isImm())
833 return false;
834
Sander de Smalen98686c62018-05-29 10:39:49 +0000835 // Otherwise it should be a real negative immediate in range.
836 if (auto ShiftedVal = getShiftedVal<12>())
837 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000838
Sander de Smalen98686c62018-05-29 10:39:49 +0000839 return false;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000840 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000841
Sander de Smalen62770792018-05-25 09:47:52 +0000842 // Signed value in the range -128 to +127. For element widths of
843 // 16 bits or higher it may also be a signed multiple of 256 in the
844 // range -32768 to +32512.
845 // For element-width of 8 bits a range of -128 to 255 is accepted,
846 // since a copy of a byte can be either signed/unsigned.
847 template <typename T>
848 DiagnosticPredicate isSVECpyImm() const {
849 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
850 return DiagnosticPredicateTy::NoMatch;
851
852 bool IsByte =
853 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
854 if (auto ShiftedImm = getShiftedVal<8>())
855 if (!(IsByte && ShiftedImm->second) &&
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000856 AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
857 << ShiftedImm->second))
Sander de Smalen62770792018-05-25 09:47:52 +0000858 return DiagnosticPredicateTy::Match;
859
860 return DiagnosticPredicateTy::NearMatch;
861 }
862
Sander de Smalen98686c62018-05-29 10:39:49 +0000863 // Unsigned value in the range 0 to 255. For element widths of
864 // 16 bits or higher it may also be a signed multiple of 256 in the
865 // range 0 to 65280.
866 template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
867 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
868 return DiagnosticPredicateTy::NoMatch;
869
870 bool IsByte =
871 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
872 if (auto ShiftedImm = getShiftedVal<8>())
873 if (!(IsByte && ShiftedImm->second) &&
874 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
875 << ShiftedImm->second))
876 return DiagnosticPredicateTy::Match;
877
878 return DiagnosticPredicateTy::NearMatch;
879 }
880
Sander de Smalen97ca6b92018-06-01 07:25:46 +0000881 template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
882 if (isLogicalImm<T>() && !isSVECpyImm<T>())
883 return DiagnosticPredicateTy::Match;
884 return DiagnosticPredicateTy::NoMatch;
885 }
886
Tim Northover3b0846e2014-05-24 12:50:23 +0000887 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000888
Tim Northover3b0846e2014-05-24 12:50:23 +0000889 bool isSIMDImmType10() const {
890 if (!isImm())
891 return false;
892 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
893 if (!MCE)
894 return false;
895 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
896 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000897
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000898 template<int N>
899 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000900 if (!isImm())
901 return false;
902 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
903 if (!MCE)
904 return true;
905 int64_t Val = MCE->getValue();
906 if (Val & 0x3)
907 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000908 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
909 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000910 }
911
912 bool
913 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
914 if (!isImm())
915 return false;
916
917 AArch64MCExpr::VariantKind ELFRefKind;
918 MCSymbolRefExpr::VariantKind DarwinRefKind;
919 int64_t Addend;
920 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
921 DarwinRefKind, Addend)) {
922 return false;
923 }
924 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
925 return false;
926
927 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
928 if (ELFRefKind == AllowedModifiers[i])
David Green85d6a552018-09-18 09:44:53 +0000929 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000930 }
931
932 return false;
933 }
934
935 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000936 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000937 }
938
939 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000940 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
941 AArch64MCExpr::VK_TPREL_G2,
942 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000943 }
944
945 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000946 return isMovWSymbol({
947 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000948 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
949 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000950 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000951 }
952
953 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000954 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
955 AArch64MCExpr::VK_TPREL_G0,
956 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000957 }
958
959 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000960 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000961 }
962
963 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000964 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000965 }
966
967 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000968 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
969 AArch64MCExpr::VK_TPREL_G1_NC,
970 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000971 }
972
973 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000974 return isMovWSymbol(
975 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
976 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000977 }
978
979 template<int RegWidth, int Shift>
980 bool isMOVZMovAlias() const {
981 if (!isImm()) return false;
982
983 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
984 if (!CE) return false;
985 uint64_t Value = CE->getValue();
986
Tim Northoverdaa1c012016-06-16 01:42:25 +0000987 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000988 }
989
990 template<int RegWidth, int Shift>
991 bool isMOVNMovAlias() const {
992 if (!isImm()) return false;
993
994 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
995 if (!CE) return false;
996 uint64_t Value = CE->getValue();
997
Tim Northoverdaa1c012016-06-16 01:42:25 +0000998 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000999 }
1000
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001001 bool isFPImm() const {
1002 return Kind == k_FPImm &&
1003 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt()) != -1;
1004 }
1005
Tim Northover3b0846e2014-05-24 12:50:23 +00001006 bool isBarrier() const { return Kind == k_Barrier; }
1007 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001008
Tim Northover3b0846e2014-05-24 12:50:23 +00001009 bool isMRSSystemRegister() const {
1010 if (!isSysReg()) return false;
1011
Tim Northover7cd58932015-01-22 17:23:04 +00001012 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +00001013 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001014
Tim Northover3b0846e2014-05-24 12:50:23 +00001015 bool isMSRSystemRegister() const {
1016 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +00001017 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +00001018 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001019
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001020 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001021 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +00001022 return (SysReg.PStateField == AArch64PState::PAN ||
Sjoerd Meijer173b7f02018-07-03 12:09:20 +00001023 SysReg.PStateField == AArch64PState::DIT ||
Oliver Stannard8459d342018-09-27 14:05:46 +00001024 SysReg.PStateField == AArch64PState::UAO ||
1025 SysReg.PStateField == AArch64PState::SSBS);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001026 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001027
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001028 bool isSystemPStateFieldWithImm0_15() const {
1029 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +00001030 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +00001031 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001032
Florian Hahnc4422242017-11-07 13:07:50 +00001033 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00001034 return Kind == k_Register;
1035 }
1036
1037 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001038 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
1039 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001040
Florian Hahnc4422242017-11-07 13:07:50 +00001041 bool isNeonVectorReg() const {
1042 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
1043 }
1044
1045 bool isNeonVectorRegLo() const {
1046 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001047 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
1048 Reg.RegNum);
1049 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001050
Sander de Smalencd6be962017-12-20 11:02:42 +00001051 template <unsigned Class> bool isSVEVectorReg() const {
1052 RegKind RK;
1053 switch (Class) {
1054 case AArch64::ZPRRegClassID:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00001055 case AArch64::ZPR_3bRegClassID:
1056 case AArch64::ZPR_4bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +00001057 RK = RegKind::SVEDataVector;
1058 break;
1059 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +00001060 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +00001061 RK = RegKind::SVEPredicateVector;
1062 break;
1063 default:
1064 llvm_unreachable("Unsupport register class");
1065 }
1066
1067 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +00001068 AArch64MCRegisterClasses[Class].contains(getReg());
1069 }
1070
Sander de Smalenfd54a782018-06-04 07:07:35 +00001071 template <unsigned Class> bool isFPRasZPR() const {
1072 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1073 AArch64MCRegisterClasses[Class].contains(getReg());
1074 }
1075
Sander de Smalencd6be962017-12-20 11:02:42 +00001076 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +00001077 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
1078 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
1079 return DiagnosticPredicateTy::NoMatch;
1080
1081 if (isSVEVectorReg<Class>() &&
1082 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
1083 return DiagnosticPredicateTy::Match;
1084
1085 return DiagnosticPredicateTy::NearMatch;
1086 }
1087
1088 template <int ElementWidth, unsigned Class>
1089 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
1090 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
1091 return DiagnosticPredicateTy::NoMatch;
1092
1093 if (isSVEVectorReg<Class>() &&
1094 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
1095 return DiagnosticPredicateTy::Match;
1096
1097 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00001098 }
1099
Sander de Smaleneb896b12018-04-25 09:26:47 +00001100 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +00001101 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
1102 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +00001103 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
1104 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
1105 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001106 return DiagnosticPredicateTy::NoMatch;
1107
Sander de Smalen5861c262018-04-30 07:24:38 +00001108 // Give a more specific diagnostic when the user has explicitly typed in
1109 // a shift-amount that does not match what is expected, but for which
1110 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
1111 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
1112 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
1113 ShiftExtendTy == AArch64_AM::SXTW) &&
1114 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
1115 return DiagnosticPredicateTy::NoMatch;
1116
1117 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001118 return DiagnosticPredicateTy::Match;
1119
1120 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +00001121 }
1122
Tim Northover3b0846e2014-05-24 12:50:23 +00001123 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001124 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001125 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
1126 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001127
Sander de Smalen0325e302018-07-02 07:34:52 +00001128 bool isGPR64as32() const {
1129 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1130 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(Reg.RegNum);
1131 }
1132
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001133 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001134 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001135 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
1136 Reg.RegNum);
1137 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001138
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001139 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001140 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001141 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1142 Reg.RegNum);
1143 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001144
Sam Parker5f934642017-08-31 09:27:04 +00001145 template<int64_t Angle, int64_t Remainder>
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001146 DiagnosticPredicate isComplexRotation() const {
1147 if (!isImm()) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001148
1149 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001150 if (!CE) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001151 uint64_t Value = CE->getValue();
1152
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001153 if (Value % Angle == Remainder && Value <= 270)
1154 return DiagnosticPredicateTy::Match;
1155 return DiagnosticPredicateTy::NearMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001156 }
1157
Sander de Smalen149916d2018-04-20 07:24:20 +00001158 template <unsigned RegClassID> bool isGPR64() const {
1159 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1160 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1161 }
1162
1163 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001164 DiagnosticPredicate isGPR64WithShiftExtend() const {
1165 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1166 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001167
Sander de Smalenfe17a782018-04-26 12:54:42 +00001168 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1169 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1170 return DiagnosticPredicateTy::Match;
1171 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001172 }
1173
Tim Northover3b0846e2014-05-24 12:50:23 +00001174 /// Is this a vector list with the type implicit (presumably attached to the
1175 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001176 template <RegKind VectorKind, unsigned NumRegs>
1177 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001178 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001179 VectorList.NumElements == 0 &&
1180 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001181 }
1182
Sander de Smalen650234b2018-04-12 11:40:52 +00001183 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1184 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001185 bool isTypedVectorList() const {
1186 if (Kind != k_VectorList)
1187 return false;
1188 if (VectorList.Count != NumRegs)
1189 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001190 if (VectorList.RegisterKind != VectorKind)
1191 return false;
1192 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001193 return false;
1194 return VectorList.NumElements == NumElements;
1195 }
1196
Sander de Smalenc33d6682018-06-04 06:40:55 +00001197 template <int Min, int Max>
1198 DiagnosticPredicate isVectorIndex() const {
1199 if (Kind != k_VectorIndex)
1200 return DiagnosticPredicateTy::NoMatch;
1201 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1202 return DiagnosticPredicateTy::Match;
1203 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001204 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001205
Tim Northover3b0846e2014-05-24 12:50:23 +00001206 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001207
Tim Northover3b0846e2014-05-24 12:50:23 +00001208 bool isTokenEqual(StringRef Str) const {
1209 return Kind == k_Token && getToken() == Str;
1210 }
1211 bool isSysCR() const { return Kind == k_SysCR; }
1212 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001213 bool isPSBHint() const { return Kind == k_PSBHint; }
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001214 bool isBTIHint() const { return Kind == k_BTIHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001215 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1216 bool isShifter() const {
1217 if (!isShiftExtend())
1218 return false;
1219
1220 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1221 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1222 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1223 ST == AArch64_AM::MSL);
1224 }
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001225
1226 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1227 if (Kind != k_FPImm)
1228 return DiagnosticPredicateTy::NoMatch;
1229
1230 if (getFPImmIsExact()) {
1231 // Lookup the immediate from table of supported immediates.
1232 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1233 assert(Desc && "Unknown enum value");
1234
1235 // Calculate its FP value.
1236 APFloat RealVal(APFloat::IEEEdouble());
1237 if (RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero) !=
1238 APFloat::opOK)
1239 llvm_unreachable("FP immediate is not exact");
1240
1241 if (getFPImm().bitwiseIsEqual(RealVal))
1242 return DiagnosticPredicateTy::Match;
1243 }
1244
1245 return DiagnosticPredicateTy::NearMatch;
1246 }
1247
1248 template <unsigned ImmA, unsigned ImmB>
1249 DiagnosticPredicate isExactFPImm() const {
1250 DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1251 if ((Res = isExactFPImm<ImmA>()))
1252 return DiagnosticPredicateTy::Match;
1253 if ((Res = isExactFPImm<ImmB>()))
1254 return DiagnosticPredicateTy::Match;
1255 return Res;
1256 }
1257
Tim Northover3b0846e2014-05-24 12:50:23 +00001258 bool isExtend() const {
1259 if (!isShiftExtend())
1260 return false;
1261
1262 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1263 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1264 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1265 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1266 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1267 ET == AArch64_AM::LSL) &&
1268 getShiftExtendAmount() <= 4;
1269 }
1270
1271 bool isExtend64() const {
1272 if (!isExtend())
1273 return false;
1274 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1275 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1276 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1277 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001278
Tim Northover3b0846e2014-05-24 12:50:23 +00001279 bool isExtendLSL64() const {
1280 if (!isExtend())
1281 return false;
1282 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1283 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1284 ET == AArch64_AM::LSL) &&
1285 getShiftExtendAmount() <= 4;
1286 }
1287
1288 template<int Width> bool isMemXExtend() const {
1289 if (!isExtend())
1290 return false;
1291 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1292 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1293 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1294 getShiftExtendAmount() == 0);
1295 }
1296
1297 template<int Width> bool isMemWExtend() const {
1298 if (!isExtend())
1299 return false;
1300 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1301 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1302 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1303 getShiftExtendAmount() == 0);
1304 }
1305
1306 template <unsigned width>
1307 bool isArithmeticShifter() const {
1308 if (!isShifter())
1309 return false;
1310
1311 // An arithmetic shifter is LSL, LSR, or ASR.
1312 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1313 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1314 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1315 }
1316
1317 template <unsigned width>
1318 bool isLogicalShifter() const {
1319 if (!isShifter())
1320 return false;
1321
1322 // A logical shifter is LSL, LSR, ASR or ROR.
1323 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1324 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1325 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1326 getShiftExtendAmount() < width;
1327 }
1328
1329 bool isMovImm32Shifter() const {
1330 if (!isShifter())
1331 return false;
1332
1333 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1334 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1335 if (ST != AArch64_AM::LSL)
1336 return false;
1337 uint64_t Val = getShiftExtendAmount();
1338 return (Val == 0 || Val == 16);
1339 }
1340
1341 bool isMovImm64Shifter() const {
1342 if (!isShifter())
1343 return false;
1344
1345 // A MOVi shifter is LSL of 0 or 16.
1346 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1347 if (ST != AArch64_AM::LSL)
1348 return false;
1349 uint64_t Val = getShiftExtendAmount();
1350 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1351 }
1352
1353 bool isLogicalVecShifter() const {
1354 if (!isShifter())
1355 return false;
1356
1357 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1358 unsigned Shift = getShiftExtendAmount();
1359 return getShiftExtendType() == AArch64_AM::LSL &&
1360 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1361 }
1362
1363 bool isLogicalVecHalfWordShifter() const {
1364 if (!isLogicalVecShifter())
1365 return false;
1366
1367 // A logical vector shifter is a left shift by 0 or 8.
1368 unsigned Shift = getShiftExtendAmount();
1369 return getShiftExtendType() == AArch64_AM::LSL &&
1370 (Shift == 0 || Shift == 8);
1371 }
1372
1373 bool isMoveVecShifter() const {
1374 if (!isShiftExtend())
1375 return false;
1376
1377 // A logical vector shifter is a left shift by 8 or 16.
1378 unsigned Shift = getShiftExtendAmount();
1379 return getShiftExtendType() == AArch64_AM::MSL &&
1380 (Shift == 8 || Shift == 16);
1381 }
1382
1383 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1384 // to LDUR/STUR when the offset is not legal for the former but is for
1385 // the latter. As such, in addition to checking for being a legal unscaled
1386 // address, also check that it is not a legal scaled address. This avoids
1387 // ambiguity in the matcher.
1388 template<int Width>
1389 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001390 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001391 }
1392
1393 bool isAdrpLabel() const {
1394 // Validation was handled during parsing, so we just sanity check that
1395 // something didn't go haywire.
1396 if (!isImm())
1397 return false;
1398
1399 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1400 int64_t Val = CE->getValue();
1401 int64_t Min = - (4096 * (1LL << (21 - 1)));
1402 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1403 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1404 }
1405
1406 return true;
1407 }
1408
1409 bool isAdrLabel() const {
1410 // Validation was handled during parsing, so we just sanity check that
1411 // something didn't go haywire.
1412 if (!isImm())
1413 return false;
1414
1415 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1416 int64_t Val = CE->getValue();
1417 int64_t Min = - (1LL << (21 - 1));
1418 int64_t Max = ((1LL << (21 - 1)) - 1);
1419 return Val >= Min && Val <= Max;
1420 }
1421
1422 return true;
1423 }
1424
1425 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1426 // Add as immediates when possible. Null MCExpr = 0.
1427 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001428 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001429 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001430 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001431 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001432 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001433 }
1434
1435 void addRegOperands(MCInst &Inst, unsigned N) const {
1436 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001437 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001438 }
1439
1440 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1441 assert(N == 1 && "Invalid number of operands!");
1442 assert(
1443 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1444
1445 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1446 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1447 RI->getEncodingValue(getReg()));
1448
Jim Grosbache9119e42015-05-13 18:37:00 +00001449 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001450 }
1451
Sander de Smalen0325e302018-07-02 07:34:52 +00001452 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1453 assert(N == 1 && "Invalid number of operands!");
1454 assert(
1455 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(getReg()));
1456
1457 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1458 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID).getRegister(
1459 RI->getEncodingValue(getReg()));
1460
1461 Inst.addOperand(MCOperand::createReg(Reg));
1462 }
1463
Sander de Smalenfd54a782018-06-04 07:07:35 +00001464 template <int Width>
1465 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1466 unsigned Base;
1467 switch (Width) {
1468 case 8: Base = AArch64::B0; break;
1469 case 16: Base = AArch64::H0; break;
1470 case 32: Base = AArch64::S0; break;
1471 case 64: Base = AArch64::D0; break;
1472 case 128: Base = AArch64::Q0; break;
1473 default:
1474 llvm_unreachable("Unsupported width");
1475 }
1476 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1477 }
1478
Tim Northover3b0846e2014-05-24 12:50:23 +00001479 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1480 assert(N == 1 && "Invalid number of operands!");
1481 assert(
1482 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001483 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001484 }
1485
1486 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1487 assert(N == 1 && "Invalid number of operands!");
1488 assert(
1489 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001490 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001491 }
1492
1493 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1494 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001495 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001496 }
1497
Sander de Smalen525e3222018-04-12 13:19:32 +00001498 enum VecListIndexType {
1499 VecListIdx_DReg = 0,
1500 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001501 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001502 };
1503
1504 template <VecListIndexType RegTy, unsigned NumRegs>
1505 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001506 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001507 static const unsigned FirstRegs[][5] = {
1508 /* DReg */ { AArch64::Q0,
1509 AArch64::D0, AArch64::D0_D1,
1510 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1511 /* QReg */ { AArch64::Q0,
1512 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001513 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1514 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001515 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001516 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001517 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001518
Sander de Smalen7a210db2018-04-16 10:46:18 +00001519 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1520 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001521
Sander de Smalen525e3222018-04-12 13:19:32 +00001522 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1523 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1524 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001525 }
1526
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001527 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001528 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001529 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001530 }
1531
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001532 template <unsigned ImmIs0, unsigned ImmIs1>
1533 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1534 assert(N == 1 && "Invalid number of operands!");
1535 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1536 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1537 }
1538
Tim Northover3b0846e2014-05-24 12:50:23 +00001539 void addImmOperands(MCInst &Inst, unsigned N) const {
1540 assert(N == 1 && "Invalid number of operands!");
1541 // If this is a pageoff symrefexpr with an addend, adjust the addend
1542 // to be only the page-offset portion. Otherwise, just add the expr
1543 // as-is.
1544 addExpr(Inst, getImm());
1545 }
1546
Sander de Smalen62770792018-05-25 09:47:52 +00001547 template <int Shift>
1548 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001549 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001550 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1551 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1552 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1553 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001554 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001555 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001556 } else {
1557 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001558 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001559 }
1560 }
1561
Sander de Smalen62770792018-05-25 09:47:52 +00001562 template <int Shift>
1563 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001564 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001565 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1566 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1567 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1568 } else
1569 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001570 }
1571
Tim Northover3b0846e2014-05-24 12:50:23 +00001572 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1573 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001574 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001575 }
1576
1577 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1578 assert(N == 1 && "Invalid number of operands!");
1579 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1580 if (!MCE)
1581 addExpr(Inst, getImm());
1582 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001583 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001584 }
1585
1586 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1587 addImmOperands(Inst, N);
1588 }
1589
1590 template<int Scale>
1591 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1592 assert(N == 1 && "Invalid number of operands!");
1593 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1594
1595 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001596 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001597 return;
1598 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001599 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001600 }
1601
Sjoerd Meijera3dad802018-07-06 12:32:33 +00001602 void addUImm6Operands(MCInst &Inst, unsigned N) const {
1603 assert(N == 1 && "Invalid number of operands!");
1604 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1605 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1606 }
1607
Sander de Smalen5c625982018-04-13 12:56:14 +00001608 template <int Scale>
1609 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1610 assert(N == 1 && "Invalid number of operands!");
1611 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1612 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1613 }
1614
Sander de Smalena1c259c2018-01-29 13:05:38 +00001615 template <typename T>
1616 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001617 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001618 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001619 typename std::make_unsigned<T>::type Val = MCE->getValue();
1620 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001621 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001622 }
1623
Sander de Smalena1c259c2018-01-29 13:05:38 +00001624 template <typename T>
1625 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001626 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001627 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001628 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1629 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001630 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001631 }
1632
Tim Northover3b0846e2014-05-24 12:50:23 +00001633 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1634 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001635 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001636 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001637 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001638 }
1639
1640 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1641 // Branch operands don't encode the low bits, so shift them off
1642 // here. If it's a label, however, just put it on directly as there's
1643 // not enough information now to do anything.
1644 assert(N == 1 && "Invalid number of operands!");
1645 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1646 if (!MCE) {
1647 addExpr(Inst, getImm());
1648 return;
1649 }
1650 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001651 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001652 }
1653
1654 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1655 // Branch operands don't encode the low bits, so shift them off
1656 // here. If it's a label, however, just put it on directly as there's
1657 // not enough information now to do anything.
1658 assert(N == 1 && "Invalid number of operands!");
1659 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1660 if (!MCE) {
1661 addExpr(Inst, getImm());
1662 return;
1663 }
1664 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001665 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001666 }
1667
1668 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1669 // Branch operands don't encode the low bits, so shift them off
1670 // here. If it's a label, however, just put it on directly as there's
1671 // not enough information now to do anything.
1672 assert(N == 1 && "Invalid number of operands!");
1673 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1674 if (!MCE) {
1675 addExpr(Inst, getImm());
1676 return;
1677 }
1678 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001679 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001680 }
1681
1682 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1683 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001684 Inst.addOperand(MCOperand::createImm(
1685 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
Tim Northover3b0846e2014-05-24 12:50:23 +00001686 }
1687
1688 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1689 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001690 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001691 }
1692
1693 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1694 assert(N == 1 && "Invalid number of operands!");
1695
Jim Grosbache9119e42015-05-13 18:37:00 +00001696 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001697 }
1698
1699 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1700 assert(N == 1 && "Invalid number of operands!");
1701
Jim Grosbache9119e42015-05-13 18:37:00 +00001702 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001703 }
1704
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001705 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1706 assert(N == 1 && "Invalid number of operands!");
1707
1708 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1709 }
1710
1711 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001712 assert(N == 1 && "Invalid number of operands!");
1713
Jim Grosbache9119e42015-05-13 18:37:00 +00001714 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001715 }
1716
1717 void addSysCROperands(MCInst &Inst, unsigned N) const {
1718 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001719 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001720 }
1721
1722 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1723 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001724 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001725 }
1726
Oliver Stannarda34e4702015-12-01 10:48:51 +00001727 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1728 assert(N == 1 && "Invalid number of operands!");
1729 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1730 }
1731
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001732 void addBTIHintOperands(MCInst &Inst, unsigned N) const {
1733 assert(N == 1 && "Invalid number of operands!");
1734 Inst.addOperand(MCOperand::createImm(getBTIHint()));
1735 }
1736
Tim Northover3b0846e2014-05-24 12:50:23 +00001737 void addShifterOperands(MCInst &Inst, unsigned N) const {
1738 assert(N == 1 && "Invalid number of operands!");
1739 unsigned Imm =
1740 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001741 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001742 }
1743
1744 void addExtendOperands(MCInst &Inst, unsigned N) const {
1745 assert(N == 1 && "Invalid number of operands!");
1746 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1747 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1748 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001749 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001750 }
1751
1752 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1753 assert(N == 1 && "Invalid number of operands!");
1754 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1755 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1756 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001757 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001758 }
1759
1760 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1761 assert(N == 2 && "Invalid number of operands!");
1762 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1763 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001764 Inst.addOperand(MCOperand::createImm(IsSigned));
1765 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001766 }
1767
1768 // For 8-bit load/store instructions with a register offset, both the
1769 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1770 // they're disambiguated by whether the shift was explicit or implicit rather
1771 // than its size.
1772 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1773 assert(N == 2 && "Invalid number of operands!");
1774 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1775 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001776 Inst.addOperand(MCOperand::createImm(IsSigned));
1777 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001778 }
1779
1780 template<int Shift>
1781 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1782 assert(N == 1 && "Invalid number of operands!");
1783
1784 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1785 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001786 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001787 }
1788
1789 template<int Shift>
1790 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1791 assert(N == 1 && "Invalid number of operands!");
1792
1793 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1794 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001795 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001796 }
1797
Sam Parker5f934642017-08-31 09:27:04 +00001798 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1799 assert(N == 1 && "Invalid number of operands!");
1800 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1801 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1802 }
1803
1804 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1805 assert(N == 1 && "Invalid number of operands!");
1806 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1807 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1808 }
1809
Tim Northover3b0846e2014-05-24 12:50:23 +00001810 void print(raw_ostream &OS) const override;
1811
David Blaikie960ea3f2014-06-08 16:18:35 +00001812 static std::unique_ptr<AArch64Operand>
1813 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1814 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001815 Op->Tok.Data = Str.data();
1816 Op->Tok.Length = Str.size();
1817 Op->Tok.IsSuffix = IsSuffix;
1818 Op->StartLoc = S;
1819 Op->EndLoc = S;
1820 return Op;
1821 }
1822
David Blaikie960ea3f2014-06-08 16:18:35 +00001823 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001824 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
Sander de Smalen0325e302018-07-02 07:34:52 +00001825 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
Sander de Smalen149916d2018-04-20 07:24:20 +00001826 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1827 unsigned ShiftAmount = 0,
1828 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001829 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001830 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001831 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001832 Op->Reg.ElementWidth = 0;
Sander de Smalen0325e302018-07-02 07:34:52 +00001833 Op->Reg.EqualityTy = EqTy;
Sander de Smalen149916d2018-04-20 07:24:20 +00001834 Op->Reg.ShiftExtend.Type = ExtTy;
1835 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1836 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001837 Op->StartLoc = S;
1838 Op->EndLoc = E;
1839 return Op;
1840 }
1841
David Blaikie960ea3f2014-06-08 16:18:35 +00001842 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001843 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001844 SMLoc S, SMLoc E, MCContext &Ctx,
1845 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1846 unsigned ShiftAmount = 0,
1847 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001848 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1849 Kind == RegKind::SVEPredicateVector) &&
1850 "Invalid vector kind");
Sander de Smalen0325e302018-07-02 07:34:52 +00001851 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
Sander de Smalen149916d2018-04-20 07:24:20 +00001852 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001853 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001854 return Op;
1855 }
1856
1857 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001858 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001859 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1860 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001861 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001862 Op->VectorList.RegNum = RegNum;
1863 Op->VectorList.Count = Count;
1864 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001865 Op->VectorList.ElementWidth = ElementWidth;
1866 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001867 Op->StartLoc = S;
1868 Op->EndLoc = E;
1869 return Op;
1870 }
1871
David Blaikie960ea3f2014-06-08 16:18:35 +00001872 static std::unique_ptr<AArch64Operand>
1873 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1874 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001875 Op->VectorIndex.Val = Idx;
1876 Op->StartLoc = S;
1877 Op->EndLoc = E;
1878 return Op;
1879 }
1880
David Blaikie960ea3f2014-06-08 16:18:35 +00001881 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1882 SMLoc E, MCContext &Ctx) {
1883 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001884 Op->Imm.Val = Val;
1885 Op->StartLoc = S;
1886 Op->EndLoc = E;
1887 return Op;
1888 }
1889
David Blaikie960ea3f2014-06-08 16:18:35 +00001890 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1891 unsigned ShiftAmount,
1892 SMLoc S, SMLoc E,
1893 MCContext &Ctx) {
1894 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001895 Op->ShiftedImm .Val = Val;
1896 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1897 Op->StartLoc = S;
1898 Op->EndLoc = E;
1899 return Op;
1900 }
1901
David Blaikie960ea3f2014-06-08 16:18:35 +00001902 static std::unique_ptr<AArch64Operand>
1903 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1904 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001905 Op->CondCode.Code = Code;
1906 Op->StartLoc = S;
1907 Op->EndLoc = E;
1908 return Op;
1909 }
1910
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001911 static std::unique_ptr<AArch64Operand>
1912 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001913 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001914 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
1915 Op->FPImm.IsExact = IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +00001916 Op->StartLoc = S;
1917 Op->EndLoc = S;
1918 return Op;
1919 }
1920
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001921 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1922 StringRef Str,
1923 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001924 MCContext &Ctx) {
1925 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001926 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001927 Op->Barrier.Data = Str.data();
1928 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001929 Op->StartLoc = S;
1930 Op->EndLoc = S;
1931 return Op;
1932 }
1933
Tim Northover7cd58932015-01-22 17:23:04 +00001934 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1935 uint32_t MRSReg,
1936 uint32_t MSRReg,
1937 uint32_t PStateField,
1938 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001939 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001940 Op->SysReg.Data = Str.data();
1941 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001942 Op->SysReg.MRSReg = MRSReg;
1943 Op->SysReg.MSRReg = MSRReg;
1944 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001945 Op->StartLoc = S;
1946 Op->EndLoc = S;
1947 return Op;
1948 }
1949
David Blaikie960ea3f2014-06-08 16:18:35 +00001950 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1951 SMLoc E, MCContext &Ctx) {
1952 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001953 Op->SysCRImm.Val = Val;
1954 Op->StartLoc = S;
1955 Op->EndLoc = E;
1956 return Op;
1957 }
1958
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001959 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1960 StringRef Str,
1961 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001962 MCContext &Ctx) {
1963 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001964 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001965 Op->Barrier.Data = Str.data();
1966 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001967 Op->StartLoc = S;
1968 Op->EndLoc = S;
1969 return Op;
1970 }
1971
Oliver Stannarda34e4702015-12-01 10:48:51 +00001972 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1973 StringRef Str,
1974 SMLoc S,
1975 MCContext &Ctx) {
1976 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1977 Op->PSBHint.Val = Val;
1978 Op->PSBHint.Data = Str.data();
1979 Op->PSBHint.Length = Str.size();
1980 Op->StartLoc = S;
1981 Op->EndLoc = S;
1982 return Op;
1983 }
1984
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001985 static std::unique_ptr<AArch64Operand> CreateBTIHint(unsigned Val,
1986 StringRef Str,
1987 SMLoc S,
1988 MCContext &Ctx) {
1989 auto Op = make_unique<AArch64Operand>(k_BTIHint, Ctx);
1990 Op->BTIHint.Val = Val << 1 | 32;
1991 Op->BTIHint.Data = Str.data();
1992 Op->BTIHint.Length = Str.size();
1993 Op->StartLoc = S;
1994 Op->EndLoc = S;
1995 return Op;
1996 }
1997
David Blaikie960ea3f2014-06-08 16:18:35 +00001998 static std::unique_ptr<AArch64Operand>
1999 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
2000 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
2001 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00002002 Op->ShiftExtend.Type = ShOp;
2003 Op->ShiftExtend.Amount = Val;
2004 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
2005 Op->StartLoc = S;
2006 Op->EndLoc = E;
2007 return Op;
2008 }
2009};
2010
2011} // end anonymous namespace.
2012
2013void AArch64Operand::print(raw_ostream &OS) const {
2014 switch (Kind) {
2015 case k_FPImm:
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002016 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
2017 if (!getFPImmIsExact())
2018 OS << " (inexact)";
2019 OS << ">";
Tim Northover3b0846e2014-05-24 12:50:23 +00002020 break;
2021 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00002022 StringRef Name = getBarrierName();
2023 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00002024 OS << "<barrier " << Name << ">";
2025 else
2026 OS << "<barrier invalid #" << getBarrier() << ">";
2027 break;
2028 }
2029 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00002030 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00002031 break;
2032 case k_ShiftedImm: {
2033 unsigned Shift = getShiftedImmShift();
2034 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00002035 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00002036 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
2037 break;
2038 }
2039 case k_CondCode:
2040 OS << "<condcode " << getCondCode() << ">";
2041 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00002042 case k_VectorList: {
2043 OS << "<vectorlist ";
2044 unsigned Reg = getVectorListStart();
2045 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
2046 OS << Reg + i << " ";
2047 OS << ">";
2048 break;
2049 }
2050 case k_VectorIndex:
2051 OS << "<vectorindex " << getVectorIndex() << ">";
2052 break;
2053 case k_SysReg:
2054 OS << "<sysreg: " << getSysReg() << '>';
2055 break;
2056 case k_Token:
2057 OS << "'" << getToken() << "'";
2058 break;
2059 case k_SysCR:
2060 OS << "c" << getSysCR();
2061 break;
2062 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00002063 StringRef Name = getPrefetchName();
2064 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00002065 OS << "<prfop " << Name << ">";
2066 else
2067 OS << "<prfop invalid #" << getPrefetch() << ">";
2068 break;
2069 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00002070 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00002071 OS << getPSBHintName();
2072 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00002073 case k_Register:
2074 OS << "<register " << getReg() << ">";
2075 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
2076 break;
2077 LLVM_FALLTHROUGH;
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00002078 case k_BTIHint:
2079 OS << getBTIHintName();
2080 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00002081 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00002082 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
2083 << getShiftExtendAmount();
2084 if (!hasShiftExtendAmount())
2085 OS << "<imp>";
2086 OS << '>';
2087 break;
2088 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002089}
2090
2091/// @name Auto-generated Match Functions
2092/// {
2093
2094static unsigned MatchRegisterName(StringRef Name);
2095
2096/// }
2097
Florian Hahnc4422242017-11-07 13:07:50 +00002098static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00002099 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00002100 .Case("v0", AArch64::Q0)
2101 .Case("v1", AArch64::Q1)
2102 .Case("v2", AArch64::Q2)
2103 .Case("v3", AArch64::Q3)
2104 .Case("v4", AArch64::Q4)
2105 .Case("v5", AArch64::Q5)
2106 .Case("v6", AArch64::Q6)
2107 .Case("v7", AArch64::Q7)
2108 .Case("v8", AArch64::Q8)
2109 .Case("v9", AArch64::Q9)
2110 .Case("v10", AArch64::Q10)
2111 .Case("v11", AArch64::Q11)
2112 .Case("v12", AArch64::Q12)
2113 .Case("v13", AArch64::Q13)
2114 .Case("v14", AArch64::Q14)
2115 .Case("v15", AArch64::Q15)
2116 .Case("v16", AArch64::Q16)
2117 .Case("v17", AArch64::Q17)
2118 .Case("v18", AArch64::Q18)
2119 .Case("v19", AArch64::Q19)
2120 .Case("v20", AArch64::Q20)
2121 .Case("v21", AArch64::Q21)
2122 .Case("v22", AArch64::Q22)
2123 .Case("v23", AArch64::Q23)
2124 .Case("v24", AArch64::Q24)
2125 .Case("v25", AArch64::Q25)
2126 .Case("v26", AArch64::Q26)
2127 .Case("v27", AArch64::Q27)
2128 .Case("v28", AArch64::Q28)
2129 .Case("v29", AArch64::Q29)
2130 .Case("v30", AArch64::Q30)
2131 .Case("v31", AArch64::Q31)
2132 .Default(0);
2133}
2134
Sander de Smalen73937b72018-04-11 07:36:10 +00002135/// Returns an optional pair of (#elements, element-width) if Suffix
2136/// is a valid vector kind. Where the number of elements in a vector
2137/// or the vector width is implicit or explicitly unknown (but still a
2138/// valid suffix kind), 0 is used.
2139static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2140 RegKind VectorKind) {
2141 std::pair<int, int> Res = {-1, -1};
2142
2143 switch (VectorKind) {
2144 case RegKind::NeonVector:
2145 Res =
2146 StringSwitch<std::pair<int, int>>(Suffix.lower())
2147 .Case("", {0, 0})
2148 .Case(".1d", {1, 64})
2149 .Case(".1q", {1, 128})
2150 // '.2h' needed for fp16 scalar pairwise reductions
2151 .Case(".2h", {2, 16})
2152 .Case(".2s", {2, 32})
2153 .Case(".2d", {2, 64})
2154 // '.4b' is another special case for the ARMv8.2a dot product
2155 // operand
2156 .Case(".4b", {4, 8})
2157 .Case(".4h", {4, 16})
2158 .Case(".4s", {4, 32})
2159 .Case(".8b", {8, 8})
2160 .Case(".8h", {8, 16})
2161 .Case(".16b", {16, 8})
2162 // Accept the width neutral ones, too, for verbose syntax. If those
2163 // aren't used in the right places, the token operand won't match so
2164 // all will work out.
2165 .Case(".b", {0, 8})
2166 .Case(".h", {0, 16})
2167 .Case(".s", {0, 32})
2168 .Case(".d", {0, 64})
2169 .Default({-1, -1});
2170 break;
2171 case RegKind::SVEPredicateVector:
2172 case RegKind::SVEDataVector:
2173 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2174 .Case("", {0, 0})
2175 .Case(".b", {0, 8})
2176 .Case(".h", {0, 16})
2177 .Case(".s", {0, 32})
2178 .Case(".d", {0, 64})
2179 .Case(".q", {0, 128})
2180 .Default({-1, -1});
2181 break;
2182 default:
2183 llvm_unreachable("Unsupported RegKind");
2184 }
2185
2186 if (Res == std::make_pair(-1, -1))
2187 return Optional<std::pair<int, int>>();
2188
2189 return Optional<std::pair<int, int>>(Res);
2190}
2191
2192static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2193 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002194}
2195
Florian Hahn91f11e52017-11-07 16:45:48 +00002196static unsigned matchSVEDataVectorRegName(StringRef Name) {
2197 return StringSwitch<unsigned>(Name.lower())
2198 .Case("z0", AArch64::Z0)
2199 .Case("z1", AArch64::Z1)
2200 .Case("z2", AArch64::Z2)
2201 .Case("z3", AArch64::Z3)
2202 .Case("z4", AArch64::Z4)
2203 .Case("z5", AArch64::Z5)
2204 .Case("z6", AArch64::Z6)
2205 .Case("z7", AArch64::Z7)
2206 .Case("z8", AArch64::Z8)
2207 .Case("z9", AArch64::Z9)
2208 .Case("z10", AArch64::Z10)
2209 .Case("z11", AArch64::Z11)
2210 .Case("z12", AArch64::Z12)
2211 .Case("z13", AArch64::Z13)
2212 .Case("z14", AArch64::Z14)
2213 .Case("z15", AArch64::Z15)
2214 .Case("z16", AArch64::Z16)
2215 .Case("z17", AArch64::Z17)
2216 .Case("z18", AArch64::Z18)
2217 .Case("z19", AArch64::Z19)
2218 .Case("z20", AArch64::Z20)
2219 .Case("z21", AArch64::Z21)
2220 .Case("z22", AArch64::Z22)
2221 .Case("z23", AArch64::Z23)
2222 .Case("z24", AArch64::Z24)
2223 .Case("z25", AArch64::Z25)
2224 .Case("z26", AArch64::Z26)
2225 .Case("z27", AArch64::Z27)
2226 .Case("z28", AArch64::Z28)
2227 .Case("z29", AArch64::Z29)
2228 .Case("z30", AArch64::Z30)
2229 .Case("z31", AArch64::Z31)
2230 .Default(0);
2231}
2232
Sander de Smalencd6be962017-12-20 11:02:42 +00002233static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2234 return StringSwitch<unsigned>(Name.lower())
2235 .Case("p0", AArch64::P0)
2236 .Case("p1", AArch64::P1)
2237 .Case("p2", AArch64::P2)
2238 .Case("p3", AArch64::P3)
2239 .Case("p4", AArch64::P4)
2240 .Case("p5", AArch64::P5)
2241 .Case("p6", AArch64::P6)
2242 .Case("p7", AArch64::P7)
2243 .Case("p8", AArch64::P8)
2244 .Case("p9", AArch64::P9)
2245 .Case("p10", AArch64::P10)
2246 .Case("p11", AArch64::P11)
2247 .Case("p12", AArch64::P12)
2248 .Case("p13", AArch64::P13)
2249 .Case("p14", AArch64::P14)
2250 .Case("p15", AArch64::P15)
2251 .Default(0);
2252}
2253
Tim Northover3b0846e2014-05-24 12:50:23 +00002254bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2255 SMLoc &EndLoc) {
2256 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002257 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002258 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002259 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002260}
2261
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002262// Matches a register name or register alias previously defined by '.req'
2263unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002264 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002265 unsigned RegNum = 0;
2266 if ((RegNum = matchSVEDataVectorRegName(Name)))
2267 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2268
Sander de Smalencd6be962017-12-20 11:02:42 +00002269 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2270 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2271
Sander de Smalenc067c302017-12-20 09:45:45 +00002272 if ((RegNum = MatchNeonVectorRegName(Name)))
2273 return Kind == RegKind::NeonVector ? RegNum : 0;
2274
2275 // The parsed register must be of RegKind Scalar
2276 if ((RegNum = MatchRegisterName(Name)))
2277 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002278
Florian Hahnc4422242017-11-07 13:07:50 +00002279 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002280 // Handle a few common aliases of registers.
2281 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2282 .Case("fp", AArch64::FP)
2283 .Case("lr", AArch64::LR)
2284 .Case("x31", AArch64::XZR)
2285 .Case("w31", AArch64::WZR)
2286 .Default(0))
2287 return Kind == RegKind::Scalar ? RegNum : 0;
2288
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002289 // Check for aliases registered via .req. Canonicalize to lower case.
2290 // That's more consistent since register names are case insensitive, and
2291 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2292 auto Entry = RegisterReqs.find(Name.lower());
2293 if (Entry == RegisterReqs.end())
2294 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002295
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002296 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002297 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002298 RegNum = Entry->getValue().second;
2299 }
2300 return RegNum;
2301}
2302
Sander de Smalen50d87022018-04-19 07:35:08 +00002303/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002304/// Identifier when called, and if it is a register name the token is eaten and
2305/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002306OperandMatchResultTy
2307AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002308 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002309 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002310 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002311 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002312
2313 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002314 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2315 if (Reg == 0)
2316 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002317
Sander de Smalen50d87022018-04-19 07:35:08 +00002318 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002319 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002320 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002321}
2322
Tim Northover3b0846e2014-05-24 12:50:23 +00002323/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002324OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002325AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002326 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002327 SMLoc S = getLoc();
2328
2329 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2330 Error(S, "Expected cN operand where 0 <= N <= 15");
2331 return MatchOperand_ParseFail;
2332 }
2333
2334 StringRef Tok = Parser.getTok().getIdentifier();
2335 if (Tok[0] != 'c' && Tok[0] != 'C') {
2336 Error(S, "Expected cN operand where 0 <= N <= 15");
2337 return MatchOperand_ParseFail;
2338 }
2339
2340 uint32_t CRNum;
2341 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2342 if (BadNum || CRNum > 15) {
2343 Error(S, "Expected cN operand where 0 <= N <= 15");
2344 return MatchOperand_ParseFail;
2345 }
2346
2347 Parser.Lex(); // Eat identifier token.
2348 Operands.push_back(
2349 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2350 return MatchOperand_Success;
2351}
2352
2353/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002354template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002355OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002356AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002357 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002358 SMLoc S = getLoc();
2359 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002360
2361 auto LookupByName = [](StringRef N) {
2362 if (IsSVEPrefetch) {
2363 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2364 return Optional<unsigned>(Res->Encoding);
2365 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2366 return Optional<unsigned>(Res->Encoding);
2367 return Optional<unsigned>();
2368 };
2369
2370 auto LookupByEncoding = [](unsigned E) {
2371 if (IsSVEPrefetch) {
2372 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2373 return Optional<StringRef>(Res->Name);
2374 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2375 return Optional<StringRef>(Res->Name);
2376 return Optional<StringRef>();
2377 };
2378 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2379
Tim Northover3b0846e2014-05-24 12:50:23 +00002380 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002381 // Eat optional hash.
2382 if (parseOptionalToken(AsmToken::Hash) ||
2383 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002384 const MCExpr *ImmVal;
2385 if (getParser().parseExpression(ImmVal))
2386 return MatchOperand_ParseFail;
2387
2388 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2389 if (!MCE) {
2390 TokError("immediate value expected for prefetch operand");
2391 return MatchOperand_ParseFail;
2392 }
2393 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002394 if (prfop > MaxVal) {
2395 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2396 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002397 return MatchOperand_ParseFail;
2398 }
2399
Sander de Smalen93380372018-05-14 11:54:41 +00002400 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002401 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002402 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002403 return MatchOperand_Success;
2404 }
2405
2406 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002407 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002408 return MatchOperand_ParseFail;
2409 }
2410
Sander de Smalen93380372018-05-14 11:54:41 +00002411 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002412 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002413 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002414 return MatchOperand_ParseFail;
2415 }
2416
2417 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002418 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002419 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002420 return MatchOperand_Success;
2421}
2422
Oliver Stannarda34e4702015-12-01 10:48:51 +00002423/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002424OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002425AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2426 MCAsmParser &Parser = getParser();
2427 SMLoc S = getLoc();
2428 const AsmToken &Tok = Parser.getTok();
2429 if (Tok.isNot(AsmToken::Identifier)) {
2430 TokError("invalid operand for instruction");
2431 return MatchOperand_ParseFail;
2432 }
2433
Tim Northovere6ae6762016-07-05 21:23:04 +00002434 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2435 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002436 TokError("invalid operand for instruction");
2437 return MatchOperand_ParseFail;
2438 }
2439
2440 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002441 Operands.push_back(AArch64Operand::CreatePSBHint(
2442 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002443 return MatchOperand_Success;
2444}
2445
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00002446/// tryParseBTIHint - Try to parse a BTI operand, mapped to Hint command
2447OperandMatchResultTy
2448AArch64AsmParser::tryParseBTIHint(OperandVector &Operands) {
2449 MCAsmParser &Parser = getParser();
2450 SMLoc S = getLoc();
2451 const AsmToken &Tok = Parser.getTok();
2452 if (Tok.isNot(AsmToken::Identifier)) {
2453 TokError("invalid operand for instruction");
2454 return MatchOperand_ParseFail;
2455 }
2456
2457 auto BTI = AArch64BTIHint::lookupBTIByName(Tok.getString());
2458 if (!BTI) {
2459 TokError("invalid operand for instruction");
2460 return MatchOperand_ParseFail;
2461 }
2462
2463 Parser.Lex(); // Eat identifier token.
2464 Operands.push_back(AArch64Operand::CreateBTIHint(
2465 BTI->Encoding, Tok.getString(), S, getContext()));
2466 return MatchOperand_Success;
2467}
2468
Tim Northover3b0846e2014-05-24 12:50:23 +00002469/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2470/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002471OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002472AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002473 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002474 SMLoc S = getLoc();
2475 const MCExpr *Expr;
2476
2477 if (Parser.getTok().is(AsmToken::Hash)) {
2478 Parser.Lex(); // Eat hash token.
2479 }
2480
2481 if (parseSymbolicImmVal(Expr))
2482 return MatchOperand_ParseFail;
2483
2484 AArch64MCExpr::VariantKind ELFRefKind;
2485 MCSymbolRefExpr::VariantKind DarwinRefKind;
2486 int64_t Addend;
2487 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2488 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2489 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2490 // No modifier was specified at all; this is the syntax for an ELF basic
2491 // ADRP relocation (unfortunately).
2492 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002493 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002494 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2495 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2496 Addend != 0) {
2497 Error(S, "gotpage label reference not allowed an addend");
2498 return MatchOperand_ParseFail;
2499 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2500 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2501 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2502 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2503 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2504 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2505 // The operand must be an @page or @gotpage qualified symbolref.
2506 Error(S, "page or gotpage label reference expected");
2507 return MatchOperand_ParseFail;
2508 }
2509 }
2510
2511 // We have either a label reference possibly with addend or an immediate. The
2512 // addend is a raw value here. The linker will adjust it to only reference the
2513 // page.
2514 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2515 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2516
2517 return MatchOperand_Success;
2518}
2519
2520/// tryParseAdrLabel - Parse and validate a source label for the ADR
2521/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002522OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002523AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2524 SMLoc S = getLoc();
2525 const MCExpr *Expr;
2526
David Green9dd1d452018-08-22 11:31:39 +00002527 // Leave anything with a bracket to the default for SVE
2528 if (getParser().getTok().is(AsmToken::LBrac))
2529 return MatchOperand_NoMatch;
2530
2531 if (getParser().getTok().is(AsmToken::Hash))
2532 getParser().Lex(); // Eat hash token.
2533
2534 if (parseSymbolicImmVal(Expr))
2535 return MatchOperand_ParseFail;
2536
2537 AArch64MCExpr::VariantKind ELFRefKind;
2538 MCSymbolRefExpr::VariantKind DarwinRefKind;
2539 int64_t Addend;
2540 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2541 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2542 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2543 // No modifier was specified at all; this is the syntax for an ELF basic
2544 // ADR relocation (unfortunately).
2545 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS, getContext());
2546 } else {
2547 Error(S, "unexpected adr label");
Sander de Smalenc69944c2018-07-09 09:58:24 +00002548 return MatchOperand_ParseFail;
David Green9dd1d452018-08-22 11:31:39 +00002549 }
Sander de Smalenc69944c2018-07-09 09:58:24 +00002550 }
David Green9dd1d452018-08-22 11:31:39 +00002551
2552 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2553 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2554 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002555}
2556
2557/// tryParseFPImm - A floating point immediate expression operand.
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002558template<bool AddFPZeroAsLiteral>
Alex Bradbury58eba092016-11-01 16:32:05 +00002559OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002560AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002561 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002562 SMLoc S = getLoc();
2563
Nirav Davee833c6c2016-11-08 18:31:04 +00002564 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002565
2566 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002567 bool isNegative = parseOptionalToken(AsmToken::Minus);
2568
Tim Northover3b0846e2014-05-24 12:50:23 +00002569 const AsmToken &Tok = Parser.getTok();
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002570 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2571 if (!Hash)
2572 return MatchOperand_NoMatch;
2573 TokError("invalid floating point immediate");
2574 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002575 }
2576
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002577 // Parse hexadecimal representation.
2578 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2579 if (Tok.getIntVal() > 255 || isNegative) {
2580 TokError("encoded floating point value out of range");
2581 return MatchOperand_ParseFail;
2582 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002583
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002584 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2585 Operands.push_back(
2586 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2587 } else {
2588 // Parse FP representation.
2589 APFloat RealVal(APFloat::IEEEdouble());
2590 auto Status =
2591 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2592 if (isNegative)
2593 RealVal.changeSign();
2594
2595 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2596 Operands.push_back(
2597 AArch64Operand::CreateToken("#0", false, S, getContext()));
2598 Operands.push_back(
2599 AArch64Operand::CreateToken(".0", false, S, getContext()));
2600 } else
2601 Operands.push_back(AArch64Operand::CreateFPImm(
2602 RealVal, Status == APFloat::opOK, S, getContext()));
2603 }
2604
2605 Parser.Lex(); // Eat the token.
2606
2607 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002608}
2609
Sander de Smalen62770792018-05-25 09:47:52 +00002610/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2611/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002612OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002613AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002614 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002615 SMLoc S = getLoc();
2616
2617 if (Parser.getTok().is(AsmToken::Hash))
2618 Parser.Lex(); // Eat '#'
2619 else if (Parser.getTok().isNot(AsmToken::Integer))
2620 // Operand should start from # or should be integer, emit error otherwise.
2621 return MatchOperand_NoMatch;
2622
2623 const MCExpr *Imm;
2624 if (parseSymbolicImmVal(Imm))
2625 return MatchOperand_ParseFail;
2626 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002627 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002628 Operands.push_back(
2629 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002630 return MatchOperand_Success;
2631 }
2632
2633 // Eat ','
2634 Parser.Lex();
2635
2636 // The optional operand must be "lsl #N" where N is non-negative.
2637 if (!Parser.getTok().is(AsmToken::Identifier) ||
2638 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2639 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2640 return MatchOperand_ParseFail;
2641 }
2642
2643 // Eat 'lsl'
2644 Parser.Lex();
2645
Nirav Davee833c6c2016-11-08 18:31:04 +00002646 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002647
2648 if (Parser.getTok().isNot(AsmToken::Integer)) {
2649 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2650 return MatchOperand_ParseFail;
2651 }
2652
2653 int64_t ShiftAmount = Parser.getTok().getIntVal();
2654
2655 if (ShiftAmount < 0) {
2656 Error(Parser.getTok().getLoc(), "positive shift amount required");
2657 return MatchOperand_ParseFail;
2658 }
2659 Parser.Lex(); // Eat the number
2660
Sander de Smalen62770792018-05-25 09:47:52 +00002661 // Just in case the optional lsl #0 is used for immediates other than zero.
2662 if (ShiftAmount == 0 && Imm != 0) {
2663 SMLoc E = Parser.getTok().getLoc();
2664 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2665 return MatchOperand_Success;
2666 }
2667
Tim Northover3b0846e2014-05-24 12:50:23 +00002668 SMLoc E = Parser.getTok().getLoc();
2669 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2670 S, E, getContext()));
2671 return MatchOperand_Success;
2672}
2673
2674/// parseCondCodeString - Parse a Condition Code string.
2675AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2676 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2677 .Case("eq", AArch64CC::EQ)
2678 .Case("ne", AArch64CC::NE)
2679 .Case("cs", AArch64CC::HS)
2680 .Case("hs", AArch64CC::HS)
2681 .Case("cc", AArch64CC::LO)
2682 .Case("lo", AArch64CC::LO)
2683 .Case("mi", AArch64CC::MI)
2684 .Case("pl", AArch64CC::PL)
2685 .Case("vs", AArch64CC::VS)
2686 .Case("vc", AArch64CC::VC)
2687 .Case("hi", AArch64CC::HI)
2688 .Case("ls", AArch64CC::LS)
2689 .Case("ge", AArch64CC::GE)
2690 .Case("lt", AArch64CC::LT)
2691 .Case("gt", AArch64CC::GT)
2692 .Case("le", AArch64CC::LE)
2693 .Case("al", AArch64CC::AL)
2694 .Case("nv", AArch64CC::NV)
2695 .Default(AArch64CC::Invalid);
Sander de Smalene31e6d42018-07-04 08:50:49 +00002696
2697 if (CC == AArch64CC::Invalid &&
2698 getSTI().getFeatureBits()[AArch64::FeatureSVE])
2699 CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2700 .Case("none", AArch64CC::EQ)
2701 .Case("any", AArch64CC::NE)
2702 .Case("nlast", AArch64CC::HS)
2703 .Case("last", AArch64CC::LO)
2704 .Case("first", AArch64CC::MI)
2705 .Case("nfrst", AArch64CC::PL)
2706 .Case("pmore", AArch64CC::HI)
2707 .Case("plast", AArch64CC::LS)
2708 .Case("tcont", AArch64CC::GE)
2709 .Case("tstop", AArch64CC::LT)
2710 .Default(AArch64CC::Invalid);
2711
Tim Northover3b0846e2014-05-24 12:50:23 +00002712 return CC;
2713}
2714
2715/// parseCondCode - Parse a Condition Code operand.
2716bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2717 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002718 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002719 SMLoc S = getLoc();
2720 const AsmToken &Tok = Parser.getTok();
2721 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2722
2723 StringRef Cond = Tok.getString();
2724 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2725 if (CC == AArch64CC::Invalid)
2726 return TokError("invalid condition code");
2727 Parser.Lex(); // Eat identifier token.
2728
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002729 if (invertCondCode) {
2730 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2731 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002732 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002733 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002734
2735 Operands.push_back(
2736 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2737 return false;
2738}
2739
2740/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2741/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002742OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002743AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002744 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002745 const AsmToken &Tok = Parser.getTok();
2746 std::string LowerID = Tok.getString().lower();
2747 AArch64_AM::ShiftExtendType ShOp =
2748 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2749 .Case("lsl", AArch64_AM::LSL)
2750 .Case("lsr", AArch64_AM::LSR)
2751 .Case("asr", AArch64_AM::ASR)
2752 .Case("ror", AArch64_AM::ROR)
2753 .Case("msl", AArch64_AM::MSL)
2754 .Case("uxtb", AArch64_AM::UXTB)
2755 .Case("uxth", AArch64_AM::UXTH)
2756 .Case("uxtw", AArch64_AM::UXTW)
2757 .Case("uxtx", AArch64_AM::UXTX)
2758 .Case("sxtb", AArch64_AM::SXTB)
2759 .Case("sxth", AArch64_AM::SXTH)
2760 .Case("sxtw", AArch64_AM::SXTW)
2761 .Case("sxtx", AArch64_AM::SXTX)
2762 .Default(AArch64_AM::InvalidShiftExtend);
2763
2764 if (ShOp == AArch64_AM::InvalidShiftExtend)
2765 return MatchOperand_NoMatch;
2766
2767 SMLoc S = Tok.getLoc();
2768 Parser.Lex();
2769
Nirav Davee833c6c2016-11-08 18:31:04 +00002770 bool Hash = parseOptionalToken(AsmToken::Hash);
2771
Tim Northover3b0846e2014-05-24 12:50:23 +00002772 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2773 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2774 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2775 ShOp == AArch64_AM::MSL) {
2776 // We expect a number here.
2777 TokError("expected #imm after shift specifier");
2778 return MatchOperand_ParseFail;
2779 }
2780
Chad Rosier2ff37b82016-12-27 16:58:09 +00002781 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002782 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2783 Operands.push_back(
2784 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2785 return MatchOperand_Success;
2786 }
2787
Chad Rosier2ff37b82016-12-27 16:58:09 +00002788 // Make sure we do actually have a number, identifier or a parenthesized
2789 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002790 SMLoc E = Parser.getTok().getLoc();
2791 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002792 !Parser.getTok().is(AsmToken::LParen) &&
2793 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002794 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002795 return MatchOperand_ParseFail;
2796 }
2797
2798 const MCExpr *ImmVal;
2799 if (getParser().parseExpression(ImmVal))
2800 return MatchOperand_ParseFail;
2801
2802 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2803 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002804 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002805 return MatchOperand_ParseFail;
2806 }
2807
Jim Grosbach57fd2622014-09-23 22:16:02 +00002808 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002809 Operands.push_back(AArch64Operand::CreateShiftExtend(
2810 ShOp, MCE->getValue(), true, S, E, getContext()));
2811 return MatchOperand_Success;
2812}
2813
Oliver Stannard89b16042018-09-26 13:52:27 +00002814static const struct Extension {
2815 const char *Name;
2816 const FeatureBitset Features;
2817} ExtensionMap[] = {
Diogo N. Sampaio9c906732018-12-06 15:39:17 +00002818 {"crc", {AArch64::FeatureCRC}},
2819 {"sm4", {AArch64::FeatureSM4}},
2820 {"sha3", {AArch64::FeatureSHA3}},
2821 {"sha2", {AArch64::FeatureSHA2}},
2822 {"aes", {AArch64::FeatureAES}},
2823 {"crypto", {AArch64::FeatureCrypto}},
2824 {"fp", {AArch64::FeatureFPARMv8}},
2825 {"simd", {AArch64::FeatureNEON}},
2826 {"ras", {AArch64::FeatureRAS}},
2827 {"lse", {AArch64::FeatureLSE}},
Diogo N. Sampaio1eb31c82019-01-09 11:24:15 +00002828 {"predres", {AArch64::FeaturePredRes}},
Diogo N. Sampaio9c906732018-12-06 15:39:17 +00002829 {"ccdp", {AArch64::FeatureCacheDeepPersist}},
2830 {"mte", {AArch64::FeatureMTE}},
2831 {"tlb-rmi", {AArch64::FeatureTLB_RMI}},
2832 {"pan-rwv", {AArch64::FeaturePAN_RWV}},
2833 {"ccpp", {AArch64::FeatureCCPP}},
Martin Storsjo74d93f92018-12-31 10:22:04 +00002834 {"sve", {AArch64::FeatureSVE}},
Diogo N. Sampaio9c906732018-12-06 15:39:17 +00002835 // FIXME: Unsupported extensions
2836 {"pan", {}},
2837 {"lor", {}},
2838 {"rdma", {}},
2839 {"profile", {}},
Oliver Stannard89b16042018-09-26 13:52:27 +00002840};
2841
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002842static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2843 if (FBS[AArch64::HasV8_1aOps])
2844 Str += "ARMv8.1a";
2845 else if (FBS[AArch64::HasV8_2aOps])
2846 Str += "ARMv8.2a";
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002847 else if (FBS[AArch64::HasV8_3aOps])
2848 Str += "ARMv8.3a";
2849 else if (FBS[AArch64::HasV8_4aOps])
2850 Str += "ARMv8.4a";
Oliver Stannard89b16042018-09-26 13:52:27 +00002851 else if (FBS[AArch64::HasV8_5aOps])
2852 Str += "ARMv8.5a";
2853 else {
2854 auto ext = std::find_if(std::begin(ExtensionMap),
2855 std::end(ExtensionMap),
2856 [&](const Extension& e)
2857 // Use & in case multiple features are enabled
2858 { return (FBS & e.Features) != FeatureBitset(); }
2859 );
2860
2861 Str += ext != std::end(ExtensionMap) ? ext->Name : "(unknown)";
2862 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002863}
2864
2865void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2866 SMLoc S) {
2867 const uint16_t Op2 = Encoding & 7;
2868 const uint16_t Cm = (Encoding & 0x78) >> 3;
2869 const uint16_t Cn = (Encoding & 0x780) >> 7;
2870 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2871
2872 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2873
2874 Operands.push_back(
2875 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2876 Operands.push_back(
2877 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2878 Operands.push_back(
2879 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2880 Expr = MCConstantExpr::create(Op2, getContext());
2881 Operands.push_back(
2882 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2883}
2884
Tim Northover3b0846e2014-05-24 12:50:23 +00002885/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2886/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2887bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2888 OperandVector &Operands) {
2889 if (Name.find('.') != StringRef::npos)
2890 return TokError("invalid operand");
2891
2892 Mnemonic = Name;
2893 Operands.push_back(
2894 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2895
Rafael Espindola961d4692014-11-11 05:18:41 +00002896 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002897 const AsmToken &Tok = Parser.getTok();
2898 StringRef Op = Tok.getString();
2899 SMLoc S = Tok.getLoc();
2900
Tim Northover3b0846e2014-05-24 12:50:23 +00002901 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002902 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2903 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002904 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002905 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2906 std::string Str("IC " + std::string(IC->Name) + " requires ");
2907 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2908 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002909 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002910 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002911 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002912 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2913 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002914 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002915 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2916 std::string Str("DC " + std::string(DC->Name) + " requires ");
2917 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2918 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002919 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002920 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002921 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002922 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2923 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002924 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002925 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2926 std::string Str("AT " + std::string(AT->Name) + " requires ");
2927 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2928 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002929 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002930 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002931 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002932 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2933 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002934 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002935 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2936 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2937 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2938 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002939 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002940 createSysAlias(TLBI->Encoding, Operands, S);
Oliver Stannard224428c2018-09-27 13:47:40 +00002941 } else if (Mnemonic == "cfp" || Mnemonic == "dvp" || Mnemonic == "cpp") {
2942 const AArch64PRCTX::PRCTX *PRCTX = AArch64PRCTX::lookupPRCTXByName(Op);
2943 if (!PRCTX)
2944 return TokError("invalid operand for prediction restriction instruction");
2945 else if (!PRCTX->haveFeatures(getSTI().getFeatureBits())) {
2946 std::string Str(
2947 Mnemonic.upper() + std::string(PRCTX->Name) + " requires ");
2948 setRequiredFeatureString(PRCTX->getRequiredFeatures(), Str);
2949 return TokError(Str.c_str());
2950 }
2951 uint16_t PRCTX_Op2 =
2952 Mnemonic == "cfp" ? 4 :
2953 Mnemonic == "dvp" ? 5 :
2954 Mnemonic == "cpp" ? 7 :
2955 0;
2956 assert(PRCTX_Op2 && "Invalid mnemonic for prediction restriction instruction");
2957 createSysAlias(PRCTX->Encoding << 3 | PRCTX_Op2 , Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002958 }
2959
Tim Northover3b0846e2014-05-24 12:50:23 +00002960 Parser.Lex(); // Eat operand.
2961
2962 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2963 bool HasRegister = false;
2964
2965 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002966 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002967 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2968 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002969 HasRegister = true;
2970 }
2971
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002972 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002973 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002974 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002975 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002976
Nirav Davee833c6c2016-11-08 18:31:04 +00002977 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2978 return true;
2979
Tim Northover3b0846e2014-05-24 12:50:23 +00002980 return false;
2981}
2982
Alex Bradbury58eba092016-11-01 16:32:05 +00002983OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002984AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002985 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002986 const AsmToken &Tok = Parser.getTok();
2987
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002988 if (Mnemonic == "tsb" && Tok.isNot(AsmToken::Identifier)) {
2989 TokError("'csync' operand expected");
2990 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002991 // Can be either a #imm style literal or an option name
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002992 } else if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002993 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002994 const MCExpr *ImmVal;
2995 SMLoc ExprLoc = getLoc();
2996 if (getParser().parseExpression(ImmVal))
2997 return MatchOperand_ParseFail;
2998 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2999 if (!MCE) {
3000 Error(ExprLoc, "immediate value expected for barrier operand");
3001 return MatchOperand_ParseFail;
3002 }
3003 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
3004 Error(ExprLoc, "barrier operand out of range");
3005 return MatchOperand_ParseFail;
3006 }
Tim Northovere6ae6762016-07-05 21:23:04 +00003007 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
3008 Operands.push_back(AArch64Operand::CreateBarrier(
3009 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003010 return MatchOperand_Success;
3011 }
3012
3013 if (Tok.isNot(AsmToken::Identifier)) {
3014 TokError("invalid operand for instruction");
3015 return MatchOperand_ParseFail;
3016 }
3017
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003018 auto TSB = AArch64TSB::lookupTSBByName(Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003019 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00003020 auto DB = AArch64DB::lookupDBByName(Tok.getString());
3021 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003022 TokError("'sy' or #imm operand expected");
3023 return MatchOperand_ParseFail;
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003024 // The only valid named option for TSB is 'csync'
3025 } else if (Mnemonic == "tsb" && (!TSB || TSB->Encoding != AArch64TSB::csync)) {
3026 TokError("'csync' operand expected");
3027 return MatchOperand_ParseFail;
3028 } else if (!DB && !TSB) {
Sjoerd Meijere5b85572017-04-24 08:22:20 +00003029 TokError("invalid barrier option name");
3030 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003031 }
3032
Tim Northovere6ae6762016-07-05 21:23:04 +00003033 Operands.push_back(AArch64Operand::CreateBarrier(
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003034 DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003035 Parser.Lex(); // Consume the option
3036
3037 return MatchOperand_Success;
3038}
3039
Alex Bradbury58eba092016-11-01 16:32:05 +00003040OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003041AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003042 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003043 const AsmToken &Tok = Parser.getTok();
3044
3045 if (Tok.isNot(AsmToken::Identifier))
3046 return MatchOperand_NoMatch;
3047
Tim Northovere6ae6762016-07-05 21:23:04 +00003048 int MRSReg, MSRReg;
3049 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
3050 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
3051 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
3052 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
3053 } else
3054 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00003055
Tim Northovere6ae6762016-07-05 21:23:04 +00003056 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
3057 unsigned PStateImm = -1;
3058 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
3059 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00003060
Tim Northovere6ae6762016-07-05 21:23:04 +00003061 Operands.push_back(
3062 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
3063 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003064 Parser.Lex(); // Eat identifier
3065
3066 return MatchOperand_Success;
3067}
3068
Florian Hahnc4422242017-11-07 13:07:50 +00003069/// tryParseNeonVectorRegister - Parse a vector register operand.
3070bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003071 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003072 if (Parser.getTok().isNot(AsmToken::Identifier))
3073 return true;
3074
3075 SMLoc S = getLoc();
3076 // Check for a vector register specifier first.
3077 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003078 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00003079 OperandMatchResultTy Res =
3080 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
3081 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00003082 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00003083
3084 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
3085 if (!KindRes)
3086 return true;
3087
3088 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00003089 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00003090 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
3091 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00003092
Tim Northover3b0846e2014-05-24 12:50:23 +00003093 // If there was an explicit qualifier, that goes on as a literal text
3094 // operand.
3095 if (!Kind.empty())
3096 Operands.push_back(
3097 AArch64Operand::CreateToken(Kind, false, S, getContext()));
3098
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003099 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3100}
3101
3102OperandMatchResultTy
3103AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00003104 SMLoc SIdx = getLoc();
3105 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003106 const MCExpr *ImmVal;
3107 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003108 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00003109 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3110 if (!MCE) {
3111 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003112 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00003113 }
3114
3115 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003116
Nirav Davee833c6c2016-11-08 18:31:04 +00003117 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003118 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00003119
3120 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
3121 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003122 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003123 }
3124
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003125 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00003126}
3127
Sander de Smalen73937b72018-04-11 07:36:10 +00003128// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00003129// optional kind specifier. If it is a register specifier, eat the token
3130// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00003131OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00003132AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00003133 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00003134 MCAsmParser &Parser = getParser();
3135 const AsmToken &Tok = Parser.getTok();
3136
Florian Hahn91f11e52017-11-07 16:45:48 +00003137 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00003138 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003139
3140 StringRef Name = Tok.getString();
3141 // If there is a kind specifier, it's separated from the register name by
3142 // a '.'.
3143 size_t Start = 0, Next = Name.find('.');
3144 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00003145 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00003146
3147 if (RegNum) {
3148 if (Next != StringRef::npos) {
3149 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00003150 if (!isValidVectorKind(Kind, MatchKind)) {
3151 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00003152 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00003153 }
3154 }
Sander de Smalen8e607342017-11-15 15:44:43 +00003155 Parser.Lex(); // Eat the register token.
3156
3157 Reg = RegNum;
3158 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00003159 }
3160
Sander de Smalen8e607342017-11-15 15:44:43 +00003161 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003162}
3163
Sander de Smalencd6be962017-12-20 11:02:42 +00003164/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
3165OperandMatchResultTy
3166AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
3167 // Check for a SVE predicate register specifier first.
3168 const SMLoc S = getLoc();
3169 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003170 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00003171 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00003172 if (Res != MatchOperand_Success)
3173 return Res;
3174
Sander de Smalen73937b72018-04-11 07:36:10 +00003175 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
3176 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00003177 return MatchOperand_NoMatch;
3178
Sander de Smalen73937b72018-04-11 07:36:10 +00003179 unsigned ElementWidth = KindRes->second;
3180 Operands.push_back(AArch64Operand::CreateVectorReg(
3181 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
3182 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00003183
Sander de Smalen7868e742018-01-09 11:17:06 +00003184 // Not all predicates are followed by a '/m' or '/z'.
3185 MCAsmParser &Parser = getParser();
3186 if (Parser.getTok().isNot(AsmToken::Slash))
3187 return MatchOperand_Success;
3188
3189 // But when they do they shouldn't have an element type suffix.
3190 if (!Kind.empty()) {
3191 Error(S, "not expecting size suffix");
3192 return MatchOperand_ParseFail;
3193 }
3194
3195 // Add a literal slash as operand
3196 Operands.push_back(
3197 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
3198
3199 Parser.Lex(); // Eat the slash.
3200
3201 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00003202 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00003203 if (Pred != "z" && Pred != "m") {
3204 Error(getLoc(), "expecting 'm' or 'z' predication");
3205 return MatchOperand_ParseFail;
3206 }
3207
3208 // Add zero/merge token.
3209 const char *ZM = Pred == "z" ? "z" : "m";
3210 Operands.push_back(
3211 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
3212
3213 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00003214 return MatchOperand_Success;
3215}
3216
Sander de Smalen50d87022018-04-19 07:35:08 +00003217/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00003218bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003219 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00003220 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00003221 return false;
3222
Sander de Smalen149916d2018-04-20 07:24:20 +00003223 // Otherwise try for a scalar register.
3224 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
3225 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003226
Sander de Smalen149916d2018-04-20 07:24:20 +00003227 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003228}
3229
3230bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003231 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003232 bool HasELFModifier = false;
3233 AArch64MCExpr::VariantKind RefKind;
3234
Nirav Davee833c6c2016-11-08 18:31:04 +00003235 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003236 HasELFModifier = true;
3237
Nirav Davee833c6c2016-11-08 18:31:04 +00003238 if (Parser.getTok().isNot(AsmToken::Identifier))
3239 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003240
3241 std::string LowerCase = Parser.getTok().getIdentifier().lower();
3242 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
3243 .Case("lo12", AArch64MCExpr::VK_LO12)
3244 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
3245 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
3246 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
3247 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
3248 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
3249 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
3250 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
3251 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
3252 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
3253 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
3254 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
3255 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
3256 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3257 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3258 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3259 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3260 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3261 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3262 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3263 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3264 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3265 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3266 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3267 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3268 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3269 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3270 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3271 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3272 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3273 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3274 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3275 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3276 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3277 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003278 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3279 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00003280 .Default(AArch64MCExpr::VK_INVALID);
3281
Nirav Davee833c6c2016-11-08 18:31:04 +00003282 if (RefKind == AArch64MCExpr::VK_INVALID)
3283 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003284
3285 Parser.Lex(); // Eat identifier
3286
Nirav Davee833c6c2016-11-08 18:31:04 +00003287 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003288 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003289 }
3290
3291 if (getParser().parseExpression(ImmVal))
3292 return true;
3293
3294 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003295 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003296
3297 return false;
3298}
3299
Sander de Smalen650234b2018-04-12 11:40:52 +00003300template <RegKind VectorKind>
3301OperandMatchResultTy
3302AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3303 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003304 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003305 if (!Parser.getTok().is(AsmToken::LCurly))
3306 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003307
3308 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003309 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003310 bool NoMatchIsError) {
3311 auto RegTok = Parser.getTok();
3312 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3313 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003314 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003315 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003316 llvm_unreachable("Expected a valid vector kind");
3317 }
3318
Sander de Smalen650234b2018-04-12 11:40:52 +00003319 if (RegTok.isNot(AsmToken::Identifier) ||
3320 ParseRes == MatchOperand_ParseFail ||
3321 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3322 Error(Loc, "vector register expected");
3323 return MatchOperand_ParseFail;
3324 }
3325
3326 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003327 };
3328
Tim Northover3b0846e2014-05-24 12:50:23 +00003329 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003330 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003331 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003332
Tim Northover3b0846e2014-05-24 12:50:23 +00003333 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003334 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003335 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3336
3337 // Put back the original left bracket if there was no match, so that
3338 // different types of list-operands can be matched (e.g. SVE, Neon).
3339 if (ParseRes == MatchOperand_NoMatch)
3340 Parser.getLexer().UnLex(LCurly);
3341
3342 if (ParseRes != MatchOperand_Success)
3343 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003344
Tim Northover3b0846e2014-05-24 12:50:23 +00003345 int64_t PrevReg = FirstReg;
3346 unsigned Count = 1;
3347
Nirav Davee833c6c2016-11-08 18:31:04 +00003348 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003349 SMLoc Loc = getLoc();
3350 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003351
Sander de Smalen50d87022018-04-19 07:35:08 +00003352 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003353 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3354 if (ParseRes != MatchOperand_Success)
3355 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003356
Tim Northover3b0846e2014-05-24 12:50:23 +00003357 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003358 if (Kind != NextKind) {
3359 Error(Loc, "mismatched register size suffix");
3360 return MatchOperand_ParseFail;
3361 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003362
3363 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3364
3365 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003366 Error(Loc, "invalid number of vectors");
3367 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003368 }
3369
3370 Count += Space;
3371 }
3372 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003373 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003374 SMLoc Loc = getLoc();
3375 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003376 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003377 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3378 if (ParseRes != MatchOperand_Success)
3379 return ParseRes;
3380
Tim Northover3b0846e2014-05-24 12:50:23 +00003381 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003382 if (Kind != NextKind) {
3383 Error(Loc, "mismatched register size suffix");
3384 return MatchOperand_ParseFail;
3385 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003386
3387 // Registers must be incremental (with wraparound at 31)
3388 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003389 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3390 Error(Loc, "registers must be sequential");
3391 return MatchOperand_ParseFail;
3392 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003393
3394 PrevReg = Reg;
3395 ++Count;
3396 }
3397 }
3398
Nirav Davee833c6c2016-11-08 18:31:04 +00003399 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003400 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003401
Sander de Smalen650234b2018-04-12 11:40:52 +00003402 if (Count > 4) {
3403 Error(S, "invalid number of vectors");
3404 return MatchOperand_ParseFail;
3405 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003406
3407 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003408 unsigned ElementWidth = 0;
3409 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003410 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003411 std::tie(NumElements, ElementWidth) = *VK;
3412 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003413
3414 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003415 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3416 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003417
Sander de Smalen650234b2018-04-12 11:40:52 +00003418 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003419}
3420
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003421/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3422bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003423 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3424 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003425 return true;
3426
3427 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3428}
3429
Alex Bradbury58eba092016-11-01 16:32:05 +00003430OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003431AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003432 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003433
Sander de Smalen50d87022018-04-19 07:35:08 +00003434 unsigned RegNum;
3435 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3436 if (Res != MatchOperand_Success)
3437 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003438
Nirav Davee833c6c2016-11-08 18:31:04 +00003439 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003440 Operands.push_back(AArch64Operand::CreateReg(
3441 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003442 return MatchOperand_Success;
3443 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003444
Nirav Davee833c6c2016-11-08 18:31:04 +00003445 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003446
Sander de Smalen50d87022018-04-19 07:35:08 +00003447 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003448 Error(getLoc(), "index must be absent or #0");
3449 return MatchOperand_ParseFail;
3450 }
3451
3452 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003453 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003454 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3455 Error(getLoc(), "index must be absent or #0");
3456 return MatchOperand_ParseFail;
3457 }
3458
Sander de Smalen50d87022018-04-19 07:35:08 +00003459 Operands.push_back(AArch64Operand::CreateReg(
3460 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003461 return MatchOperand_Success;
3462}
3463
Sander de Smalen0325e302018-07-02 07:34:52 +00003464template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
Sander de Smalen149916d2018-04-20 07:24:20 +00003465OperandMatchResultTy
3466AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3467 SMLoc StartLoc = getLoc();
3468
3469 unsigned RegNum;
3470 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3471 if (Res != MatchOperand_Success)
3472 return Res;
3473
3474 // No shift/extend is the default.
3475 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3476 Operands.push_back(AArch64Operand::CreateReg(
Sander de Smalen0325e302018-07-02 07:34:52 +00003477 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
Sander de Smalen149916d2018-04-20 07:24:20 +00003478 return MatchOperand_Success;
3479 }
3480
3481 // Eat the comma
3482 getParser().Lex();
3483
3484 // Match the shift
3485 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3486 Res = tryParseOptionalShiftExtend(ExtOpnd);
3487 if (Res != MatchOperand_Success)
3488 return Res;
3489
3490 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
Sander de Smalen0325e302018-07-02 07:34:52 +00003491 Operands.push_back(AArch64Operand::CreateReg(
3492 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3493 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3494 Ext->hasShiftExtendAmount()));
Sander de Smalen149916d2018-04-20 07:24:20 +00003495
3496 return MatchOperand_Success;
3497}
3498
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003499bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
Sander de Smalen5c625982018-04-13 12:56:14 +00003500 MCAsmParser &Parser = getParser();
3501
3502 // Some SVE instructions have a decoration after the immediate, i.e.
3503 // "mul vl". We parse them here and add tokens, which must be present in the
3504 // asm string in the tablegen instruction.
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003505 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3506 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
Sander de Smalen5c625982018-04-13 12:56:14 +00003507 if (!Parser.getTok().getString().equals_lower("mul") ||
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003508 !(NextIsVL || NextIsHash))
Sander de Smalen5c625982018-04-13 12:56:14 +00003509 return true;
3510
Sander de Smalen5c625982018-04-13 12:56:14 +00003511 Operands.push_back(
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003512 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
Sander de Smalen5c625982018-04-13 12:56:14 +00003513 Parser.Lex(); // Eat the "mul"
3514
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003515 if (NextIsVL) {
3516 Operands.push_back(
3517 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3518 Parser.Lex(); // Eat the "vl"
3519 return false;
3520 }
Sander de Smalen5c625982018-04-13 12:56:14 +00003521
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003522 if (NextIsHash) {
3523 Parser.Lex(); // Eat the #
3524 SMLoc S = getLoc();
3525
3526 // Parse immediate operand.
3527 const MCExpr *ImmVal;
3528 if (!Parser.parseExpression(ImmVal))
3529 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3530 Operands.push_back(AArch64Operand::CreateImm(
3531 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3532 getContext()));
3533 return MatchOperand_Success;
3534 }
3535 }
3536
3537 return Error(getLoc(), "expected 'vl' or '#<imm>'");
Sander de Smalen5c625982018-04-13 12:56:14 +00003538}
3539
Tim Northover3b0846e2014-05-24 12:50:23 +00003540/// parseOperand - Parse a arm instruction operand. For now this parses the
3541/// operand regardless of the mnemonic.
3542bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3543 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003544 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003545
3546 OperandMatchResultTy ResTy =
3547 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3548
Tim Northover3b0846e2014-05-24 12:50:23 +00003549 // Check if the current operand has a custom associated parser, if so, try to
3550 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003551 if (ResTy == MatchOperand_Success)
3552 return false;
3553 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3554 // there was a match, but an error occurred, in which case, just return that
3555 // the operand parsing failed.
3556 if (ResTy == MatchOperand_ParseFail)
3557 return true;
3558
3559 // Nothing custom, so do general case parsing.
3560 SMLoc S, E;
3561 switch (getLexer().getKind()) {
3562 default: {
3563 SMLoc S = getLoc();
3564 const MCExpr *Expr;
3565 if (parseSymbolicImmVal(Expr))
3566 return Error(S, "invalid operand");
3567
3568 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3569 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3570 return false;
3571 }
3572 case AsmToken::LBrac: {
3573 SMLoc Loc = Parser.getTok().getLoc();
3574 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3575 getContext()));
3576 Parser.Lex(); // Eat '['
3577
3578 // There's no comma after a '[', so we can parse the next operand
3579 // immediately.
3580 return parseOperand(Operands, false, false);
3581 }
3582 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003583 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003584 case AsmToken::Identifier: {
3585 // If we're expecting a Condition Code operand, then just parse that.
3586 if (isCondCode)
3587 return parseCondCode(Operands, invertCondCode);
3588
3589 // If it's a register name, parse it.
3590 if (!parseRegister(Operands))
3591 return false;
3592
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003593 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3594 // by SVE instructions.
3595 if (!parseOptionalMulOperand(Operands))
Sander de Smalen5c625982018-04-13 12:56:14 +00003596 return false;
3597
Tim Northover3b0846e2014-05-24 12:50:23 +00003598 // This could be an optional "shift" or "extend" operand.
3599 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3600 // We can only continue if no tokens were eaten.
3601 if (GotShift != MatchOperand_NoMatch)
3602 return GotShift;
3603
3604 // This was not a register so parse other operands that start with an
3605 // identifier (like labels) as expressions and create them as immediates.
3606 const MCExpr *IdVal;
3607 S = getLoc();
3608 if (getParser().parseExpression(IdVal))
3609 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003610 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3611 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3612 return false;
3613 }
3614 case AsmToken::Integer:
3615 case AsmToken::Real:
3616 case AsmToken::Hash: {
3617 // #42 -> immediate.
3618 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003619
3620 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003621
3622 // Parse a negative sign
3623 bool isNegative = false;
3624 if (Parser.getTok().is(AsmToken::Minus)) {
3625 isNegative = true;
3626 // We need to consume this token only when we have a Real, otherwise
3627 // we let parseSymbolicImmVal take care of it
3628 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3629 Parser.Lex();
3630 }
3631
3632 // The only Real that should come through here is a literal #0.0 for
3633 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3634 // so convert the value.
3635 const AsmToken &Tok = Parser.getTok();
3636 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003637 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003638 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3639 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3640 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
Sander de Smalen8fcc3f52018-07-03 09:07:23 +00003641 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
Tim Northover3b0846e2014-05-24 12:50:23 +00003642 return TokError("unexpected floating point literal");
3643 else if (IntVal != 0 || isNegative)
3644 return TokError("expected floating-point constant #0.0");
3645 Parser.Lex(); // Eat the token.
3646
3647 Operands.push_back(
3648 AArch64Operand::CreateToken("#0", false, S, getContext()));
3649 Operands.push_back(
3650 AArch64Operand::CreateToken(".0", false, S, getContext()));
3651 return false;
3652 }
3653
3654 const MCExpr *ImmVal;
3655 if (parseSymbolicImmVal(ImmVal))
3656 return true;
3657
3658 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3659 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3660 return false;
3661 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003662 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003663 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003664 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003665 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003666 Parser.Lex(); // Eat '='
3667 const MCExpr *SubExprVal;
3668 if (getParser().parseExpression(SubExprVal))
3669 return true;
3670
David Peixottoae5ba762014-07-18 16:05:14 +00003671 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003672 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003673 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003674
3675 bool IsXReg =
3676 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3677 Operands[1]->getReg());
3678
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003679 MCContext& Ctx = getContext();
3680 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3681 // 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 +00003682 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003683 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3684 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3685 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3686 ShiftAmt += 16;
3687 Imm >>= 16;
3688 }
3689 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3690 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3691 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003692 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003693 if (ShiftAmt)
3694 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3695 ShiftAmt, true, S, E, Ctx));
3696 return false;
3697 }
David Peixottoae5ba762014-07-18 16:05:14 +00003698 APInt Simm = APInt(64, Imm << ShiftAmt);
3699 // check if the immediate is an unsigned or signed 32-bit int for W regs
3700 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3701 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003702 }
3703 // 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 +00003704 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003705 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003706 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3707 return false;
3708 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003709 }
3710}
3711
Sander de Smalen0325e302018-07-02 07:34:52 +00003712bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3713 const MCParsedAsmOperand &Op2) const {
3714 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3715 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3716 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3717 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3718 return MCTargetAsmParser::regsEqual(Op1, Op2);
3719
3720 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3721 "Testing equality of non-scalar registers not supported");
3722
3723 // Check if a registers match their sub/super register classes.
3724 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3725 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3726 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3727 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3728 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3729 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3730 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3731 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3732
3733 return false;
3734}
3735
Tim Northover3b0846e2014-05-24 12:50:23 +00003736/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3737/// operands.
3738bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3739 StringRef Name, SMLoc NameLoc,
3740 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003741 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003742 Name = StringSwitch<StringRef>(Name.lower())
3743 .Case("beq", "b.eq")
3744 .Case("bne", "b.ne")
3745 .Case("bhs", "b.hs")
3746 .Case("bcs", "b.cs")
3747 .Case("blo", "b.lo")
3748 .Case("bcc", "b.cc")
3749 .Case("bmi", "b.mi")
3750 .Case("bpl", "b.pl")
3751 .Case("bvs", "b.vs")
3752 .Case("bvc", "b.vc")
3753 .Case("bhi", "b.hi")
3754 .Case("bls", "b.ls")
3755 .Case("bge", "b.ge")
3756 .Case("blt", "b.lt")
3757 .Case("bgt", "b.gt")
3758 .Case("ble", "b.le")
3759 .Case("bal", "b.al")
3760 .Case("bnv", "b.nv")
3761 .Default(Name);
3762
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003763 // First check for the AArch64-specific .req directive.
3764 if (Parser.getTok().is(AsmToken::Identifier) &&
3765 Parser.getTok().getIdentifier() == ".req") {
3766 parseDirectiveReq(Name, NameLoc);
3767 // We always return 'error' for this, as we're done with this
3768 // statement and don't need to match the 'instruction."
3769 return true;
3770 }
3771
Tim Northover3b0846e2014-05-24 12:50:23 +00003772 // Create the leading tokens for the mnemonic, split by '.' characters.
3773 size_t Start = 0, Next = Name.find('.');
3774 StringRef Head = Name.slice(Start, Next);
3775
Oliver Stannard224428c2018-09-27 13:47:40 +00003776 // IC, DC, AT, TLBI and Prediction invalidation instructions are aliases for
3777 // the SYS instruction.
3778 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi" ||
3779 Head == "cfp" || Head == "dvp" || Head == "cpp")
Nirav Davee833c6c2016-11-08 18:31:04 +00003780 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003781
3782 Operands.push_back(
3783 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3784 Mnemonic = Head;
3785
3786 // Handle condition codes for a branch mnemonic
3787 if (Head == "b" && Next != StringRef::npos) {
3788 Start = Next;
3789 Next = Name.find('.', Start + 1);
3790 Head = Name.slice(Start + 1, Next);
3791
3792 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3793 (Head.data() - Name.data()));
3794 AArch64CC::CondCode CC = parseCondCodeString(Head);
3795 if (CC == AArch64CC::Invalid)
3796 return Error(SuffixLoc, "invalid condition code");
3797 Operands.push_back(
3798 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3799 Operands.push_back(
3800 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3801 }
3802
3803 // Add the remaining tokens in the mnemonic.
3804 while (Next != StringRef::npos) {
3805 Start = Next;
3806 Next = Name.find('.', Start + 1);
3807 Head = Name.slice(Start, Next);
3808 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3809 (Head.data() - Name.data()) + 1);
3810 Operands.push_back(
3811 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3812 }
3813
3814 // Conditional compare instructions have a Condition Code operand, which needs
3815 // to be parsed and an immediate operand created.
3816 bool condCodeFourthOperand =
3817 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3818 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3819 Head == "csinc" || Head == "csinv" || Head == "csneg");
3820
3821 // These instructions are aliases to some of the conditional select
3822 // instructions. However, the condition code is inverted in the aliased
3823 // instruction.
3824 //
3825 // FIXME: Is this the correct way to handle these? Or should the parser
3826 // generate the aliased instructions directly?
3827 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3828 bool condCodeThirdOperand =
3829 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3830
3831 // Read the remaining operands.
3832 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003833
Oliver Stannardc4190282018-10-02 10:04:39 +00003834 unsigned N = 1;
3835 do {
Tim Northover3b0846e2014-05-24 12:50:23 +00003836 // Parse and remember the operand.
3837 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3838 (N == 3 && condCodeThirdOperand) ||
3839 (N == 2 && condCodeSecondOperand),
3840 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003841 return true;
3842 }
3843
3844 // After successfully parsing some operands there are two special cases to
3845 // consider (i.e. notional operands not separated by commas). Both are due
3846 // to memory specifiers:
3847 // + An RBrac will end an address for load/store/prefetch
3848 // + An '!' will indicate a pre-indexed operation.
3849 //
3850 // It's someone else's responsibility to make sure these tokens are sane
3851 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003852
Nirav Davee833c6c2016-11-08 18:31:04 +00003853 SMLoc RLoc = Parser.getTok().getLoc();
3854 if (parseOptionalToken(AsmToken::RBrac))
3855 Operands.push_back(
3856 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3857 SMLoc ELoc = Parser.getTok().getLoc();
3858 if (parseOptionalToken(AsmToken::Exclaim))
3859 Operands.push_back(
3860 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003861
3862 ++N;
Oliver Stannardc4190282018-10-02 10:04:39 +00003863 } while (parseOptionalToken(AsmToken::Comma));
Tim Northover3b0846e2014-05-24 12:50:23 +00003864 }
3865
Nirav Davee833c6c2016-11-08 18:31:04 +00003866 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3867 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003868
Tim Northover3b0846e2014-05-24 12:50:23 +00003869 return false;
3870}
3871
Sander de Smalen9b333092018-07-30 15:42:46 +00003872static inline bool isMatchingOrAlias(unsigned ZReg, unsigned Reg) {
3873 assert((ZReg >= AArch64::Z0) && (ZReg <= AArch64::Z31));
3874 return (ZReg == ((Reg - AArch64::B0) + AArch64::Z0)) ||
3875 (ZReg == ((Reg - AArch64::H0) + AArch64::Z0)) ||
3876 (ZReg == ((Reg - AArch64::S0) + AArch64::Z0)) ||
3877 (ZReg == ((Reg - AArch64::D0) + AArch64::Z0)) ||
3878 (ZReg == ((Reg - AArch64::Q0) + AArch64::Z0)) ||
3879 (ZReg == ((Reg - AArch64::Z0) + AArch64::Z0));
3880}
3881
Tim Northover3b0846e2014-05-24 12:50:23 +00003882// FIXME: This entire function is a giant hack to provide us with decent
3883// operand range validation/diagnostics until TableGen/MC can be extended
3884// to support autogeneration of this kind of validation.
Sander de Smalen9b333092018-07-30 15:42:46 +00003885bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
3886 SmallVectorImpl<SMLoc> &Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003887 const MCRegisterInfo *RI = getContext().getRegisterInfo();
Sander de Smalen9b333092018-07-30 15:42:46 +00003888 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
3889
3890 // A prefix only applies to the instruction following it. Here we extract
3891 // prefix information for the next instruction before validating the current
3892 // one so that in the case of failure we don't erronously continue using the
3893 // current prefix.
3894 PrefixInfo Prefix = NextPrefix;
3895 NextPrefix = PrefixInfo::CreateFromInst(Inst, MCID.TSFlags);
3896
3897 // Before validating the instruction in isolation we run through the rules
3898 // applicable when it follows a prefix instruction.
3899 // NOTE: brk & hlt can be prefixed but require no additional validation.
3900 if (Prefix.isActive() &&
3901 (Inst.getOpcode() != AArch64::BRK) &&
3902 (Inst.getOpcode() != AArch64::HLT)) {
3903
3904 // Prefixed intructions must have a destructive operand.
3905 if ((MCID.TSFlags & AArch64::DestructiveInstTypeMask) ==
3906 AArch64::NotDestructive)
3907 return Error(IDLoc, "instruction is unpredictable when following a"
3908 " movprfx, suggest replacing movprfx with mov");
3909
3910 // Destination operands must match.
3911 if (Inst.getOperand(0).getReg() != Prefix.getDstReg())
3912 return Error(Loc[0], "instruction is unpredictable when following a"
3913 " movprfx writing to a different destination");
3914
3915 // Destination operand must not be used in any other location.
3916 for (unsigned i = 1; i < Inst.getNumOperands(); ++i) {
3917 if (Inst.getOperand(i).isReg() &&
3918 (MCID.getOperandConstraint(i, MCOI::TIED_TO) == -1) &&
3919 isMatchingOrAlias(Prefix.getDstReg(), Inst.getOperand(i).getReg()))
3920 return Error(Loc[0], "instruction is unpredictable when following a"
3921 " movprfx and destination also used as non-destructive"
3922 " source");
3923 }
3924
3925 auto PPRRegClass = AArch64MCRegisterClasses[AArch64::PPRRegClassID];
3926 if (Prefix.isPredicated()) {
3927 int PgIdx = -1;
3928
3929 // Find the instructions general predicate.
3930 for (unsigned i = 1; i < Inst.getNumOperands(); ++i)
3931 if (Inst.getOperand(i).isReg() &&
3932 PPRRegClass.contains(Inst.getOperand(i).getReg())) {
3933 PgIdx = i;
3934 break;
3935 }
3936
3937 // Instruction must be predicated if the movprfx is predicated.
3938 if (PgIdx == -1 ||
3939 (MCID.TSFlags & AArch64::ElementSizeMask) == AArch64::ElementSizeNone)
3940 return Error(IDLoc, "instruction is unpredictable when following a"
3941 " predicated movprfx, suggest using unpredicated movprfx");
3942
3943 // Instruction must use same general predicate as the movprfx.
3944 if (Inst.getOperand(PgIdx).getReg() != Prefix.getPgReg())
3945 return Error(IDLoc, "instruction is unpredictable when following a"
3946 " predicated movprfx using a different general predicate");
3947
3948 // Instruction element type must match the movprfx.
3949 if ((MCID.TSFlags & AArch64::ElementSizeMask) != Prefix.getElementSize())
3950 return Error(IDLoc, "instruction is unpredictable when following a"
3951 " predicated movprfx with a different element size");
3952 }
3953 }
3954
Tim Northover3b0846e2014-05-24 12:50:23 +00003955 // Check for indexed addressing modes w/ the base register being the
3956 // same as a destination/source register or pair load where
3957 // the Rt == Rt2. All of those are undefined behaviour.
3958 switch (Inst.getOpcode()) {
3959 case AArch64::LDPSWpre:
3960 case AArch64::LDPWpost:
3961 case AArch64::LDPWpre:
3962 case AArch64::LDPXpost:
3963 case AArch64::LDPXpre: {
3964 unsigned Rt = Inst.getOperand(1).getReg();
3965 unsigned Rt2 = Inst.getOperand(2).getReg();
3966 unsigned Rn = Inst.getOperand(3).getReg();
3967 if (RI->isSubRegisterEq(Rn, Rt))
3968 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3969 "is also a destination");
3970 if (RI->isSubRegisterEq(Rn, Rt2))
3971 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3972 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003973 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003974 }
3975 case AArch64::LDPDi:
3976 case AArch64::LDPQi:
3977 case AArch64::LDPSi:
3978 case AArch64::LDPSWi:
3979 case AArch64::LDPWi:
3980 case AArch64::LDPXi: {
3981 unsigned Rt = Inst.getOperand(0).getReg();
3982 unsigned Rt2 = Inst.getOperand(1).getReg();
3983 if (Rt == Rt2)
3984 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3985 break;
3986 }
3987 case AArch64::LDPDpost:
3988 case AArch64::LDPDpre:
3989 case AArch64::LDPQpost:
3990 case AArch64::LDPQpre:
3991 case AArch64::LDPSpost:
3992 case AArch64::LDPSpre:
3993 case AArch64::LDPSWpost: {
3994 unsigned Rt = Inst.getOperand(1).getReg();
3995 unsigned Rt2 = Inst.getOperand(2).getReg();
3996 if (Rt == Rt2)
3997 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3998 break;
3999 }
4000 case AArch64::STPDpost:
4001 case AArch64::STPDpre:
4002 case AArch64::STPQpost:
4003 case AArch64::STPQpre:
4004 case AArch64::STPSpost:
4005 case AArch64::STPSpre:
4006 case AArch64::STPWpost:
4007 case AArch64::STPWpre:
4008 case AArch64::STPXpost:
4009 case AArch64::STPXpre: {
4010 unsigned Rt = Inst.getOperand(1).getReg();
4011 unsigned Rt2 = Inst.getOperand(2).getReg();
4012 unsigned Rn = Inst.getOperand(3).getReg();
4013 if (RI->isSubRegisterEq(Rn, Rt))
4014 return Error(Loc[0], "unpredictable STP instruction, writeback base "
4015 "is also a source");
4016 if (RI->isSubRegisterEq(Rn, Rt2))
4017 return Error(Loc[1], "unpredictable STP instruction, writeback base "
4018 "is also a source");
4019 break;
4020 }
4021 case AArch64::LDRBBpre:
4022 case AArch64::LDRBpre:
4023 case AArch64::LDRHHpre:
4024 case AArch64::LDRHpre:
4025 case AArch64::LDRSBWpre:
4026 case AArch64::LDRSBXpre:
4027 case AArch64::LDRSHWpre:
4028 case AArch64::LDRSHXpre:
4029 case AArch64::LDRSWpre:
4030 case AArch64::LDRWpre:
4031 case AArch64::LDRXpre:
4032 case AArch64::LDRBBpost:
4033 case AArch64::LDRBpost:
4034 case AArch64::LDRHHpost:
4035 case AArch64::LDRHpost:
4036 case AArch64::LDRSBWpost:
4037 case AArch64::LDRSBXpost:
4038 case AArch64::LDRSHWpost:
4039 case AArch64::LDRSHXpost:
4040 case AArch64::LDRSWpost:
4041 case AArch64::LDRWpost:
4042 case AArch64::LDRXpost: {
4043 unsigned Rt = Inst.getOperand(1).getReg();
4044 unsigned Rn = Inst.getOperand(2).getReg();
4045 if (RI->isSubRegisterEq(Rn, Rt))
4046 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
4047 "is also a source");
4048 break;
4049 }
4050 case AArch64::STRBBpost:
4051 case AArch64::STRBpost:
4052 case AArch64::STRHHpost:
4053 case AArch64::STRHpost:
4054 case AArch64::STRWpost:
4055 case AArch64::STRXpost:
4056 case AArch64::STRBBpre:
4057 case AArch64::STRBpre:
4058 case AArch64::STRHHpre:
4059 case AArch64::STRHpre:
4060 case AArch64::STRWpre:
4061 case AArch64::STRXpre: {
4062 unsigned Rt = Inst.getOperand(1).getReg();
4063 unsigned Rn = Inst.getOperand(2).getReg();
4064 if (RI->isSubRegisterEq(Rn, Rt))
4065 return Error(Loc[0], "unpredictable STR instruction, writeback base "
4066 "is also a source");
4067 break;
4068 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004069 case AArch64::STXRB:
4070 case AArch64::STXRH:
4071 case AArch64::STXRW:
4072 case AArch64::STXRX:
4073 case AArch64::STLXRB:
4074 case AArch64::STLXRH:
4075 case AArch64::STLXRW:
4076 case AArch64::STLXRX: {
4077 unsigned Rs = Inst.getOperand(0).getReg();
4078 unsigned Rt = Inst.getOperand(1).getReg();
4079 unsigned Rn = Inst.getOperand(2).getReg();
4080 if (RI->isSubRegisterEq(Rt, Rs) ||
4081 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
4082 return Error(Loc[0],
4083 "unpredictable STXR instruction, status is also a source");
4084 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00004085 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004086 case AArch64::STXPW:
4087 case AArch64::STXPX:
4088 case AArch64::STLXPW:
4089 case AArch64::STLXPX: {
4090 unsigned Rs = Inst.getOperand(0).getReg();
4091 unsigned Rt1 = Inst.getOperand(1).getReg();
4092 unsigned Rt2 = Inst.getOperand(2).getReg();
4093 unsigned Rn = Inst.getOperand(3).getReg();
4094 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
4095 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
4096 return Error(Loc[0],
4097 "unpredictable STXP instruction, status is also a source");
4098 break;
4099 }
Oliver Stannardc4190282018-10-02 10:04:39 +00004100 case AArch64::LDGV: {
4101 unsigned Rt = Inst.getOperand(0).getReg();
4102 unsigned Rn = Inst.getOperand(1).getReg();
4103 if (RI->isSubRegisterEq(Rt, Rn)) {
4104 return Error(Loc[0],
4105 "unpredictable LDGV instruction, writeback register is also "
4106 "the target register");
4107 }
4108 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004109 }
4110
Tim Northover3b0846e2014-05-24 12:50:23 +00004111
4112 // Now check immediate ranges. Separate from the above as there is overlap
4113 // in the instructions being checked and this keeps the nested conditionals
4114 // to a minimum.
4115 switch (Inst.getOpcode()) {
4116 case AArch64::ADDSWri:
4117 case AArch64::ADDSXri:
4118 case AArch64::ADDWri:
4119 case AArch64::ADDXri:
4120 case AArch64::SUBSWri:
4121 case AArch64::SUBSXri:
4122 case AArch64::SUBWri:
4123 case AArch64::SUBXri: {
4124 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
4125 // some slight duplication here.
4126 if (Inst.getOperand(2).isExpr()) {
4127 const MCExpr *Expr = Inst.getOperand(2).getExpr();
4128 AArch64MCExpr::VariantKind ELFRefKind;
4129 MCSymbolRefExpr::VariantKind DarwinRefKind;
4130 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00004131 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
4132
4133 // Only allow these with ADDXri.
4134 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
4135 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
4136 Inst.getOpcode() == AArch64::ADDXri)
4137 return false;
4138
4139 // Only allow these with ADDXri/ADDWri
4140 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
4141 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
4142 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
4143 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
4144 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
4145 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
4146 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00004147 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
4148 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
4149 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00004150 (Inst.getOpcode() == AArch64::ADDXri ||
4151 Inst.getOpcode() == AArch64::ADDWri))
4152 return false;
4153
4154 // Don't allow symbol refs in the immediate field otherwise
4155 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
4156 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
4157 // 'cmp w0, 'borked')
4158 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00004159 }
Diana Picusc93518d2016-10-11 09:17:47 +00004160 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00004161 }
4162 return false;
4163 }
4164 default:
4165 return false;
4166 }
4167}
4168
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004169static std::string AArch64MnemonicSpellCheck(StringRef S,
4170 const FeatureBitset &FBS,
Craig Topper05515562017-10-26 06:46:41 +00004171 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004172
4173bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
Sander de Smalen0325e302018-07-02 07:34:52 +00004174 uint64_t ErrorInfo,
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004175 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004176 switch (ErrCode) {
Sander de Smalen0325e302018-07-02 07:34:52 +00004177 case Match_InvalidTiedOperand: {
4178 RegConstraintEqualityTy EqTy =
4179 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
4180 .getRegEqualityTy();
4181 switch (EqTy) {
4182 case RegConstraintEqualityTy::EqualsSubReg:
4183 return Error(Loc, "operand must be 64-bit form of destination register");
4184 case RegConstraintEqualityTy::EqualsSuperReg:
4185 return Error(Loc, "operand must be 32-bit form of destination register");
4186 case RegConstraintEqualityTy::EqualsReg:
4187 return Error(Loc, "operand must match destination register");
4188 }
Simon Pilgrim6dc45e62018-07-05 09:48:01 +00004189 llvm_unreachable("Unknown RegConstraintEqualityTy");
Sander de Smalen0325e302018-07-02 07:34:52 +00004190 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004191 case Match_MissingFeature:
4192 return Error(Loc,
4193 "instruction requires a CPU feature not currently enabled");
4194 case Match_InvalidOperand:
4195 return Error(Loc, "invalid operand for instruction");
4196 case Match_InvalidSuffix:
4197 return Error(Loc, "invalid type suffix for instruction");
4198 case Match_InvalidCondCode:
4199 return Error(Loc, "expected AArch64 condition code");
4200 case Match_AddSubRegExtendSmall:
4201 return Error(Loc,
4202 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
4203 case Match_AddSubRegExtendLarge:
4204 return Error(Loc,
4205 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
4206 case Match_AddSubSecondSource:
4207 return Error(Loc,
4208 "expected compatible register, symbol or integer in range [0, 4095]");
4209 case Match_LogicalSecondSource:
4210 return Error(Loc, "expected compatible register or logical immediate");
4211 case Match_InvalidMovImm32Shift:
4212 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
4213 case Match_InvalidMovImm64Shift:
4214 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
4215 case Match_AddSubRegShift32:
4216 return Error(Loc,
4217 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
4218 case Match_AddSubRegShift64:
4219 return Error(Loc,
4220 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
4221 case Match_InvalidFPImm:
4222 return Error(Loc,
4223 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00004224 case Match_InvalidMemoryIndexedSImm6:
4225 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00004226 case Match_InvalidMemoryIndexedSImm5:
4227 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00004228 case Match_InvalidMemoryIndexed1SImm4:
4229 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00004230 case Match_InvalidMemoryIndexed2SImm4:
4231 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00004232 case Match_InvalidMemoryIndexed3SImm4:
4233 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00004234 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00004235 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004236 case Match_InvalidMemoryIndexed16SImm4:
4237 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00004238 case Match_InvalidMemoryIndexed1SImm6:
4239 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen592718f2018-07-05 07:54:10 +00004240 case Match_InvalidMemoryIndexedSImm8:
4241 return Error(Loc, "index must be an integer in range [-128, 127].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004242 case Match_InvalidMemoryIndexedSImm9:
4243 return Error(Loc, "index must be an integer in range [-256, 255].");
Oliver Stannardc4190282018-10-02 10:04:39 +00004244 case Match_InvalidMemoryIndexed16SImm9:
4245 return Error(Loc, "index must be a multiple of 16 in range [-4096, 4080].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004246 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00004247 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004248 case Match_InvalidMemoryIndexed4SImm7:
4249 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
4250 case Match_InvalidMemoryIndexed8SImm7:
4251 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
4252 case Match_InvalidMemoryIndexed16SImm7:
4253 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00004254 case Match_InvalidMemoryIndexed8UImm5:
4255 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
4256 case Match_InvalidMemoryIndexed4UImm5:
4257 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
4258 case Match_InvalidMemoryIndexed2UImm5:
4259 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00004260 case Match_InvalidMemoryIndexed8UImm6:
4261 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
Oliver Stannardc4190282018-10-02 10:04:39 +00004262 case Match_InvalidMemoryIndexed16UImm6:
4263 return Error(Loc, "index must be a multiple of 16 in range [0, 1008].");
Sander de Smalend8e76492018-05-08 10:46:55 +00004264 case Match_InvalidMemoryIndexed4UImm6:
4265 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
4266 case Match_InvalidMemoryIndexed2UImm6:
4267 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
4268 case Match_InvalidMemoryIndexed1UImm6:
4269 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004270 case Match_InvalidMemoryWExtend8:
4271 return Error(Loc,
4272 "expected 'uxtw' or 'sxtw' with optional shift of #0");
4273 case Match_InvalidMemoryWExtend16:
4274 return Error(Loc,
4275 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
4276 case Match_InvalidMemoryWExtend32:
4277 return Error(Loc,
4278 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
4279 case Match_InvalidMemoryWExtend64:
4280 return Error(Loc,
4281 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
4282 case Match_InvalidMemoryWExtend128:
4283 return Error(Loc,
4284 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
4285 case Match_InvalidMemoryXExtend8:
4286 return Error(Loc,
4287 "expected 'lsl' or 'sxtx' with optional shift of #0");
4288 case Match_InvalidMemoryXExtend16:
4289 return Error(Loc,
4290 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
4291 case Match_InvalidMemoryXExtend32:
4292 return Error(Loc,
4293 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
4294 case Match_InvalidMemoryXExtend64:
4295 return Error(Loc,
4296 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
4297 case Match_InvalidMemoryXExtend128:
4298 return Error(Loc,
4299 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
4300 case Match_InvalidMemoryIndexed1:
4301 return Error(Loc, "index must be an integer in range [0, 4095].");
4302 case Match_InvalidMemoryIndexed2:
4303 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
4304 case Match_InvalidMemoryIndexed4:
4305 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
4306 case Match_InvalidMemoryIndexed8:
4307 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
4308 case Match_InvalidMemoryIndexed16:
4309 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004310 case Match_InvalidImm0_1:
4311 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004312 case Match_InvalidImm0_7:
4313 return Error(Loc, "immediate must be an integer in range [0, 7].");
4314 case Match_InvalidImm0_15:
4315 return Error(Loc, "immediate must be an integer in range [0, 15].");
4316 case Match_InvalidImm0_31:
4317 return Error(Loc, "immediate must be an integer in range [0, 31].");
4318 case Match_InvalidImm0_63:
4319 return Error(Loc, "immediate must be an integer in range [0, 63].");
4320 case Match_InvalidImm0_127:
4321 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004322 case Match_InvalidImm0_255:
4323 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004324 case Match_InvalidImm0_65535:
4325 return Error(Loc, "immediate must be an integer in range [0, 65535].");
4326 case Match_InvalidImm1_8:
4327 return Error(Loc, "immediate must be an integer in range [1, 8].");
4328 case Match_InvalidImm1_16:
4329 return Error(Loc, "immediate must be an integer in range [1, 16].");
4330 case Match_InvalidImm1_32:
4331 return Error(Loc, "immediate must be an integer in range [1, 32].");
4332 case Match_InvalidImm1_64:
4333 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00004334 case Match_InvalidSVEAddSubImm8:
4335 return Error(Loc, "immediate must be an integer in range [0, 255]"
4336 " with a shift amount of 0");
4337 case Match_InvalidSVEAddSubImm16:
4338 case Match_InvalidSVEAddSubImm32:
4339 case Match_InvalidSVEAddSubImm64:
4340 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
4341 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004342 case Match_InvalidSVECpyImm8:
4343 return Error(Loc, "immediate must be an integer in range [-128, 255]"
4344 " with a shift amount of 0");
4345 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00004346 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4347 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004348 case Match_InvalidSVECpyImm32:
4349 case Match_InvalidSVECpyImm64:
4350 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4351 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004352 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004353 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004354 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00004355 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004356 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00004357 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004358 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004359 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004360 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004361 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004362 case Match_InvalidSVEIndexRange0_63:
4363 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4364 case Match_InvalidSVEIndexRange0_31:
4365 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4366 case Match_InvalidSVEIndexRange0_15:
4367 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4368 case Match_InvalidSVEIndexRange0_7:
4369 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4370 case Match_InvalidSVEIndexRange0_3:
4371 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004372 case Match_InvalidLabel:
4373 return Error(Loc, "expected label or encodable integer pc offset");
4374 case Match_MRS:
4375 return Error(Loc, "expected readable system register");
4376 case Match_MSR:
4377 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00004378 case Match_InvalidComplexRotationEven:
4379 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4380 case Match_InvalidComplexRotationOdd:
4381 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004382 case Match_MnemonicFail: {
4383 std::string Suggestion = AArch64MnemonicSpellCheck(
4384 ((AArch64Operand &)*Operands[0]).getToken(),
4385 ComputeAvailableFeatures(STI->getFeatureBits()));
4386 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4387 }
Sander de Smalen367694b2018-04-20 08:54:49 +00004388 case Match_InvalidGPR64shifted8:
4389 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4390 case Match_InvalidGPR64shifted16:
4391 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4392 case Match_InvalidGPR64shifted32:
4393 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4394 case Match_InvalidGPR64shifted64:
4395 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4396 case Match_InvalidGPR64NoXZRshifted8:
4397 return Error(Loc, "register must be x0..x30 without shift");
4398 case Match_InvalidGPR64NoXZRshifted16:
4399 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4400 case Match_InvalidGPR64NoXZRshifted32:
4401 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4402 case Match_InvalidGPR64NoXZRshifted64:
4403 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004404 case Match_InvalidZPR32UXTW8:
4405 case Match_InvalidZPR32SXTW8:
4406 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4407 case Match_InvalidZPR32UXTW16:
4408 case Match_InvalidZPR32SXTW16:
4409 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4410 case Match_InvalidZPR32UXTW32:
4411 case Match_InvalidZPR32SXTW32:
4412 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4413 case Match_InvalidZPR32UXTW64:
4414 case Match_InvalidZPR32SXTW64:
4415 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4416 case Match_InvalidZPR64UXTW8:
4417 case Match_InvalidZPR64SXTW8:
4418 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4419 case Match_InvalidZPR64UXTW16:
4420 case Match_InvalidZPR64SXTW16:
4421 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4422 case Match_InvalidZPR64UXTW32:
4423 case Match_InvalidZPR64SXTW32:
4424 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4425 case Match_InvalidZPR64UXTW64:
4426 case Match_InvalidZPR64SXTW64:
4427 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
Sander de Smalenc69944c2018-07-09 09:58:24 +00004428 case Match_InvalidZPR32LSL8:
4429 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s'");
4430 case Match_InvalidZPR32LSL16:
4431 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #1'");
4432 case Match_InvalidZPR32LSL32:
4433 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #2'");
4434 case Match_InvalidZPR32LSL64:
4435 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004436 case Match_InvalidZPR64LSL8:
4437 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4438 case Match_InvalidZPR64LSL16:
4439 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4440 case Match_InvalidZPR64LSL32:
4441 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4442 case Match_InvalidZPR64LSL64:
4443 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00004444 case Match_InvalidZPR0:
4445 return Error(Loc, "expected register without element width sufix");
4446 case Match_InvalidZPR8:
4447 case Match_InvalidZPR16:
4448 case Match_InvalidZPR32:
4449 case Match_InvalidZPR64:
4450 case Match_InvalidZPR128:
4451 return Error(Loc, "invalid element width");
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004452 case Match_InvalidZPR_3b8:
4453 return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b");
4454 case Match_InvalidZPR_3b16:
4455 return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h");
4456 case Match_InvalidZPR_3b32:
4457 return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s");
4458 case Match_InvalidZPR_4b16:
4459 return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h");
4460 case Match_InvalidZPR_4b32:
4461 return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s");
4462 case Match_InvalidZPR_4b64:
4463 return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004464 case Match_InvalidSVEPattern:
4465 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004466 case Match_InvalidSVEPredicateAnyReg:
4467 case Match_InvalidSVEPredicateBReg:
4468 case Match_InvalidSVEPredicateHReg:
4469 case Match_InvalidSVEPredicateSReg:
4470 case Match_InvalidSVEPredicateDReg:
4471 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004472 case Match_InvalidSVEPredicate3bAnyReg:
4473 case Match_InvalidSVEPredicate3bBReg:
4474 case Match_InvalidSVEPredicate3bHReg:
4475 case Match_InvalidSVEPredicate3bSReg:
4476 case Match_InvalidSVEPredicate3bDReg:
4477 return Error(Loc, "restricted predicate has range [0, 7].");
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004478 case Match_InvalidSVEExactFPImmOperandHalfOne:
4479 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4480 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4481 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4482 case Match_InvalidSVEExactFPImmOperandZeroOne:
4483 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004484 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004485 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004486 }
4487}
4488
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004489static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004490
4491bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4492 OperandVector &Operands,
4493 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004494 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004495 bool MatchingInlineAsm) {
4496 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004497 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4498 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004499
David Blaikie960ea3f2014-06-08 16:18:35 +00004500 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004501 unsigned NumOperands = Operands.size();
4502
4503 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004504 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4505 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004506 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004507 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004508 if (Op3CE) {
4509 uint64_t Op3Val = Op3CE->getValue();
4510 uint64_t NewOp3Val = 0;
4511 uint64_t NewOp4Val = 0;
4512 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004513 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004514 NewOp3Val = (32 - Op3Val) & 0x1f;
4515 NewOp4Val = 31 - Op3Val;
4516 } else {
4517 NewOp3Val = (64 - Op3Val) & 0x3f;
4518 NewOp4Val = 63 - Op3Val;
4519 }
4520
Jim Grosbach13760bd2015-05-30 01:25:56 +00004521 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4522 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004523
4524 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004525 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004526 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004527 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4528 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4529 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004530 }
4531 }
Tim Northover03b99f62015-04-30 18:28:58 +00004532 } else if (NumOperands == 4 && Tok == "bfc") {
4533 // FIXME: Horrible hack to handle BFC->BFM alias.
4534 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4535 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4536 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4537
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004538 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004539 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4540 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4541
4542 if (LSBCE && WidthCE) {
4543 uint64_t LSB = LSBCE->getValue();
4544 uint64_t Width = WidthCE->getValue();
4545
4546 uint64_t RegWidth = 0;
4547 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4548 Op1.getReg()))
4549 RegWidth = 64;
4550 else
4551 RegWidth = 32;
4552
4553 if (LSB >= RegWidth)
4554 return Error(LSBOp.getStartLoc(),
4555 "expected integer in range [0, 31]");
4556 if (Width < 1 || Width > RegWidth)
4557 return Error(WidthOp.getStartLoc(),
4558 "expected integer in range [1, 32]");
4559
4560 uint64_t ImmR = 0;
4561 if (RegWidth == 32)
4562 ImmR = (32 - LSB) & 0x1f;
4563 else
4564 ImmR = (64 - LSB) & 0x3f;
4565
4566 uint64_t ImmS = Width - 1;
4567
4568 if (ImmR != 0 && ImmS >= ImmR)
4569 return Error(WidthOp.getStartLoc(),
4570 "requested insert overflows register");
4571
Jim Grosbach13760bd2015-05-30 01:25:56 +00004572 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4573 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004574 Operands[0] = AArch64Operand::CreateToken(
4575 "bfm", false, Op.getStartLoc(), getContext());
4576 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004577 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4578 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004579 Operands[3] = AArch64Operand::CreateImm(
4580 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4581 Operands.emplace_back(
4582 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4583 WidthOp.getEndLoc(), getContext()));
4584 }
4585 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004586 } else if (NumOperands == 5) {
4587 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4588 // UBFIZ -> UBFM aliases.
4589 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004590 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4591 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4592 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004593
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004594 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004595 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4596 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004597
4598 if (Op3CE && Op4CE) {
4599 uint64_t Op3Val = Op3CE->getValue();
4600 uint64_t Op4Val = Op4CE->getValue();
4601
4602 uint64_t RegWidth = 0;
4603 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004604 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004605 RegWidth = 64;
4606 else
4607 RegWidth = 32;
4608
4609 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004610 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004611 "expected integer in range [0, 31]");
4612 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004613 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004614 "expected integer in range [1, 32]");
4615
4616 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004617 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004618 NewOp3Val = (32 - Op3Val) & 0x1f;
4619 else
4620 NewOp3Val = (64 - Op3Val) & 0x3f;
4621
4622 uint64_t NewOp4Val = Op4Val - 1;
4623
4624 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004625 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004626 "requested insert overflows register");
4627
4628 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004629 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004630 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004631 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004632 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004633 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004634 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004635 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004636 if (Tok == "bfi")
4637 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004638 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004639 else if (Tok == "sbfiz")
4640 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004641 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004642 else if (Tok == "ubfiz")
4643 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004644 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004645 else
4646 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004647 }
4648 }
4649
4650 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4651 // UBFX -> UBFM aliases.
4652 } else if (NumOperands == 5 &&
4653 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004654 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4655 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4656 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004657
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004658 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004659 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4660 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004661
4662 if (Op3CE && Op4CE) {
4663 uint64_t Op3Val = Op3CE->getValue();
4664 uint64_t Op4Val = Op4CE->getValue();
4665
4666 uint64_t RegWidth = 0;
4667 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004668 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004669 RegWidth = 64;
4670 else
4671 RegWidth = 32;
4672
4673 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004674 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004675 "expected integer in range [0, 31]");
4676 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004677 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004678 "expected integer in range [1, 32]");
4679
4680 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4681
4682 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004683 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004684 "requested extract overflows register");
4685
4686 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004687 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004688 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004689 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004690 if (Tok == "bfxil")
4691 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004692 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004693 else if (Tok == "sbfx")
4694 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004695 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004696 else if (Tok == "ubfx")
4697 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004698 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004699 else
4700 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004701 }
4702 }
4703 }
4704 }
Tim Northover9097a072017-12-18 10:36:00 +00004705
4706 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4707 // instruction for FP registers correctly in some rare circumstances. Convert
4708 // it to a safe instruction and warn (because silently changing someone's
4709 // assembly is rude).
4710 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4711 NumOperands == 4 && Tok == "movi") {
4712 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4713 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4714 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4715 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4716 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4717 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4718 if (Suffix.lower() == ".2d" &&
4719 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4720 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4721 " correctly on this CPU, converting to equivalent movi.16b");
4722 // Switch the suffix to .16b.
4723 unsigned Idx = Op1.isToken() ? 1 : 2;
4724 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4725 getContext());
4726 }
4727 }
4728 }
4729
Tim Northover3b0846e2014-05-24 12:50:23 +00004730 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4731 // InstAlias can't quite handle this since the reg classes aren't
4732 // subclasses.
4733 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4734 // The source register can be Wn here, but the matcher expects a
4735 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004736 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004737 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004738 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004739 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4740 Op.getStartLoc(), Op.getEndLoc(),
4741 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004742 }
4743 }
4744 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4745 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004746 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004747 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004748 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004749 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004750 // The source register can be Wn here, but the matcher expects a
4751 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004752 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004753 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004754 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004755 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4756 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004757 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004758 }
4759 }
4760 }
4761 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4762 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004763 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004764 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004765 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004766 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004767 // The source register can be Wn here, but the matcher expects a
4768 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004769 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004770 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004771 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004772 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4773 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004774 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004775 }
4776 }
4777 }
4778
Tim Northover3b0846e2014-05-24 12:50:23 +00004779 MCInst Inst;
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004780 FeatureBitset MissingFeatures;
Tim Northover3b0846e2014-05-24 12:50:23 +00004781 // First try to match against the secondary set of tables containing the
4782 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4783 unsigned MatchResult =
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004784 MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
4785 MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004786
4787 // If that fails, try against the alternate table containing long-form NEON:
4788 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004789 if (MatchResult != Match_Success) {
4790 // But first, save the short-form match result: we can use it in case the
4791 // long-form match also fails.
4792 auto ShortFormNEONErrorInfo = ErrorInfo;
4793 auto ShortFormNEONMatchResult = MatchResult;
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004794 auto ShortFormNEONMissingFeatures = MissingFeatures;
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004795
Tim Northover3b0846e2014-05-24 12:50:23 +00004796 MatchResult =
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004797 MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
4798 MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004799
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004800 // Now, both matches failed, and the long-form match failed on the mnemonic
4801 // suffix token operand. The short-form match failure is probably more
4802 // relevant: use it instead.
4803 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004804 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004805 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4806 MatchResult = ShortFormNEONMatchResult;
4807 ErrorInfo = ShortFormNEONErrorInfo;
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004808 MissingFeatures = ShortFormNEONMissingFeatures;
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004809 }
4810 }
4811
Tim Northover3b0846e2014-05-24 12:50:23 +00004812 switch (MatchResult) {
4813 case Match_Success: {
4814 // Perform range checking and other semantic validations
4815 SmallVector<SMLoc, 8> OperandLocs;
4816 NumOperands = Operands.size();
4817 for (unsigned i = 1; i < NumOperands; ++i)
4818 OperandLocs.push_back(Operands[i]->getStartLoc());
Sander de Smalen9b333092018-07-30 15:42:46 +00004819 if (validateInstruction(Inst, IDLoc, OperandLocs))
Tim Northover3b0846e2014-05-24 12:50:23 +00004820 return true;
4821
4822 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004823 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004824 return false;
4825 }
4826 case Match_MissingFeature: {
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004827 assert(MissingFeatures.any() && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004828 // Special case the error message for the very common case where only
4829 // a single subtarget feature is missing (neon, e.g.).
4830 std::string Msg = "instruction requires:";
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004831 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
4832 if (MissingFeatures[i]) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004833 Msg += " ";
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004834 Msg += getSubtargetFeatureName(i);
Tim Northover3b0846e2014-05-24 12:50:23 +00004835 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004836 }
4837 return Error(IDLoc, Msg);
4838 }
4839 case Match_MnemonicFail:
Sander de Smalen0325e302018-07-02 07:34:52 +00004840 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004841 case Match_InvalidOperand: {
4842 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004843
Tim Northover26bb14e2014-08-18 11:49:42 +00004844 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004845 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004846 return Error(IDLoc, "too few operands for instruction",
4847 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004848
David Blaikie960ea3f2014-06-08 16:18:35 +00004849 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004850 if (ErrorLoc == SMLoc())
4851 ErrorLoc = IDLoc;
4852 }
4853 // If the match failed on a suffix token operand, tweak the diagnostic
4854 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004855 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4856 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004857 MatchResult = Match_InvalidSuffix;
4858
Sander de Smalen0325e302018-07-02 07:34:52 +00004859 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004860 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004861 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004862 case Match_InvalidMemoryIndexed1:
4863 case Match_InvalidMemoryIndexed2:
4864 case Match_InvalidMemoryIndexed4:
4865 case Match_InvalidMemoryIndexed8:
4866 case Match_InvalidMemoryIndexed16:
4867 case Match_InvalidCondCode:
4868 case Match_AddSubRegExtendSmall:
4869 case Match_AddSubRegExtendLarge:
4870 case Match_AddSubSecondSource:
4871 case Match_LogicalSecondSource:
4872 case Match_AddSubRegShift32:
4873 case Match_AddSubRegShift64:
4874 case Match_InvalidMovImm32Shift:
4875 case Match_InvalidMovImm64Shift:
4876 case Match_InvalidFPImm:
4877 case Match_InvalidMemoryWExtend8:
4878 case Match_InvalidMemoryWExtend16:
4879 case Match_InvalidMemoryWExtend32:
4880 case Match_InvalidMemoryWExtend64:
4881 case Match_InvalidMemoryWExtend128:
4882 case Match_InvalidMemoryXExtend8:
4883 case Match_InvalidMemoryXExtend16:
4884 case Match_InvalidMemoryXExtend32:
4885 case Match_InvalidMemoryXExtend64:
4886 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004887 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004888 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004889 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004890 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004891 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004892 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004893 case Match_InvalidMemoryIndexed4SImm7:
4894 case Match_InvalidMemoryIndexed8SImm7:
4895 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004896 case Match_InvalidMemoryIndexed8UImm5:
4897 case Match_InvalidMemoryIndexed4UImm5:
4898 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004899 case Match_InvalidMemoryIndexed1UImm6:
4900 case Match_InvalidMemoryIndexed2UImm6:
4901 case Match_InvalidMemoryIndexed4UImm6:
4902 case Match_InvalidMemoryIndexed8UImm6:
Oliver Stannardc4190282018-10-02 10:04:39 +00004903 case Match_InvalidMemoryIndexed16UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004904 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004905 case Match_InvalidMemoryIndexedSImm5:
Sander de Smalen592718f2018-07-05 07:54:10 +00004906 case Match_InvalidMemoryIndexedSImm8:
Tim Northover3b0846e2014-05-24 12:50:23 +00004907 case Match_InvalidMemoryIndexedSImm9:
Oliver Stannardc4190282018-10-02 10:04:39 +00004908 case Match_InvalidMemoryIndexed16SImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004909 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004910 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004911 case Match_InvalidImm0_7:
4912 case Match_InvalidImm0_15:
4913 case Match_InvalidImm0_31:
4914 case Match_InvalidImm0_63:
4915 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004916 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004917 case Match_InvalidImm0_65535:
4918 case Match_InvalidImm1_8:
4919 case Match_InvalidImm1_16:
4920 case Match_InvalidImm1_32:
4921 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004922 case Match_InvalidSVEAddSubImm8:
4923 case Match_InvalidSVEAddSubImm16:
4924 case Match_InvalidSVEAddSubImm32:
4925 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004926 case Match_InvalidSVECpyImm8:
4927 case Match_InvalidSVECpyImm16:
4928 case Match_InvalidSVECpyImm32:
4929 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004930 case Match_InvalidIndexRange1_1:
4931 case Match_InvalidIndexRange0_15:
4932 case Match_InvalidIndexRange0_7:
4933 case Match_InvalidIndexRange0_3:
4934 case Match_InvalidIndexRange0_1:
4935 case Match_InvalidSVEIndexRange0_63:
4936 case Match_InvalidSVEIndexRange0_31:
4937 case Match_InvalidSVEIndexRange0_15:
4938 case Match_InvalidSVEIndexRange0_7:
4939 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004940 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004941 case Match_InvalidComplexRotationEven:
4942 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004943 case Match_InvalidGPR64shifted8:
4944 case Match_InvalidGPR64shifted16:
4945 case Match_InvalidGPR64shifted32:
4946 case Match_InvalidGPR64shifted64:
4947 case Match_InvalidGPR64NoXZRshifted8:
4948 case Match_InvalidGPR64NoXZRshifted16:
4949 case Match_InvalidGPR64NoXZRshifted32:
4950 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004951 case Match_InvalidZPR32UXTW8:
4952 case Match_InvalidZPR32UXTW16:
4953 case Match_InvalidZPR32UXTW32:
4954 case Match_InvalidZPR32UXTW64:
4955 case Match_InvalidZPR32SXTW8:
4956 case Match_InvalidZPR32SXTW16:
4957 case Match_InvalidZPR32SXTW32:
4958 case Match_InvalidZPR32SXTW64:
4959 case Match_InvalidZPR64UXTW8:
4960 case Match_InvalidZPR64SXTW8:
4961 case Match_InvalidZPR64UXTW16:
4962 case Match_InvalidZPR64SXTW16:
4963 case Match_InvalidZPR64UXTW32:
4964 case Match_InvalidZPR64SXTW32:
4965 case Match_InvalidZPR64UXTW64:
4966 case Match_InvalidZPR64SXTW64:
Sander de Smalenc69944c2018-07-09 09:58:24 +00004967 case Match_InvalidZPR32LSL8:
4968 case Match_InvalidZPR32LSL16:
4969 case Match_InvalidZPR32LSL32:
4970 case Match_InvalidZPR32LSL64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004971 case Match_InvalidZPR64LSL8:
4972 case Match_InvalidZPR64LSL16:
4973 case Match_InvalidZPR64LSL32:
4974 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004975 case Match_InvalidZPR0:
4976 case Match_InvalidZPR8:
4977 case Match_InvalidZPR16:
4978 case Match_InvalidZPR32:
4979 case Match_InvalidZPR64:
4980 case Match_InvalidZPR128:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004981 case Match_InvalidZPR_3b8:
4982 case Match_InvalidZPR_3b16:
4983 case Match_InvalidZPR_3b32:
4984 case Match_InvalidZPR_4b16:
4985 case Match_InvalidZPR_4b32:
4986 case Match_InvalidZPR_4b64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004987 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004988 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004989 case Match_InvalidSVEPredicateBReg:
4990 case Match_InvalidSVEPredicateHReg:
4991 case Match_InvalidSVEPredicateSReg:
4992 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004993 case Match_InvalidSVEPredicate3bAnyReg:
4994 case Match_InvalidSVEPredicate3bBReg:
4995 case Match_InvalidSVEPredicate3bHReg:
4996 case Match_InvalidSVEPredicate3bSReg:
4997 case Match_InvalidSVEPredicate3bDReg:
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004998 case Match_InvalidSVEExactFPImmOperandHalfOne:
4999 case Match_InvalidSVEExactFPImmOperandHalfTwo:
5000 case Match_InvalidSVEExactFPImmOperandZeroOne:
Tim Northover3b0846e2014-05-24 12:50:23 +00005001 case Match_MSR:
5002 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00005003 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00005004 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00005005 // Any time we get here, there's nothing fancy to do. Just get the
5006 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00005007 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00005008 if (ErrorLoc == SMLoc())
5009 ErrorLoc = IDLoc;
Sander de Smalen0325e302018-07-02 07:34:52 +00005010 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00005011 }
5012 }
5013
5014 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00005015}
5016
5017/// ParseDirective parses the arm specific directives
5018bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00005019 const MCObjectFileInfo::Environment Format =
5020 getContext().getObjectFileInfo()->getObjectFileType();
5021 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005022
Tim Northover3b0846e2014-05-24 12:50:23 +00005023 StringRef IDVal = DirectiveID.getIdentifier();
5024 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005025 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00005026 parseDirectiveArch(Loc);
5027 else if (IDVal == ".cpu")
5028 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00005029 else if (IDVal == ".tlsdesccall")
5030 parseDirectiveTLSDescCall(Loc);
5031 else if (IDVal == ".ltorg" || IDVal == ".pool")
5032 parseDirectiveLtorg(Loc);
5033 else if (IDVal == ".unreq")
5034 parseDirectiveUnreq(Loc);
Martin Storsjo3e3d39d2018-07-31 09:26:52 +00005035 else if (IDVal == ".inst")
5036 parseDirectiveInst(Loc);
Luke Cheesemanf57d7d82018-12-18 10:37:42 +00005037 else if (IDVal == ".cfi_negate_ra_state")
5038 parseDirectiveCFINegateRAState();
Luke Cheeseman41a9e532018-12-21 10:45:08 +00005039 else if (IDVal == ".cfi_b_key_frame")
5040 parseDirectiveCFIBKeyFrame();
Martin Storsjo20187772018-12-30 21:06:32 +00005041 else if (IDVal == ".arch_extension")
5042 parseDirectiveArchExtension(Loc);
Martin Storsjod4590c32018-08-01 06:50:18 +00005043 else if (IsMachO) {
5044 if (IDVal == MCLOHDirectiveName())
5045 parseDirectiveLOH(IDVal, Loc);
5046 else
5047 return true;
5048 } else
Nirav Davee833c6c2016-11-08 18:31:04 +00005049 return true;
5050 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00005051}
5052
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005053static void ExpandCryptoAEK(AArch64::ArchKind ArchKind,
5054 SmallVector<StringRef, 4> &RequestedExtensions) {
5055 const bool NoCrypto =
5056 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
5057 "nocrypto") != std::end(RequestedExtensions));
5058 const bool Crypto =
5059 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
5060 "crypto") != std::end(RequestedExtensions));
5061
5062 if (!NoCrypto && Crypto) {
5063 switch (ArchKind) {
5064 default:
5065 // Map 'generic' (and others) to sha2 and aes, because
5066 // that was the traditional meaning of crypto.
5067 case AArch64::ArchKind::ARMV8_1A:
5068 case AArch64::ArchKind::ARMV8_2A:
5069 case AArch64::ArchKind::ARMV8_3A:
5070 RequestedExtensions.push_back("sha2");
5071 RequestedExtensions.push_back("aes");
5072 break;
5073 case AArch64::ArchKind::ARMV8_4A:
Oliver Stannard7c3c4ba2018-09-26 12:48:21 +00005074 case AArch64::ArchKind::ARMV8_5A:
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005075 RequestedExtensions.push_back("sm4");
5076 RequestedExtensions.push_back("sha3");
5077 RequestedExtensions.push_back("sha2");
5078 RequestedExtensions.push_back("aes");
5079 break;
5080 }
5081 } else if (NoCrypto) {
5082 switch (ArchKind) {
5083 default:
5084 // Map 'generic' (and others) to sha2 and aes, because
5085 // that was the traditional meaning of crypto.
5086 case AArch64::ArchKind::ARMV8_1A:
5087 case AArch64::ArchKind::ARMV8_2A:
5088 case AArch64::ArchKind::ARMV8_3A:
5089 RequestedExtensions.push_back("nosha2");
5090 RequestedExtensions.push_back("noaes");
5091 break;
5092 case AArch64::ArchKind::ARMV8_4A:
Oliver Stannard7c3c4ba2018-09-26 12:48:21 +00005093 case AArch64::ArchKind::ARMV8_5A:
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005094 RequestedExtensions.push_back("nosm4");
5095 RequestedExtensions.push_back("nosha3");
5096 RequestedExtensions.push_back("nosha2");
5097 RequestedExtensions.push_back("noaes");
5098 break;
5099 }
5100 }
5101}
5102
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005103/// parseDirectiveArch
5104/// ::= .arch token
5105bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
5106 SMLoc ArchLoc = getLoc();
5107
5108 StringRef Arch, ExtensionString;
5109 std::tie(Arch, ExtensionString) =
5110 getParser().parseStringToEndOfStatement().trim().split('+');
5111
Florian Hahn67ddd1d2017-07-27 16:27:56 +00005112 AArch64::ArchKind ID = AArch64::parseArch(Arch);
5113 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00005114 return Error(ArchLoc, "unknown arch name");
5115
5116 if (parseToken(AsmToken::EndOfStatement))
5117 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005118
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005119 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00005120 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005121 AArch64::getArchFeatures(ID, AArch64Features);
5122 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
5123 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005124
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005125 MCSubtargetInfo &STI = copySTI();
5126 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
5127 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
5128
5129 SmallVector<StringRef, 4> RequestedExtensions;
5130 if (!ExtensionString.empty())
5131 ExtensionString.split(RequestedExtensions, '+');
5132
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005133 ExpandCryptoAEK(ID, RequestedExtensions);
5134
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005135 FeatureBitset Features = STI.getFeatureBits();
5136 for (auto Name : RequestedExtensions) {
5137 bool EnableFeature = true;
5138
5139 if (Name.startswith_lower("no")) {
5140 EnableFeature = false;
5141 Name = Name.substr(2);
5142 }
5143
5144 for (const auto &Extension : ExtensionMap) {
5145 if (Extension.Name != Name)
5146 continue;
5147
5148 if (Extension.Features.none())
5149 report_fatal_error("unsupported architectural extension: " + Name);
5150
5151 FeatureBitset ToggleFeatures = EnableFeature
5152 ? (~Features & Extension.Features)
5153 : ( Features & Extension.Features);
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00005154 FeatureBitset Features =
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005155 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5156 setAvailableFeatures(Features);
5157 break;
5158 }
5159 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005160 return false;
5161}
5162
Martin Storsjo20187772018-12-30 21:06:32 +00005163/// parseDirectiveArchExtension
5164/// ::= .arch_extension [no]feature
5165bool AArch64AsmParser::parseDirectiveArchExtension(SMLoc L) {
5166 MCAsmParser &Parser = getParser();
5167
5168 if (getLexer().isNot(AsmToken::Identifier))
5169 return Error(getLexer().getLoc(), "expected architecture extension name");
5170
5171 const AsmToken &Tok = Parser.getTok();
5172 StringRef Name = Tok.getString();
5173 SMLoc ExtLoc = Tok.getLoc();
5174 Lex();
5175
5176 if (parseToken(AsmToken::EndOfStatement,
5177 "unexpected token in '.arch_extension' directive"))
5178 return true;
5179
5180 bool EnableFeature = true;
5181 if (Name.startswith_lower("no")) {
5182 EnableFeature = false;
5183 Name = Name.substr(2);
5184 }
5185
5186 MCSubtargetInfo &STI = copySTI();
5187 FeatureBitset Features = STI.getFeatureBits();
5188 for (const auto &Extension : ExtensionMap) {
5189 if (Extension.Name != Name)
5190 continue;
5191
5192 if (Extension.Features.none())
5193 return Error(ExtLoc, "unsupported architectural extension: " + Name);
5194
5195 FeatureBitset ToggleFeatures = EnableFeature
5196 ? (~Features & Extension.Features)
5197 : (Features & Extension.Features);
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00005198 FeatureBitset Features =
Martin Storsjo20187772018-12-30 21:06:32 +00005199 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5200 setAvailableFeatures(Features);
5201 return false;
5202 }
5203
5204 return Error(ExtLoc, "unknown architectural extension: " + Name);
5205}
5206
Tim Northover8b96c7e2017-05-15 19:42:15 +00005207static SMLoc incrementLoc(SMLoc L, int Offset) {
5208 return SMLoc::getFromPointer(L.getPointer() + Offset);
5209}
5210
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005211/// parseDirectiveCPU
5212/// ::= .cpu id
5213bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005214 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005215
5216 StringRef CPU, ExtensionString;
5217 std::tie(CPU, ExtensionString) =
5218 getParser().parseStringToEndOfStatement().trim().split('+');
5219
Nirav Davee833c6c2016-11-08 18:31:04 +00005220 if (parseToken(AsmToken::EndOfStatement))
5221 return true;
5222
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005223 SmallVector<StringRef, 4> RequestedExtensions;
5224 if (!ExtensionString.empty())
5225 ExtensionString.split(RequestedExtensions, '+');
5226
5227 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
5228 // once that is tablegen'ed
5229 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005230 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005231 return false;
5232 }
5233
5234 MCSubtargetInfo &STI = copySTI();
5235 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00005236 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005237
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005238 ExpandCryptoAEK(llvm::AArch64::getCPUArchKind(CPU), RequestedExtensions);
5239
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005240 FeatureBitset Features = STI.getFeatureBits();
5241 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005242 // Advance source location past '+'.
5243 CurLoc = incrementLoc(CurLoc, 1);
5244
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005245 bool EnableFeature = true;
5246
5247 if (Name.startswith_lower("no")) {
5248 EnableFeature = false;
5249 Name = Name.substr(2);
5250 }
5251
Tim Northover8b96c7e2017-05-15 19:42:15 +00005252 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005253 for (const auto &Extension : ExtensionMap) {
5254 if (Extension.Name != Name)
5255 continue;
5256
5257 if (Extension.Features.none())
5258 report_fatal_error("unsupported architectural extension: " + Name);
5259
5260 FeatureBitset ToggleFeatures = EnableFeature
5261 ? (~Features & Extension.Features)
5262 : ( Features & Extension.Features);
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00005263 FeatureBitset Features =
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005264 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5265 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00005266 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005267
5268 break;
5269 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00005270
5271 if (!FoundExtension)
5272 Error(CurLoc, "unsupported architectural extension");
5273
5274 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005275 }
5276 return false;
5277}
5278
Chad Rosierdcd2a302014-10-22 20:35:57 +00005279/// parseDirectiveInst
5280/// ::= .inst opcode [, ...]
5281bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005282 if (getLexer().is(AsmToken::EndOfStatement))
5283 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005284
Nirav Davee833c6c2016-11-08 18:31:04 +00005285 auto parseOp = [&]() -> bool {
5286 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00005287 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00005288 if (check(getParser().parseExpression(Expr), L, "expected expression"))
5289 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005290 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00005291 if (check(!Value, L, "expected constant expression"))
5292 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005293 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00005294 return false;
5295 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00005296
Nirav Davee833c6c2016-11-08 18:31:04 +00005297 if (parseMany(parseOp))
5298 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005299 return false;
5300}
5301
Tim Northover3b0846e2014-05-24 12:50:23 +00005302// parseDirectiveTLSDescCall:
5303// ::= .tlsdesccall symbol
5304bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
5305 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00005306 if (check(getParser().parseIdentifier(Name), L,
5307 "expected symbol after directive") ||
5308 parseToken(AsmToken::EndOfStatement))
5309 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005310
Jim Grosbach6f482002015-05-18 18:43:14 +00005311 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00005312 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
5313 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00005314
5315 MCInst Inst;
5316 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00005317 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00005318
Akira Hatanakabd9fc282015-11-14 05:20:05 +00005319 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00005320 return false;
5321}
5322
5323/// ::= .loh <lohName | lohId> label1, ..., labelN
5324/// The number of arguments depends on the loh identifier.
5325bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00005326 MCLOHType Kind;
5327 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5328 if (getParser().getTok().isNot(AsmToken::Integer))
5329 return TokError("expected an identifier or a number in directive");
5330 // We successfully get a numeric value for the identifier.
5331 // Check if it is valid.
5332 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00005333 if (Id <= -1U && !isValidMCLOHType(Id))
5334 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00005335 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00005336 } else {
5337 StringRef Name = getTok().getIdentifier();
5338 // We successfully parse an identifier.
5339 // Check if it is a recognized one.
5340 int Id = MCLOHNameToId(Name);
5341
5342 if (Id == -1)
5343 return TokError("invalid identifier in directive");
5344 Kind = (MCLOHType)Id;
5345 }
5346 // Consume the identifier.
5347 Lex();
5348 // Get the number of arguments of this LOH.
5349 int NbArgs = MCLOHIdToNbArgs(Kind);
5350
5351 assert(NbArgs != -1 && "Invalid number of arguments");
5352
5353 SmallVector<MCSymbol *, 3> Args;
5354 for (int Idx = 0; Idx < NbArgs; ++Idx) {
5355 StringRef Name;
5356 if (getParser().parseIdentifier(Name))
5357 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00005358 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00005359
5360 if (Idx + 1 == NbArgs)
5361 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00005362 if (parseToken(AsmToken::Comma,
5363 "unexpected token in '" + Twine(IDVal) + "' directive"))
5364 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005365 }
Nirav Davee833c6c2016-11-08 18:31:04 +00005366 if (parseToken(AsmToken::EndOfStatement,
5367 "unexpected token in '" + Twine(IDVal) + "' directive"))
5368 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005369
5370 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
5371 return false;
5372}
5373
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005374/// parseDirectiveLtorg
5375/// ::= .ltorg | .pool
5376bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005377 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5378 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005379 getTargetStreamer().emitCurrentConstantPool();
5380 return false;
5381}
5382
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005383/// parseDirectiveReq
5384/// ::= name .req registername
5385bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005386 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005387 Parser.Lex(); // Eat the '.req' token.
5388 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00005389 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00005390 unsigned RegNum;
5391 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005392
Sander de Smalen50d87022018-04-19 07:35:08 +00005393 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005394 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00005395 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005396 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00005397
Sander de Smalen50d87022018-04-19 07:35:08 +00005398 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00005399 return true;
5400
Sander de Smalen50d87022018-04-19 07:35:08 +00005401 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00005402 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005403 }
5404
Sander de Smalen50d87022018-04-19 07:35:08 +00005405 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005406 StringRef Kind;
5407 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005408 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00005409 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005410
Sander de Smalen50d87022018-04-19 07:35:08 +00005411 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00005412 return true;
5413
Sander de Smalen50d87022018-04-19 07:35:08 +00005414 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00005415 return Error(SRegLoc,
5416 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00005417 }
5418
Sander de Smalen50d87022018-04-19 07:35:08 +00005419 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00005420 StringRef Kind;
5421 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005422 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00005423
Sander de Smalen50d87022018-04-19 07:35:08 +00005424 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00005425 return true;
5426
Sander de Smalen50d87022018-04-19 07:35:08 +00005427 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00005428 return Error(SRegLoc,
5429 "sve predicate register without type specifier expected");
5430 }
5431
Sander de Smalen50d87022018-04-19 07:35:08 +00005432 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00005433 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005434
5435 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00005436 if (parseToken(AsmToken::EndOfStatement,
5437 "unexpected input in .req directive"))
5438 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005439
Sander de Smalen8e607342017-11-15 15:44:43 +00005440 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00005441 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005442 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
5443
Nirav Dave2364748a2016-09-16 18:30:20 +00005444 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005445}
5446
5447/// parseDirectiveUneq
5448/// ::= .unreq registername
5449bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005450 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00005451 if (getTok().isNot(AsmToken::Identifier))
5452 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005453 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
5454 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00005455 if (parseToken(AsmToken::EndOfStatement))
5456 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005457 return false;
5458}
5459
Luke Cheesemanf57d7d82018-12-18 10:37:42 +00005460bool AArch64AsmParser::parseDirectiveCFINegateRAState() {
5461 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5462 return true;
5463 getStreamer().EmitCFINegateRAState();
5464 return false;
5465}
5466
Luke Cheeseman41a9e532018-12-21 10:45:08 +00005467/// parseDirectiveCFIBKeyFrame
5468/// ::= .cfi_b_key
5469bool AArch64AsmParser::parseDirectiveCFIBKeyFrame() {
5470 if (parseToken(AsmToken::EndOfStatement,
5471 "unexpected token in '.cfi_b_key_frame'"))
5472 return true;
5473 getStreamer().EmitCFIBKeyFrame();
5474 return false;
5475}
5476
Tim Northover3b0846e2014-05-24 12:50:23 +00005477bool
5478AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
5479 AArch64MCExpr::VariantKind &ELFRefKind,
5480 MCSymbolRefExpr::VariantKind &DarwinRefKind,
5481 int64_t &Addend) {
5482 ELFRefKind = AArch64MCExpr::VK_INVALID;
5483 DarwinRefKind = MCSymbolRefExpr::VK_None;
5484 Addend = 0;
5485
5486 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5487 ELFRefKind = AE->getKind();
5488 Expr = AE->getSubExpr();
5489 }
5490
5491 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5492 if (SE) {
5493 // It's a simple symbol reference with no addend.
5494 DarwinRefKind = SE->getKind();
5495 return true;
5496 }
5497
David Green85d6a552018-09-18 09:44:53 +00005498 // Check that it looks like a symbol + an addend
5499 MCValue Res;
5500 bool Relocatable = Expr->evaluateAsRelocatable(Res, nullptr, nullptr);
Eli Friedman48397102018-12-20 19:46:14 +00005501 if (!Relocatable || Res.getSymB())
Tim Northover3b0846e2014-05-24 12:50:23 +00005502 return false;
5503
Eli Friedman48397102018-12-20 19:46:14 +00005504 // Treat expressions with an ELFRefKind (like ":abs_g1:3", or
5505 // ":abs_g1:x" where x is constant) as symbolic even if there is no symbol.
5506 if (!Res.getSymA() && ELFRefKind == AArch64MCExpr::VK_INVALID)
5507 return false;
5508
5509 if (Res.getSymA())
5510 DarwinRefKind = Res.getSymA()->getKind();
David Green85d6a552018-09-18 09:44:53 +00005511 Addend = Res.getConstant();
Tim Northover3b0846e2014-05-24 12:50:23 +00005512
5513 // It's some symbol reference + a constant addend, but really
5514 // shouldn't use both Darwin and ELF syntax.
5515 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5516 DarwinRefKind == MCSymbolRefExpr::VK_None;
5517}
5518
5519/// Force static initialization.
5520extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00005521 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5522 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5523 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00005524}
5525
5526#define GET_REGISTER_MATCHER
5527#define GET_SUBTARGET_FEATURE_NAME
5528#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00005529#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00005530#include "AArch64GenAsmMatcher.inc"
5531
5532// Define this matcher function after the auto-generated include so we
5533// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00005534unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00005535 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005536 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00005537 // If the kind is a token for a literal immediate, check if our asm
5538 // operand matches. This is for InstAliases which have a fixed-value
5539 // immediate in the syntax.
5540 int64_t ExpectedVal;
5541 switch (Kind) {
5542 default:
5543 return Match_InvalidOperand;
5544 case MCK__35_0:
5545 ExpectedVal = 0;
5546 break;
5547 case MCK__35_1:
5548 ExpectedVal = 1;
5549 break;
5550 case MCK__35_12:
5551 ExpectedVal = 12;
5552 break;
5553 case MCK__35_16:
5554 ExpectedVal = 16;
5555 break;
5556 case MCK__35_2:
5557 ExpectedVal = 2;
5558 break;
5559 case MCK__35_24:
5560 ExpectedVal = 24;
5561 break;
5562 case MCK__35_3:
5563 ExpectedVal = 3;
5564 break;
5565 case MCK__35_32:
5566 ExpectedVal = 32;
5567 break;
5568 case MCK__35_4:
5569 ExpectedVal = 4;
5570 break;
5571 case MCK__35_48:
5572 ExpectedVal = 48;
5573 break;
5574 case MCK__35_6:
5575 ExpectedVal = 6;
5576 break;
5577 case MCK__35_64:
5578 ExpectedVal = 64;
5579 break;
5580 case MCK__35_8:
5581 ExpectedVal = 8;
5582 break;
5583 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005584 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005585 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005586 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005587 if (!CE)
5588 return Match_InvalidOperand;
5589 if (CE->getValue() == ExpectedVal)
5590 return Match_Success;
5591 return Match_InvalidOperand;
5592}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005593
Alex Bradbury58eba092016-11-01 16:32:05 +00005594OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005595AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5596
5597 SMLoc S = getLoc();
5598
5599 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5600 Error(S, "expected register");
5601 return MatchOperand_ParseFail;
5602 }
5603
Sander de Smalen50d87022018-04-19 07:35:08 +00005604 unsigned FirstReg;
5605 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5606 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005607 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005608
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005609 const MCRegisterClass &WRegClass =
5610 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5611 const MCRegisterClass &XRegClass =
5612 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5613
5614 bool isXReg = XRegClass.contains(FirstReg),
5615 isWReg = WRegClass.contains(FirstReg);
5616 if (!isXReg && !isWReg) {
5617 Error(S, "expected first even register of a "
5618 "consecutive same-size even/odd register pair");
5619 return MatchOperand_ParseFail;
5620 }
5621
5622 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5623 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5624
5625 if (FirstEncoding & 0x1) {
5626 Error(S, "expected first even register of a "
5627 "consecutive same-size even/odd register pair");
5628 return MatchOperand_ParseFail;
5629 }
5630
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005631 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005632 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005633 return MatchOperand_ParseFail;
5634 }
5635 // Eat the comma
5636 getParser().Lex();
5637
5638 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005639 unsigned SecondReg;
5640 Res = tryParseScalarRegister(SecondReg);
5641 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005642 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005643
Eugene Zelenko049b0172017-01-06 00:30:53 +00005644 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005645 (isXReg && !XRegClass.contains(SecondReg)) ||
5646 (isWReg && !WRegClass.contains(SecondReg))) {
5647 Error(E,"expected second odd register of a "
5648 "consecutive same-size even/odd register pair");
5649 return MatchOperand_ParseFail;
5650 }
Joel Jones504bf332016-10-24 13:37:13 +00005651
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005652 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005653 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005654 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5655 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5656 } else {
5657 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5658 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5659 }
5660
Florian Hahnc4422242017-11-07 13:07:50 +00005661 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5662 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005663
5664 return MatchOperand_Success;
5665}
Florian Hahn91f11e52017-11-07 16:45:48 +00005666
Sander de Smaleneb896b12018-04-25 09:26:47 +00005667template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005668OperandMatchResultTy
5669AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005670 const SMLoc S = getLoc();
5671 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005672 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005673 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005674
Sander de Smalen8e607342017-11-15 15:44:43 +00005675 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005676 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005677
5678 if (Res != MatchOperand_Success)
5679 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005680
5681 if (ParseSuffix && Kind.empty())
5682 return MatchOperand_NoMatch;
5683
Sander de Smalen73937b72018-04-11 07:36:10 +00005684 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5685 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005686 return MatchOperand_NoMatch;
5687
Sander de Smalen73937b72018-04-11 07:36:10 +00005688 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005689
5690 // No shift/extend is the default.
5691 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5692 Operands.push_back(AArch64Operand::CreateVectorReg(
5693 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5694
Sander de Smalenc33d6682018-06-04 06:40:55 +00005695 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5696 if (Res == MatchOperand_ParseFail)
5697 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005698 return MatchOperand_Success;
5699 }
5700
5701 // Eat the comma
5702 getParser().Lex();
5703
5704 // Match the shift
5705 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5706 Res = tryParseOptionalShiftExtend(ExtOpnd);
5707 if (Res != MatchOperand_Success)
5708 return Res;
5709
5710 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005711 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005712 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5713 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5714 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005715
5716 return MatchOperand_Success;
5717}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005718
5719OperandMatchResultTy
5720AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5721 MCAsmParser &Parser = getParser();
5722
5723 SMLoc SS = getLoc();
5724 const AsmToken &TokE = Parser.getTok();
5725 bool IsHash = TokE.is(AsmToken::Hash);
5726
5727 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5728 return MatchOperand_NoMatch;
5729
5730 int64_t Pattern;
5731 if (IsHash) {
5732 Parser.Lex(); // Eat hash
5733
5734 // Parse the immediate operand.
5735 const MCExpr *ImmVal;
5736 SS = getLoc();
5737 if (Parser.parseExpression(ImmVal))
5738 return MatchOperand_ParseFail;
5739
5740 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5741 if (!MCE)
5742 return MatchOperand_ParseFail;
5743
5744 Pattern = MCE->getValue();
5745 } else {
5746 // Parse the pattern
5747 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5748 if (!Pat)
5749 return MatchOperand_NoMatch;
5750
5751 Parser.Lex();
5752 Pattern = Pat->Encoding;
5753 assert(Pattern >= 0 && Pattern < 32);
5754 }
5755
5756 Operands.push_back(
5757 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5758 SS, getLoc(), getContext()));
5759
5760 return MatchOperand_Success;
5761}