blob: 6d6c3155ba1e94c6285ddd302f64155b32b22b9c [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
Sander de Smalene1eab422019-03-27 17:23:38 +00001093 if (isSVEVectorReg<Class>() && Reg.ElementWidth == ElementWidth)
Sander de Smalen22176a22018-05-16 15:45:17 +00001094 return DiagnosticPredicateTy::Match;
1095
1096 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00001097 }
1098
Sander de Smaleneb896b12018-04-25 09:26:47 +00001099 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +00001100 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
1101 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +00001102 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
1103 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
1104 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001105 return DiagnosticPredicateTy::NoMatch;
1106
Sander de Smalen5861c262018-04-30 07:24:38 +00001107 // Give a more specific diagnostic when the user has explicitly typed in
1108 // a shift-amount that does not match what is expected, but for which
1109 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
1110 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
1111 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
1112 ShiftExtendTy == AArch64_AM::SXTW) &&
1113 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
1114 return DiagnosticPredicateTy::NoMatch;
1115
1116 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001117 return DiagnosticPredicateTy::Match;
1118
1119 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +00001120 }
1121
Tim Northover3b0846e2014-05-24 12:50:23 +00001122 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001123 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001124 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
1125 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001126
Sander de Smalen0325e302018-07-02 07:34:52 +00001127 bool isGPR64as32() const {
1128 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1129 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(Reg.RegNum);
1130 }
1131
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001132 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001133 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001134 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
1135 Reg.RegNum);
1136 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001137
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001138 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001139 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001140 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1141 Reg.RegNum);
1142 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001143
Sam Parker5f934642017-08-31 09:27:04 +00001144 template<int64_t Angle, int64_t Remainder>
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001145 DiagnosticPredicate isComplexRotation() const {
1146 if (!isImm()) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001147
1148 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001149 if (!CE) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001150 uint64_t Value = CE->getValue();
1151
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001152 if (Value % Angle == Remainder && Value <= 270)
1153 return DiagnosticPredicateTy::Match;
1154 return DiagnosticPredicateTy::NearMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001155 }
1156
Sander de Smalen149916d2018-04-20 07:24:20 +00001157 template <unsigned RegClassID> bool isGPR64() const {
1158 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1159 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1160 }
1161
1162 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001163 DiagnosticPredicate isGPR64WithShiftExtend() const {
1164 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1165 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001166
Sander de Smalenfe17a782018-04-26 12:54:42 +00001167 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1168 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1169 return DiagnosticPredicateTy::Match;
1170 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001171 }
1172
Tim Northover3b0846e2014-05-24 12:50:23 +00001173 /// Is this a vector list with the type implicit (presumably attached to the
1174 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001175 template <RegKind VectorKind, unsigned NumRegs>
1176 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001177 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001178 VectorList.NumElements == 0 &&
1179 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001180 }
1181
Sander de Smalen650234b2018-04-12 11:40:52 +00001182 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1183 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001184 bool isTypedVectorList() const {
1185 if (Kind != k_VectorList)
1186 return false;
1187 if (VectorList.Count != NumRegs)
1188 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001189 if (VectorList.RegisterKind != VectorKind)
1190 return false;
1191 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001192 return false;
1193 return VectorList.NumElements == NumElements;
1194 }
1195
Sander de Smalenc33d6682018-06-04 06:40:55 +00001196 template <int Min, int Max>
1197 DiagnosticPredicate isVectorIndex() const {
1198 if (Kind != k_VectorIndex)
1199 return DiagnosticPredicateTy::NoMatch;
1200 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1201 return DiagnosticPredicateTy::Match;
1202 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001203 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001204
Tim Northover3b0846e2014-05-24 12:50:23 +00001205 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001206
Tim Northover3b0846e2014-05-24 12:50:23 +00001207 bool isTokenEqual(StringRef Str) const {
1208 return Kind == k_Token && getToken() == Str;
1209 }
1210 bool isSysCR() const { return Kind == k_SysCR; }
1211 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001212 bool isPSBHint() const { return Kind == k_PSBHint; }
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001213 bool isBTIHint() const { return Kind == k_BTIHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001214 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1215 bool isShifter() const {
1216 if (!isShiftExtend())
1217 return false;
1218
1219 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1220 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1221 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1222 ST == AArch64_AM::MSL);
1223 }
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001224
1225 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1226 if (Kind != k_FPImm)
1227 return DiagnosticPredicateTy::NoMatch;
1228
1229 if (getFPImmIsExact()) {
1230 // Lookup the immediate from table of supported immediates.
1231 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1232 assert(Desc && "Unknown enum value");
1233
1234 // Calculate its FP value.
1235 APFloat RealVal(APFloat::IEEEdouble());
1236 if (RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero) !=
1237 APFloat::opOK)
1238 llvm_unreachable("FP immediate is not exact");
1239
1240 if (getFPImm().bitwiseIsEqual(RealVal))
1241 return DiagnosticPredicateTy::Match;
1242 }
1243
1244 return DiagnosticPredicateTy::NearMatch;
1245 }
1246
1247 template <unsigned ImmA, unsigned ImmB>
1248 DiagnosticPredicate isExactFPImm() const {
1249 DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1250 if ((Res = isExactFPImm<ImmA>()))
1251 return DiagnosticPredicateTy::Match;
1252 if ((Res = isExactFPImm<ImmB>()))
1253 return DiagnosticPredicateTy::Match;
1254 return Res;
1255 }
1256
Tim Northover3b0846e2014-05-24 12:50:23 +00001257 bool isExtend() const {
1258 if (!isShiftExtend())
1259 return false;
1260
1261 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1262 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1263 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1264 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1265 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1266 ET == AArch64_AM::LSL) &&
1267 getShiftExtendAmount() <= 4;
1268 }
1269
1270 bool isExtend64() const {
1271 if (!isExtend())
1272 return false;
1273 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1274 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1275 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1276 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001277
Tim Northover3b0846e2014-05-24 12:50:23 +00001278 bool isExtendLSL64() const {
1279 if (!isExtend())
1280 return false;
1281 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1282 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1283 ET == AArch64_AM::LSL) &&
1284 getShiftExtendAmount() <= 4;
1285 }
1286
1287 template<int Width> bool isMemXExtend() const {
1288 if (!isExtend())
1289 return false;
1290 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1291 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1292 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1293 getShiftExtendAmount() == 0);
1294 }
1295
1296 template<int Width> bool isMemWExtend() const {
1297 if (!isExtend())
1298 return false;
1299 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1300 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1301 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1302 getShiftExtendAmount() == 0);
1303 }
1304
1305 template <unsigned width>
1306 bool isArithmeticShifter() const {
1307 if (!isShifter())
1308 return false;
1309
1310 // An arithmetic shifter is LSL, LSR, or ASR.
1311 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1312 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1313 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1314 }
1315
1316 template <unsigned width>
1317 bool isLogicalShifter() const {
1318 if (!isShifter())
1319 return false;
1320
1321 // A logical shifter is LSL, LSR, ASR or ROR.
1322 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1323 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1324 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1325 getShiftExtendAmount() < width;
1326 }
1327
1328 bool isMovImm32Shifter() const {
1329 if (!isShifter())
1330 return false;
1331
1332 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1333 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1334 if (ST != AArch64_AM::LSL)
1335 return false;
1336 uint64_t Val = getShiftExtendAmount();
1337 return (Val == 0 || Val == 16);
1338 }
1339
1340 bool isMovImm64Shifter() const {
1341 if (!isShifter())
1342 return false;
1343
1344 // A MOVi shifter is LSL of 0 or 16.
1345 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1346 if (ST != AArch64_AM::LSL)
1347 return false;
1348 uint64_t Val = getShiftExtendAmount();
1349 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1350 }
1351
1352 bool isLogicalVecShifter() const {
1353 if (!isShifter())
1354 return false;
1355
1356 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1357 unsigned Shift = getShiftExtendAmount();
1358 return getShiftExtendType() == AArch64_AM::LSL &&
1359 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1360 }
1361
1362 bool isLogicalVecHalfWordShifter() const {
1363 if (!isLogicalVecShifter())
1364 return false;
1365
1366 // A logical vector shifter is a left shift by 0 or 8.
1367 unsigned Shift = getShiftExtendAmount();
1368 return getShiftExtendType() == AArch64_AM::LSL &&
1369 (Shift == 0 || Shift == 8);
1370 }
1371
1372 bool isMoveVecShifter() const {
1373 if (!isShiftExtend())
1374 return false;
1375
1376 // A logical vector shifter is a left shift by 8 or 16.
1377 unsigned Shift = getShiftExtendAmount();
1378 return getShiftExtendType() == AArch64_AM::MSL &&
1379 (Shift == 8 || Shift == 16);
1380 }
1381
1382 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1383 // to LDUR/STUR when the offset is not legal for the former but is for
1384 // the latter. As such, in addition to checking for being a legal unscaled
1385 // address, also check that it is not a legal scaled address. This avoids
1386 // ambiguity in the matcher.
1387 template<int Width>
1388 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001389 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001390 }
1391
1392 bool isAdrpLabel() const {
1393 // Validation was handled during parsing, so we just sanity check that
1394 // something didn't go haywire.
1395 if (!isImm())
1396 return false;
1397
1398 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1399 int64_t Val = CE->getValue();
1400 int64_t Min = - (4096 * (1LL << (21 - 1)));
1401 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1402 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1403 }
1404
1405 return true;
1406 }
1407
1408 bool isAdrLabel() const {
1409 // Validation was handled during parsing, so we just sanity check that
1410 // something didn't go haywire.
1411 if (!isImm())
1412 return false;
1413
1414 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1415 int64_t Val = CE->getValue();
1416 int64_t Min = - (1LL << (21 - 1));
1417 int64_t Max = ((1LL << (21 - 1)) - 1);
1418 return Val >= Min && Val <= Max;
1419 }
1420
1421 return true;
1422 }
1423
1424 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1425 // Add as immediates when possible. Null MCExpr = 0.
1426 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001427 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001428 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001429 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001430 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001431 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001432 }
1433
1434 void addRegOperands(MCInst &Inst, unsigned N) const {
1435 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001436 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001437 }
1438
1439 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1440 assert(N == 1 && "Invalid number of operands!");
1441 assert(
1442 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1443
1444 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1445 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1446 RI->getEncodingValue(getReg()));
1447
Jim Grosbache9119e42015-05-13 18:37:00 +00001448 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001449 }
1450
Sander de Smalen0325e302018-07-02 07:34:52 +00001451 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1452 assert(N == 1 && "Invalid number of operands!");
1453 assert(
1454 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(getReg()));
1455
1456 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1457 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID).getRegister(
1458 RI->getEncodingValue(getReg()));
1459
1460 Inst.addOperand(MCOperand::createReg(Reg));
1461 }
1462
Sander de Smalenfd54a782018-06-04 07:07:35 +00001463 template <int Width>
1464 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1465 unsigned Base;
1466 switch (Width) {
1467 case 8: Base = AArch64::B0; break;
1468 case 16: Base = AArch64::H0; break;
1469 case 32: Base = AArch64::S0; break;
1470 case 64: Base = AArch64::D0; break;
1471 case 128: Base = AArch64::Q0; break;
1472 default:
1473 llvm_unreachable("Unsupported width");
1474 }
1475 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1476 }
1477
Tim Northover3b0846e2014-05-24 12:50:23 +00001478 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1479 assert(N == 1 && "Invalid number of operands!");
1480 assert(
1481 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001482 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001483 }
1484
1485 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1486 assert(N == 1 && "Invalid number of operands!");
1487 assert(
1488 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001489 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001490 }
1491
1492 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1493 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001494 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001495 }
1496
Sander de Smalen525e3222018-04-12 13:19:32 +00001497 enum VecListIndexType {
1498 VecListIdx_DReg = 0,
1499 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001500 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001501 };
1502
1503 template <VecListIndexType RegTy, unsigned NumRegs>
1504 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001505 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001506 static const unsigned FirstRegs[][5] = {
1507 /* DReg */ { AArch64::Q0,
1508 AArch64::D0, AArch64::D0_D1,
1509 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1510 /* QReg */ { AArch64::Q0,
1511 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001512 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1513 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001514 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001515 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001516 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001517
Sander de Smalen7a210db2018-04-16 10:46:18 +00001518 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1519 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001520
Sander de Smalen525e3222018-04-12 13:19:32 +00001521 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1522 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1523 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001524 }
1525
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001526 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001527 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001528 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001529 }
1530
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001531 template <unsigned ImmIs0, unsigned ImmIs1>
1532 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1533 assert(N == 1 && "Invalid number of operands!");
1534 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1535 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1536 }
1537
Tim Northover3b0846e2014-05-24 12:50:23 +00001538 void addImmOperands(MCInst &Inst, unsigned N) const {
1539 assert(N == 1 && "Invalid number of operands!");
1540 // If this is a pageoff symrefexpr with an addend, adjust the addend
1541 // to be only the page-offset portion. Otherwise, just add the expr
1542 // as-is.
1543 addExpr(Inst, getImm());
1544 }
1545
Sander de Smalen62770792018-05-25 09:47:52 +00001546 template <int Shift>
1547 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001548 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001549 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1550 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1551 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1552 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001553 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001554 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001555 } else {
1556 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001557 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001558 }
1559 }
1560
Sander de Smalen62770792018-05-25 09:47:52 +00001561 template <int Shift>
1562 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001563 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001564 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1565 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1566 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1567 } else
1568 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001569 }
1570
Tim Northover3b0846e2014-05-24 12:50:23 +00001571 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1572 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001573 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001574 }
1575
1576 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1577 assert(N == 1 && "Invalid number of operands!");
1578 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1579 if (!MCE)
1580 addExpr(Inst, getImm());
1581 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001582 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001583 }
1584
1585 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1586 addImmOperands(Inst, N);
1587 }
1588
1589 template<int Scale>
1590 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1591 assert(N == 1 && "Invalid number of operands!");
1592 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1593
1594 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001595 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001596 return;
1597 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001598 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001599 }
1600
Sjoerd Meijera3dad802018-07-06 12:32:33 +00001601 void addUImm6Operands(MCInst &Inst, unsigned N) const {
1602 assert(N == 1 && "Invalid number of operands!");
1603 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1604 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1605 }
1606
Sander de Smalen5c625982018-04-13 12:56:14 +00001607 template <int Scale>
1608 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1609 assert(N == 1 && "Invalid number of operands!");
1610 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1611 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1612 }
1613
Sander de Smalena1c259c2018-01-29 13:05:38 +00001614 template <typename T>
1615 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001616 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001617 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001618 typename std::make_unsigned<T>::type Val = MCE->getValue();
1619 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001620 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001621 }
1622
Sander de Smalena1c259c2018-01-29 13:05:38 +00001623 template <typename T>
1624 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001625 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001626 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001627 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1628 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001629 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001630 }
1631
Tim Northover3b0846e2014-05-24 12:50:23 +00001632 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1633 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001634 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001635 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001636 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001637 }
1638
1639 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1640 // Branch operands don't encode the low bits, so shift them off
1641 // here. If it's a label, however, just put it on directly as there's
1642 // not enough information now to do anything.
1643 assert(N == 1 && "Invalid number of operands!");
1644 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1645 if (!MCE) {
1646 addExpr(Inst, getImm());
1647 return;
1648 }
1649 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001650 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001651 }
1652
1653 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1654 // Branch operands don't encode the low bits, so shift them off
1655 // here. If it's a label, however, just put it on directly as there's
1656 // not enough information now to do anything.
1657 assert(N == 1 && "Invalid number of operands!");
1658 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1659 if (!MCE) {
1660 addExpr(Inst, getImm());
1661 return;
1662 }
1663 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001664 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001665 }
1666
1667 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1668 // Branch operands don't encode the low bits, so shift them off
1669 // here. If it's a label, however, just put it on directly as there's
1670 // not enough information now to do anything.
1671 assert(N == 1 && "Invalid number of operands!");
1672 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1673 if (!MCE) {
1674 addExpr(Inst, getImm());
1675 return;
1676 }
1677 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001678 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001679 }
1680
1681 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1682 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001683 Inst.addOperand(MCOperand::createImm(
1684 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
Tim Northover3b0846e2014-05-24 12:50:23 +00001685 }
1686
1687 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1688 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001689 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001690 }
1691
1692 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1693 assert(N == 1 && "Invalid number of operands!");
1694
Jim Grosbache9119e42015-05-13 18:37:00 +00001695 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001696 }
1697
1698 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1699 assert(N == 1 && "Invalid number of operands!");
1700
Jim Grosbache9119e42015-05-13 18:37:00 +00001701 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001702 }
1703
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001704 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1705 assert(N == 1 && "Invalid number of operands!");
1706
1707 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1708 }
1709
1710 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001711 assert(N == 1 && "Invalid number of operands!");
1712
Jim Grosbache9119e42015-05-13 18:37:00 +00001713 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001714 }
1715
1716 void addSysCROperands(MCInst &Inst, unsigned N) const {
1717 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001718 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001719 }
1720
1721 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1722 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001723 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001724 }
1725
Oliver Stannarda34e4702015-12-01 10:48:51 +00001726 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1727 assert(N == 1 && "Invalid number of operands!");
1728 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1729 }
1730
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001731 void addBTIHintOperands(MCInst &Inst, unsigned N) const {
1732 assert(N == 1 && "Invalid number of operands!");
1733 Inst.addOperand(MCOperand::createImm(getBTIHint()));
1734 }
1735
Tim Northover3b0846e2014-05-24 12:50:23 +00001736 void addShifterOperands(MCInst &Inst, unsigned N) const {
1737 assert(N == 1 && "Invalid number of operands!");
1738 unsigned Imm =
1739 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001740 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001741 }
1742
1743 void addExtendOperands(MCInst &Inst, unsigned N) const {
1744 assert(N == 1 && "Invalid number of operands!");
1745 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1746 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1747 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001748 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001749 }
1750
1751 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1752 assert(N == 1 && "Invalid number of operands!");
1753 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1754 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1755 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001756 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001757 }
1758
1759 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1760 assert(N == 2 && "Invalid number of operands!");
1761 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1762 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001763 Inst.addOperand(MCOperand::createImm(IsSigned));
1764 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001765 }
1766
1767 // For 8-bit load/store instructions with a register offset, both the
1768 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1769 // they're disambiguated by whether the shift was explicit or implicit rather
1770 // than its size.
1771 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1772 assert(N == 2 && "Invalid number of operands!");
1773 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1774 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001775 Inst.addOperand(MCOperand::createImm(IsSigned));
1776 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001777 }
1778
1779 template<int Shift>
1780 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1781 assert(N == 1 && "Invalid number of operands!");
1782
1783 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1784 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001785 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001786 }
1787
1788 template<int Shift>
1789 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1790 assert(N == 1 && "Invalid number of operands!");
1791
1792 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1793 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001794 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001795 }
1796
Sam Parker5f934642017-08-31 09:27:04 +00001797 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1798 assert(N == 1 && "Invalid number of operands!");
1799 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1800 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1801 }
1802
1803 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1804 assert(N == 1 && "Invalid number of operands!");
1805 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1806 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1807 }
1808
Tim Northover3b0846e2014-05-24 12:50:23 +00001809 void print(raw_ostream &OS) const override;
1810
David Blaikie960ea3f2014-06-08 16:18:35 +00001811 static std::unique_ptr<AArch64Operand>
1812 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1813 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001814 Op->Tok.Data = Str.data();
1815 Op->Tok.Length = Str.size();
1816 Op->Tok.IsSuffix = IsSuffix;
1817 Op->StartLoc = S;
1818 Op->EndLoc = S;
1819 return Op;
1820 }
1821
David Blaikie960ea3f2014-06-08 16:18:35 +00001822 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001823 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
Sander de Smalen0325e302018-07-02 07:34:52 +00001824 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
Sander de Smalen149916d2018-04-20 07:24:20 +00001825 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1826 unsigned ShiftAmount = 0,
1827 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001828 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001829 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001830 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001831 Op->Reg.ElementWidth = 0;
Sander de Smalen0325e302018-07-02 07:34:52 +00001832 Op->Reg.EqualityTy = EqTy;
Sander de Smalen149916d2018-04-20 07:24:20 +00001833 Op->Reg.ShiftExtend.Type = ExtTy;
1834 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1835 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001836 Op->StartLoc = S;
1837 Op->EndLoc = E;
1838 return Op;
1839 }
1840
David Blaikie960ea3f2014-06-08 16:18:35 +00001841 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001842 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001843 SMLoc S, SMLoc E, MCContext &Ctx,
1844 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1845 unsigned ShiftAmount = 0,
1846 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001847 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1848 Kind == RegKind::SVEPredicateVector) &&
1849 "Invalid vector kind");
Sander de Smalen0325e302018-07-02 07:34:52 +00001850 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
Sander de Smalen149916d2018-04-20 07:24:20 +00001851 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001852 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001853 return Op;
1854 }
1855
1856 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001857 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001858 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1859 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001860 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001861 Op->VectorList.RegNum = RegNum;
1862 Op->VectorList.Count = Count;
1863 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001864 Op->VectorList.ElementWidth = ElementWidth;
1865 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001866 Op->StartLoc = S;
1867 Op->EndLoc = E;
1868 return Op;
1869 }
1870
David Blaikie960ea3f2014-06-08 16:18:35 +00001871 static std::unique_ptr<AArch64Operand>
1872 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1873 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001874 Op->VectorIndex.Val = Idx;
1875 Op->StartLoc = S;
1876 Op->EndLoc = E;
1877 return Op;
1878 }
1879
David Blaikie960ea3f2014-06-08 16:18:35 +00001880 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1881 SMLoc E, MCContext &Ctx) {
1882 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001883 Op->Imm.Val = Val;
1884 Op->StartLoc = S;
1885 Op->EndLoc = E;
1886 return Op;
1887 }
1888
David Blaikie960ea3f2014-06-08 16:18:35 +00001889 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1890 unsigned ShiftAmount,
1891 SMLoc S, SMLoc E,
1892 MCContext &Ctx) {
1893 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001894 Op->ShiftedImm .Val = Val;
1895 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1896 Op->StartLoc = S;
1897 Op->EndLoc = E;
1898 return Op;
1899 }
1900
David Blaikie960ea3f2014-06-08 16:18:35 +00001901 static std::unique_ptr<AArch64Operand>
1902 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1903 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001904 Op->CondCode.Code = Code;
1905 Op->StartLoc = S;
1906 Op->EndLoc = E;
1907 return Op;
1908 }
1909
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001910 static std::unique_ptr<AArch64Operand>
1911 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001912 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001913 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
1914 Op->FPImm.IsExact = IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +00001915 Op->StartLoc = S;
1916 Op->EndLoc = S;
1917 return Op;
1918 }
1919
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001920 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1921 StringRef Str,
1922 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001923 MCContext &Ctx) {
1924 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001925 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001926 Op->Barrier.Data = Str.data();
1927 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001928 Op->StartLoc = S;
1929 Op->EndLoc = S;
1930 return Op;
1931 }
1932
Tim Northover7cd58932015-01-22 17:23:04 +00001933 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1934 uint32_t MRSReg,
1935 uint32_t MSRReg,
1936 uint32_t PStateField,
1937 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001938 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001939 Op->SysReg.Data = Str.data();
1940 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001941 Op->SysReg.MRSReg = MRSReg;
1942 Op->SysReg.MSRReg = MSRReg;
1943 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001944 Op->StartLoc = S;
1945 Op->EndLoc = S;
1946 return Op;
1947 }
1948
David Blaikie960ea3f2014-06-08 16:18:35 +00001949 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1950 SMLoc E, MCContext &Ctx) {
1951 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001952 Op->SysCRImm.Val = Val;
1953 Op->StartLoc = S;
1954 Op->EndLoc = E;
1955 return Op;
1956 }
1957
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001958 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1959 StringRef Str,
1960 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001961 MCContext &Ctx) {
1962 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001963 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001964 Op->Barrier.Data = Str.data();
1965 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001966 Op->StartLoc = S;
1967 Op->EndLoc = S;
1968 return Op;
1969 }
1970
Oliver Stannarda34e4702015-12-01 10:48:51 +00001971 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1972 StringRef Str,
1973 SMLoc S,
1974 MCContext &Ctx) {
1975 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1976 Op->PSBHint.Val = Val;
1977 Op->PSBHint.Data = Str.data();
1978 Op->PSBHint.Length = Str.size();
1979 Op->StartLoc = S;
1980 Op->EndLoc = S;
1981 return Op;
1982 }
1983
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001984 static std::unique_ptr<AArch64Operand> CreateBTIHint(unsigned Val,
1985 StringRef Str,
1986 SMLoc S,
1987 MCContext &Ctx) {
1988 auto Op = make_unique<AArch64Operand>(k_BTIHint, Ctx);
1989 Op->BTIHint.Val = Val << 1 | 32;
1990 Op->BTIHint.Data = Str.data();
1991 Op->BTIHint.Length = Str.size();
1992 Op->StartLoc = S;
1993 Op->EndLoc = S;
1994 return Op;
1995 }
1996
David Blaikie960ea3f2014-06-08 16:18:35 +00001997 static std::unique_ptr<AArch64Operand>
1998 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1999 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
2000 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00002001 Op->ShiftExtend.Type = ShOp;
2002 Op->ShiftExtend.Amount = Val;
2003 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
2004 Op->StartLoc = S;
2005 Op->EndLoc = E;
2006 return Op;
2007 }
2008};
2009
2010} // end anonymous namespace.
2011
2012void AArch64Operand::print(raw_ostream &OS) const {
2013 switch (Kind) {
2014 case k_FPImm:
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002015 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
2016 if (!getFPImmIsExact())
2017 OS << " (inexact)";
2018 OS << ">";
Tim Northover3b0846e2014-05-24 12:50:23 +00002019 break;
2020 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00002021 StringRef Name = getBarrierName();
2022 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00002023 OS << "<barrier " << Name << ">";
2024 else
2025 OS << "<barrier invalid #" << getBarrier() << ">";
2026 break;
2027 }
2028 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00002029 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00002030 break;
2031 case k_ShiftedImm: {
2032 unsigned Shift = getShiftedImmShift();
2033 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00002034 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00002035 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
2036 break;
2037 }
2038 case k_CondCode:
2039 OS << "<condcode " << getCondCode() << ">";
2040 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00002041 case k_VectorList: {
2042 OS << "<vectorlist ";
2043 unsigned Reg = getVectorListStart();
2044 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
2045 OS << Reg + i << " ";
2046 OS << ">";
2047 break;
2048 }
2049 case k_VectorIndex:
2050 OS << "<vectorindex " << getVectorIndex() << ">";
2051 break;
2052 case k_SysReg:
2053 OS << "<sysreg: " << getSysReg() << '>';
2054 break;
2055 case k_Token:
2056 OS << "'" << getToken() << "'";
2057 break;
2058 case k_SysCR:
2059 OS << "c" << getSysCR();
2060 break;
2061 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00002062 StringRef Name = getPrefetchName();
2063 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00002064 OS << "<prfop " << Name << ">";
2065 else
2066 OS << "<prfop invalid #" << getPrefetch() << ">";
2067 break;
2068 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00002069 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00002070 OS << getPSBHintName();
2071 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00002072 case k_Register:
2073 OS << "<register " << getReg() << ">";
2074 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
2075 break;
2076 LLVM_FALLTHROUGH;
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00002077 case k_BTIHint:
2078 OS << getBTIHintName();
2079 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00002080 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00002081 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
2082 << getShiftExtendAmount();
2083 if (!hasShiftExtendAmount())
2084 OS << "<imp>";
2085 OS << '>';
2086 break;
2087 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002088}
2089
2090/// @name Auto-generated Match Functions
2091/// {
2092
2093static unsigned MatchRegisterName(StringRef Name);
2094
2095/// }
2096
Florian Hahnc4422242017-11-07 13:07:50 +00002097static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00002098 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00002099 .Case("v0", AArch64::Q0)
2100 .Case("v1", AArch64::Q1)
2101 .Case("v2", AArch64::Q2)
2102 .Case("v3", AArch64::Q3)
2103 .Case("v4", AArch64::Q4)
2104 .Case("v5", AArch64::Q5)
2105 .Case("v6", AArch64::Q6)
2106 .Case("v7", AArch64::Q7)
2107 .Case("v8", AArch64::Q8)
2108 .Case("v9", AArch64::Q9)
2109 .Case("v10", AArch64::Q10)
2110 .Case("v11", AArch64::Q11)
2111 .Case("v12", AArch64::Q12)
2112 .Case("v13", AArch64::Q13)
2113 .Case("v14", AArch64::Q14)
2114 .Case("v15", AArch64::Q15)
2115 .Case("v16", AArch64::Q16)
2116 .Case("v17", AArch64::Q17)
2117 .Case("v18", AArch64::Q18)
2118 .Case("v19", AArch64::Q19)
2119 .Case("v20", AArch64::Q20)
2120 .Case("v21", AArch64::Q21)
2121 .Case("v22", AArch64::Q22)
2122 .Case("v23", AArch64::Q23)
2123 .Case("v24", AArch64::Q24)
2124 .Case("v25", AArch64::Q25)
2125 .Case("v26", AArch64::Q26)
2126 .Case("v27", AArch64::Q27)
2127 .Case("v28", AArch64::Q28)
2128 .Case("v29", AArch64::Q29)
2129 .Case("v30", AArch64::Q30)
2130 .Case("v31", AArch64::Q31)
2131 .Default(0);
2132}
2133
Sander de Smalen73937b72018-04-11 07:36:10 +00002134/// Returns an optional pair of (#elements, element-width) if Suffix
2135/// is a valid vector kind. Where the number of elements in a vector
2136/// or the vector width is implicit or explicitly unknown (but still a
2137/// valid suffix kind), 0 is used.
2138static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2139 RegKind VectorKind) {
2140 std::pair<int, int> Res = {-1, -1};
2141
2142 switch (VectorKind) {
2143 case RegKind::NeonVector:
2144 Res =
2145 StringSwitch<std::pair<int, int>>(Suffix.lower())
2146 .Case("", {0, 0})
2147 .Case(".1d", {1, 64})
2148 .Case(".1q", {1, 128})
2149 // '.2h' needed for fp16 scalar pairwise reductions
2150 .Case(".2h", {2, 16})
2151 .Case(".2s", {2, 32})
2152 .Case(".2d", {2, 64})
2153 // '.4b' is another special case for the ARMv8.2a dot product
2154 // operand
2155 .Case(".4b", {4, 8})
2156 .Case(".4h", {4, 16})
2157 .Case(".4s", {4, 32})
2158 .Case(".8b", {8, 8})
2159 .Case(".8h", {8, 16})
2160 .Case(".16b", {16, 8})
2161 // Accept the width neutral ones, too, for verbose syntax. If those
2162 // aren't used in the right places, the token operand won't match so
2163 // all will work out.
2164 .Case(".b", {0, 8})
2165 .Case(".h", {0, 16})
2166 .Case(".s", {0, 32})
2167 .Case(".d", {0, 64})
2168 .Default({-1, -1});
2169 break;
2170 case RegKind::SVEPredicateVector:
2171 case RegKind::SVEDataVector:
2172 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2173 .Case("", {0, 0})
2174 .Case(".b", {0, 8})
2175 .Case(".h", {0, 16})
2176 .Case(".s", {0, 32})
2177 .Case(".d", {0, 64})
2178 .Case(".q", {0, 128})
2179 .Default({-1, -1});
2180 break;
2181 default:
2182 llvm_unreachable("Unsupported RegKind");
2183 }
2184
2185 if (Res == std::make_pair(-1, -1))
2186 return Optional<std::pair<int, int>>();
2187
2188 return Optional<std::pair<int, int>>(Res);
2189}
2190
2191static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2192 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002193}
2194
Florian Hahn91f11e52017-11-07 16:45:48 +00002195static unsigned matchSVEDataVectorRegName(StringRef Name) {
2196 return StringSwitch<unsigned>(Name.lower())
2197 .Case("z0", AArch64::Z0)
2198 .Case("z1", AArch64::Z1)
2199 .Case("z2", AArch64::Z2)
2200 .Case("z3", AArch64::Z3)
2201 .Case("z4", AArch64::Z4)
2202 .Case("z5", AArch64::Z5)
2203 .Case("z6", AArch64::Z6)
2204 .Case("z7", AArch64::Z7)
2205 .Case("z8", AArch64::Z8)
2206 .Case("z9", AArch64::Z9)
2207 .Case("z10", AArch64::Z10)
2208 .Case("z11", AArch64::Z11)
2209 .Case("z12", AArch64::Z12)
2210 .Case("z13", AArch64::Z13)
2211 .Case("z14", AArch64::Z14)
2212 .Case("z15", AArch64::Z15)
2213 .Case("z16", AArch64::Z16)
2214 .Case("z17", AArch64::Z17)
2215 .Case("z18", AArch64::Z18)
2216 .Case("z19", AArch64::Z19)
2217 .Case("z20", AArch64::Z20)
2218 .Case("z21", AArch64::Z21)
2219 .Case("z22", AArch64::Z22)
2220 .Case("z23", AArch64::Z23)
2221 .Case("z24", AArch64::Z24)
2222 .Case("z25", AArch64::Z25)
2223 .Case("z26", AArch64::Z26)
2224 .Case("z27", AArch64::Z27)
2225 .Case("z28", AArch64::Z28)
2226 .Case("z29", AArch64::Z29)
2227 .Case("z30", AArch64::Z30)
2228 .Case("z31", AArch64::Z31)
2229 .Default(0);
2230}
2231
Sander de Smalencd6be962017-12-20 11:02:42 +00002232static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2233 return StringSwitch<unsigned>(Name.lower())
2234 .Case("p0", AArch64::P0)
2235 .Case("p1", AArch64::P1)
2236 .Case("p2", AArch64::P2)
2237 .Case("p3", AArch64::P3)
2238 .Case("p4", AArch64::P4)
2239 .Case("p5", AArch64::P5)
2240 .Case("p6", AArch64::P6)
2241 .Case("p7", AArch64::P7)
2242 .Case("p8", AArch64::P8)
2243 .Case("p9", AArch64::P9)
2244 .Case("p10", AArch64::P10)
2245 .Case("p11", AArch64::P11)
2246 .Case("p12", AArch64::P12)
2247 .Case("p13", AArch64::P13)
2248 .Case("p14", AArch64::P14)
2249 .Case("p15", AArch64::P15)
2250 .Default(0);
2251}
2252
Tim Northover3b0846e2014-05-24 12:50:23 +00002253bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2254 SMLoc &EndLoc) {
2255 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002256 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002257 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002258 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002259}
2260
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002261// Matches a register name or register alias previously defined by '.req'
2262unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002263 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002264 unsigned RegNum = 0;
2265 if ((RegNum = matchSVEDataVectorRegName(Name)))
2266 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2267
Sander de Smalencd6be962017-12-20 11:02:42 +00002268 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2269 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2270
Sander de Smalenc067c302017-12-20 09:45:45 +00002271 if ((RegNum = MatchNeonVectorRegName(Name)))
2272 return Kind == RegKind::NeonVector ? RegNum : 0;
2273
2274 // The parsed register must be of RegKind Scalar
2275 if ((RegNum = MatchRegisterName(Name)))
2276 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002277
Florian Hahnc4422242017-11-07 13:07:50 +00002278 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002279 // Handle a few common aliases of registers.
2280 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2281 .Case("fp", AArch64::FP)
2282 .Case("lr", AArch64::LR)
2283 .Case("x31", AArch64::XZR)
2284 .Case("w31", AArch64::WZR)
2285 .Default(0))
2286 return Kind == RegKind::Scalar ? RegNum : 0;
2287
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002288 // Check for aliases registered via .req. Canonicalize to lower case.
2289 // That's more consistent since register names are case insensitive, and
2290 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2291 auto Entry = RegisterReqs.find(Name.lower());
2292 if (Entry == RegisterReqs.end())
2293 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002294
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002295 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002296 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002297 RegNum = Entry->getValue().second;
2298 }
2299 return RegNum;
2300}
2301
Sander de Smalen50d87022018-04-19 07:35:08 +00002302/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002303/// Identifier when called, and if it is a register name the token is eaten and
2304/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002305OperandMatchResultTy
2306AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002307 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002308 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002309 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002310 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002311
2312 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002313 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2314 if (Reg == 0)
2315 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002316
Sander de Smalen50d87022018-04-19 07:35:08 +00002317 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002318 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002319 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002320}
2321
Tim Northover3b0846e2014-05-24 12:50:23 +00002322/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002323OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002324AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002325 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002326 SMLoc S = getLoc();
2327
2328 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2329 Error(S, "Expected cN operand where 0 <= N <= 15");
2330 return MatchOperand_ParseFail;
2331 }
2332
2333 StringRef Tok = Parser.getTok().getIdentifier();
2334 if (Tok[0] != 'c' && Tok[0] != 'C') {
2335 Error(S, "Expected cN operand where 0 <= N <= 15");
2336 return MatchOperand_ParseFail;
2337 }
2338
2339 uint32_t CRNum;
2340 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2341 if (BadNum || CRNum > 15) {
2342 Error(S, "Expected cN operand where 0 <= N <= 15");
2343 return MatchOperand_ParseFail;
2344 }
2345
2346 Parser.Lex(); // Eat identifier token.
2347 Operands.push_back(
2348 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2349 return MatchOperand_Success;
2350}
2351
2352/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002353template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002354OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002355AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002356 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002357 SMLoc S = getLoc();
2358 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002359
2360 auto LookupByName = [](StringRef N) {
2361 if (IsSVEPrefetch) {
2362 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2363 return Optional<unsigned>(Res->Encoding);
2364 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2365 return Optional<unsigned>(Res->Encoding);
2366 return Optional<unsigned>();
2367 };
2368
2369 auto LookupByEncoding = [](unsigned E) {
2370 if (IsSVEPrefetch) {
2371 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2372 return Optional<StringRef>(Res->Name);
2373 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2374 return Optional<StringRef>(Res->Name);
2375 return Optional<StringRef>();
2376 };
2377 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2378
Tim Northover3b0846e2014-05-24 12:50:23 +00002379 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002380 // Eat optional hash.
2381 if (parseOptionalToken(AsmToken::Hash) ||
2382 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002383 const MCExpr *ImmVal;
2384 if (getParser().parseExpression(ImmVal))
2385 return MatchOperand_ParseFail;
2386
2387 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2388 if (!MCE) {
2389 TokError("immediate value expected for prefetch operand");
2390 return MatchOperand_ParseFail;
2391 }
2392 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002393 if (prfop > MaxVal) {
2394 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2395 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002396 return MatchOperand_ParseFail;
2397 }
2398
Sander de Smalen93380372018-05-14 11:54:41 +00002399 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002400 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002401 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002402 return MatchOperand_Success;
2403 }
2404
2405 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002406 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002407 return MatchOperand_ParseFail;
2408 }
2409
Sander de Smalen93380372018-05-14 11:54:41 +00002410 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002411 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002412 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002413 return MatchOperand_ParseFail;
2414 }
2415
2416 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002417 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002418 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002419 return MatchOperand_Success;
2420}
2421
Oliver Stannarda34e4702015-12-01 10:48:51 +00002422/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002423OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002424AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2425 MCAsmParser &Parser = getParser();
2426 SMLoc S = getLoc();
2427 const AsmToken &Tok = Parser.getTok();
2428 if (Tok.isNot(AsmToken::Identifier)) {
2429 TokError("invalid operand for instruction");
2430 return MatchOperand_ParseFail;
2431 }
2432
Tim Northovere6ae6762016-07-05 21:23:04 +00002433 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2434 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002435 TokError("invalid operand for instruction");
2436 return MatchOperand_ParseFail;
2437 }
2438
2439 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002440 Operands.push_back(AArch64Operand::CreatePSBHint(
2441 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002442 return MatchOperand_Success;
2443}
2444
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00002445/// tryParseBTIHint - Try to parse a BTI operand, mapped to Hint command
2446OperandMatchResultTy
2447AArch64AsmParser::tryParseBTIHint(OperandVector &Operands) {
2448 MCAsmParser &Parser = getParser();
2449 SMLoc S = getLoc();
2450 const AsmToken &Tok = Parser.getTok();
2451 if (Tok.isNot(AsmToken::Identifier)) {
2452 TokError("invalid operand for instruction");
2453 return MatchOperand_ParseFail;
2454 }
2455
2456 auto BTI = AArch64BTIHint::lookupBTIByName(Tok.getString());
2457 if (!BTI) {
2458 TokError("invalid operand for instruction");
2459 return MatchOperand_ParseFail;
2460 }
2461
2462 Parser.Lex(); // Eat identifier token.
2463 Operands.push_back(AArch64Operand::CreateBTIHint(
2464 BTI->Encoding, Tok.getString(), S, getContext()));
2465 return MatchOperand_Success;
2466}
2467
Tim Northover3b0846e2014-05-24 12:50:23 +00002468/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2469/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002470OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002471AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002472 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002473 SMLoc S = getLoc();
2474 const MCExpr *Expr;
2475
2476 if (Parser.getTok().is(AsmToken::Hash)) {
2477 Parser.Lex(); // Eat hash token.
2478 }
2479
2480 if (parseSymbolicImmVal(Expr))
2481 return MatchOperand_ParseFail;
2482
2483 AArch64MCExpr::VariantKind ELFRefKind;
2484 MCSymbolRefExpr::VariantKind DarwinRefKind;
2485 int64_t Addend;
2486 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2487 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2488 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2489 // No modifier was specified at all; this is the syntax for an ELF basic
2490 // ADRP relocation (unfortunately).
2491 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002492 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002493 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2494 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2495 Addend != 0) {
2496 Error(S, "gotpage label reference not allowed an addend");
2497 return MatchOperand_ParseFail;
2498 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2499 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2500 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2501 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2502 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2503 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2504 // The operand must be an @page or @gotpage qualified symbolref.
2505 Error(S, "page or gotpage label reference expected");
2506 return MatchOperand_ParseFail;
2507 }
2508 }
2509
2510 // We have either a label reference possibly with addend or an immediate. The
2511 // addend is a raw value here. The linker will adjust it to only reference the
2512 // page.
2513 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2514 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2515
2516 return MatchOperand_Success;
2517}
2518
2519/// tryParseAdrLabel - Parse and validate a source label for the ADR
2520/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002521OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002522AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2523 SMLoc S = getLoc();
2524 const MCExpr *Expr;
2525
David Green9dd1d452018-08-22 11:31:39 +00002526 // Leave anything with a bracket to the default for SVE
2527 if (getParser().getTok().is(AsmToken::LBrac))
2528 return MatchOperand_NoMatch;
2529
2530 if (getParser().getTok().is(AsmToken::Hash))
2531 getParser().Lex(); // Eat hash token.
2532
2533 if (parseSymbolicImmVal(Expr))
2534 return MatchOperand_ParseFail;
2535
2536 AArch64MCExpr::VariantKind ELFRefKind;
2537 MCSymbolRefExpr::VariantKind DarwinRefKind;
2538 int64_t Addend;
2539 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2540 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2541 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2542 // No modifier was specified at all; this is the syntax for an ELF basic
2543 // ADR relocation (unfortunately).
2544 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS, getContext());
2545 } else {
2546 Error(S, "unexpected adr label");
Sander de Smalenc69944c2018-07-09 09:58:24 +00002547 return MatchOperand_ParseFail;
David Green9dd1d452018-08-22 11:31:39 +00002548 }
Sander de Smalenc69944c2018-07-09 09:58:24 +00002549 }
David Green9dd1d452018-08-22 11:31:39 +00002550
2551 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2552 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2553 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002554}
2555
2556/// tryParseFPImm - A floating point immediate expression operand.
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002557template<bool AddFPZeroAsLiteral>
Alex Bradbury58eba092016-11-01 16:32:05 +00002558OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002559AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002560 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002561 SMLoc S = getLoc();
2562
Nirav Davee833c6c2016-11-08 18:31:04 +00002563 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002564
2565 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002566 bool isNegative = parseOptionalToken(AsmToken::Minus);
2567
Tim Northover3b0846e2014-05-24 12:50:23 +00002568 const AsmToken &Tok = Parser.getTok();
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002569 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2570 if (!Hash)
2571 return MatchOperand_NoMatch;
2572 TokError("invalid floating point immediate");
2573 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002574 }
2575
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002576 // Parse hexadecimal representation.
2577 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2578 if (Tok.getIntVal() > 255 || isNegative) {
2579 TokError("encoded floating point value out of range");
2580 return MatchOperand_ParseFail;
2581 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002582
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002583 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2584 Operands.push_back(
2585 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2586 } else {
2587 // Parse FP representation.
2588 APFloat RealVal(APFloat::IEEEdouble());
2589 auto Status =
2590 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2591 if (isNegative)
2592 RealVal.changeSign();
2593
2594 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2595 Operands.push_back(
2596 AArch64Operand::CreateToken("#0", false, S, getContext()));
2597 Operands.push_back(
2598 AArch64Operand::CreateToken(".0", false, S, getContext()));
2599 } else
2600 Operands.push_back(AArch64Operand::CreateFPImm(
2601 RealVal, Status == APFloat::opOK, S, getContext()));
2602 }
2603
2604 Parser.Lex(); // Eat the token.
2605
2606 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002607}
2608
Sander de Smalen62770792018-05-25 09:47:52 +00002609/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2610/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002611OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002612AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002613 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002614 SMLoc S = getLoc();
2615
2616 if (Parser.getTok().is(AsmToken::Hash))
2617 Parser.Lex(); // Eat '#'
2618 else if (Parser.getTok().isNot(AsmToken::Integer))
2619 // Operand should start from # or should be integer, emit error otherwise.
2620 return MatchOperand_NoMatch;
2621
2622 const MCExpr *Imm;
2623 if (parseSymbolicImmVal(Imm))
2624 return MatchOperand_ParseFail;
2625 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002626 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002627 Operands.push_back(
2628 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002629 return MatchOperand_Success;
2630 }
2631
2632 // Eat ','
2633 Parser.Lex();
2634
2635 // The optional operand must be "lsl #N" where N is non-negative.
2636 if (!Parser.getTok().is(AsmToken::Identifier) ||
2637 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2638 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2639 return MatchOperand_ParseFail;
2640 }
2641
2642 // Eat 'lsl'
2643 Parser.Lex();
2644
Nirav Davee833c6c2016-11-08 18:31:04 +00002645 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002646
2647 if (Parser.getTok().isNot(AsmToken::Integer)) {
2648 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2649 return MatchOperand_ParseFail;
2650 }
2651
2652 int64_t ShiftAmount = Parser.getTok().getIntVal();
2653
2654 if (ShiftAmount < 0) {
2655 Error(Parser.getTok().getLoc(), "positive shift amount required");
2656 return MatchOperand_ParseFail;
2657 }
2658 Parser.Lex(); // Eat the number
2659
Sander de Smalen62770792018-05-25 09:47:52 +00002660 // Just in case the optional lsl #0 is used for immediates other than zero.
2661 if (ShiftAmount == 0 && Imm != 0) {
2662 SMLoc E = Parser.getTok().getLoc();
2663 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2664 return MatchOperand_Success;
2665 }
2666
Tim Northover3b0846e2014-05-24 12:50:23 +00002667 SMLoc E = Parser.getTok().getLoc();
2668 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2669 S, E, getContext()));
2670 return MatchOperand_Success;
2671}
2672
2673/// parseCondCodeString - Parse a Condition Code string.
2674AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2675 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2676 .Case("eq", AArch64CC::EQ)
2677 .Case("ne", AArch64CC::NE)
2678 .Case("cs", AArch64CC::HS)
2679 .Case("hs", AArch64CC::HS)
2680 .Case("cc", AArch64CC::LO)
2681 .Case("lo", AArch64CC::LO)
2682 .Case("mi", AArch64CC::MI)
2683 .Case("pl", AArch64CC::PL)
2684 .Case("vs", AArch64CC::VS)
2685 .Case("vc", AArch64CC::VC)
2686 .Case("hi", AArch64CC::HI)
2687 .Case("ls", AArch64CC::LS)
2688 .Case("ge", AArch64CC::GE)
2689 .Case("lt", AArch64CC::LT)
2690 .Case("gt", AArch64CC::GT)
2691 .Case("le", AArch64CC::LE)
2692 .Case("al", AArch64CC::AL)
2693 .Case("nv", AArch64CC::NV)
2694 .Default(AArch64CC::Invalid);
Sander de Smalene31e6d42018-07-04 08:50:49 +00002695
2696 if (CC == AArch64CC::Invalid &&
2697 getSTI().getFeatureBits()[AArch64::FeatureSVE])
2698 CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2699 .Case("none", AArch64CC::EQ)
2700 .Case("any", AArch64CC::NE)
2701 .Case("nlast", AArch64CC::HS)
2702 .Case("last", AArch64CC::LO)
2703 .Case("first", AArch64CC::MI)
2704 .Case("nfrst", AArch64CC::PL)
2705 .Case("pmore", AArch64CC::HI)
2706 .Case("plast", AArch64CC::LS)
2707 .Case("tcont", AArch64CC::GE)
2708 .Case("tstop", AArch64CC::LT)
2709 .Default(AArch64CC::Invalid);
2710
Tim Northover3b0846e2014-05-24 12:50:23 +00002711 return CC;
2712}
2713
2714/// parseCondCode - Parse a Condition Code operand.
2715bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2716 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002717 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002718 SMLoc S = getLoc();
2719 const AsmToken &Tok = Parser.getTok();
2720 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2721
2722 StringRef Cond = Tok.getString();
2723 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2724 if (CC == AArch64CC::Invalid)
2725 return TokError("invalid condition code");
2726 Parser.Lex(); // Eat identifier token.
2727
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002728 if (invertCondCode) {
2729 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2730 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002731 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002732 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002733
2734 Operands.push_back(
2735 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2736 return false;
2737}
2738
2739/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2740/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002741OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002742AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002743 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002744 const AsmToken &Tok = Parser.getTok();
2745 std::string LowerID = Tok.getString().lower();
2746 AArch64_AM::ShiftExtendType ShOp =
2747 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2748 .Case("lsl", AArch64_AM::LSL)
2749 .Case("lsr", AArch64_AM::LSR)
2750 .Case("asr", AArch64_AM::ASR)
2751 .Case("ror", AArch64_AM::ROR)
2752 .Case("msl", AArch64_AM::MSL)
2753 .Case("uxtb", AArch64_AM::UXTB)
2754 .Case("uxth", AArch64_AM::UXTH)
2755 .Case("uxtw", AArch64_AM::UXTW)
2756 .Case("uxtx", AArch64_AM::UXTX)
2757 .Case("sxtb", AArch64_AM::SXTB)
2758 .Case("sxth", AArch64_AM::SXTH)
2759 .Case("sxtw", AArch64_AM::SXTW)
2760 .Case("sxtx", AArch64_AM::SXTX)
2761 .Default(AArch64_AM::InvalidShiftExtend);
2762
2763 if (ShOp == AArch64_AM::InvalidShiftExtend)
2764 return MatchOperand_NoMatch;
2765
2766 SMLoc S = Tok.getLoc();
2767 Parser.Lex();
2768
Nirav Davee833c6c2016-11-08 18:31:04 +00002769 bool Hash = parseOptionalToken(AsmToken::Hash);
2770
Tim Northover3b0846e2014-05-24 12:50:23 +00002771 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2772 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2773 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2774 ShOp == AArch64_AM::MSL) {
2775 // We expect a number here.
2776 TokError("expected #imm after shift specifier");
2777 return MatchOperand_ParseFail;
2778 }
2779
Chad Rosier2ff37b82016-12-27 16:58:09 +00002780 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002781 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2782 Operands.push_back(
2783 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2784 return MatchOperand_Success;
2785 }
2786
Chad Rosier2ff37b82016-12-27 16:58:09 +00002787 // Make sure we do actually have a number, identifier or a parenthesized
2788 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002789 SMLoc E = Parser.getTok().getLoc();
2790 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002791 !Parser.getTok().is(AsmToken::LParen) &&
2792 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002793 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002794 return MatchOperand_ParseFail;
2795 }
2796
2797 const MCExpr *ImmVal;
2798 if (getParser().parseExpression(ImmVal))
2799 return MatchOperand_ParseFail;
2800
2801 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2802 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002803 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002804 return MatchOperand_ParseFail;
2805 }
2806
Jim Grosbach57fd2622014-09-23 22:16:02 +00002807 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002808 Operands.push_back(AArch64Operand::CreateShiftExtend(
2809 ShOp, MCE->getValue(), true, S, E, getContext()));
2810 return MatchOperand_Success;
2811}
2812
Oliver Stannard89b16042018-09-26 13:52:27 +00002813static const struct Extension {
2814 const char *Name;
2815 const FeatureBitset Features;
2816} ExtensionMap[] = {
Diogo N. Sampaio9c906732018-12-06 15:39:17 +00002817 {"crc", {AArch64::FeatureCRC}},
2818 {"sm4", {AArch64::FeatureSM4}},
2819 {"sha3", {AArch64::FeatureSHA3}},
2820 {"sha2", {AArch64::FeatureSHA2}},
2821 {"aes", {AArch64::FeatureAES}},
2822 {"crypto", {AArch64::FeatureCrypto}},
2823 {"fp", {AArch64::FeatureFPARMv8}},
2824 {"simd", {AArch64::FeatureNEON}},
2825 {"ras", {AArch64::FeatureRAS}},
2826 {"lse", {AArch64::FeatureLSE}},
Diogo N. Sampaio1eb31c82019-01-09 11:24:15 +00002827 {"predres", {AArch64::FeaturePredRes}},
Diogo N. Sampaio9c906732018-12-06 15:39:17 +00002828 {"ccdp", {AArch64::FeatureCacheDeepPersist}},
2829 {"mte", {AArch64::FeatureMTE}},
2830 {"tlb-rmi", {AArch64::FeatureTLB_RMI}},
2831 {"pan-rwv", {AArch64::FeaturePAN_RWV}},
2832 {"ccpp", {AArch64::FeatureCCPP}},
Martin Storsjo74d93f92018-12-31 10:22:04 +00002833 {"sve", {AArch64::FeatureSVE}},
Diogo N. Sampaio9c906732018-12-06 15:39:17 +00002834 // FIXME: Unsupported extensions
2835 {"pan", {}},
2836 {"lor", {}},
2837 {"rdma", {}},
2838 {"profile", {}},
Oliver Stannard89b16042018-09-26 13:52:27 +00002839};
2840
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002841static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2842 if (FBS[AArch64::HasV8_1aOps])
2843 Str += "ARMv8.1a";
2844 else if (FBS[AArch64::HasV8_2aOps])
2845 Str += "ARMv8.2a";
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002846 else if (FBS[AArch64::HasV8_3aOps])
2847 Str += "ARMv8.3a";
2848 else if (FBS[AArch64::HasV8_4aOps])
2849 Str += "ARMv8.4a";
Oliver Stannard89b16042018-09-26 13:52:27 +00002850 else if (FBS[AArch64::HasV8_5aOps])
2851 Str += "ARMv8.5a";
2852 else {
2853 auto ext = std::find_if(std::begin(ExtensionMap),
2854 std::end(ExtensionMap),
2855 [&](const Extension& e)
2856 // Use & in case multiple features are enabled
2857 { return (FBS & e.Features) != FeatureBitset(); }
2858 );
2859
2860 Str += ext != std::end(ExtensionMap) ? ext->Name : "(unknown)";
2861 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002862}
2863
2864void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2865 SMLoc S) {
2866 const uint16_t Op2 = Encoding & 7;
2867 const uint16_t Cm = (Encoding & 0x78) >> 3;
2868 const uint16_t Cn = (Encoding & 0x780) >> 7;
2869 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2870
2871 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2872
2873 Operands.push_back(
2874 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2875 Operands.push_back(
2876 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2877 Operands.push_back(
2878 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2879 Expr = MCConstantExpr::create(Op2, getContext());
2880 Operands.push_back(
2881 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2882}
2883
Tim Northover3b0846e2014-05-24 12:50:23 +00002884/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2885/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2886bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2887 OperandVector &Operands) {
2888 if (Name.find('.') != StringRef::npos)
2889 return TokError("invalid operand");
2890
2891 Mnemonic = Name;
2892 Operands.push_back(
2893 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2894
Rafael Espindola961d4692014-11-11 05:18:41 +00002895 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002896 const AsmToken &Tok = Parser.getTok();
2897 StringRef Op = Tok.getString();
2898 SMLoc S = Tok.getLoc();
2899
Tim Northover3b0846e2014-05-24 12:50:23 +00002900 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002901 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2902 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002903 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002904 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2905 std::string Str("IC " + std::string(IC->Name) + " requires ");
2906 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2907 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002908 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002909 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002910 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002911 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2912 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002913 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002914 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2915 std::string Str("DC " + std::string(DC->Name) + " requires ");
2916 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2917 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002918 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002919 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002920 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002921 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2922 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002923 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002924 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2925 std::string Str("AT " + std::string(AT->Name) + " requires ");
2926 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2927 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002928 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002929 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002930 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002931 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2932 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002933 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002934 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2935 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2936 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2937 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002938 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002939 createSysAlias(TLBI->Encoding, Operands, S);
Oliver Stannard224428c2018-09-27 13:47:40 +00002940 } else if (Mnemonic == "cfp" || Mnemonic == "dvp" || Mnemonic == "cpp") {
2941 const AArch64PRCTX::PRCTX *PRCTX = AArch64PRCTX::lookupPRCTXByName(Op);
2942 if (!PRCTX)
2943 return TokError("invalid operand for prediction restriction instruction");
2944 else if (!PRCTX->haveFeatures(getSTI().getFeatureBits())) {
2945 std::string Str(
2946 Mnemonic.upper() + std::string(PRCTX->Name) + " requires ");
2947 setRequiredFeatureString(PRCTX->getRequiredFeatures(), Str);
2948 return TokError(Str.c_str());
2949 }
2950 uint16_t PRCTX_Op2 =
2951 Mnemonic == "cfp" ? 4 :
2952 Mnemonic == "dvp" ? 5 :
2953 Mnemonic == "cpp" ? 7 :
2954 0;
2955 assert(PRCTX_Op2 && "Invalid mnemonic for prediction restriction instruction");
2956 createSysAlias(PRCTX->Encoding << 3 | PRCTX_Op2 , Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002957 }
2958
Tim Northover3b0846e2014-05-24 12:50:23 +00002959 Parser.Lex(); // Eat operand.
2960
2961 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2962 bool HasRegister = false;
2963
2964 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002965 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002966 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2967 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002968 HasRegister = true;
2969 }
2970
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002971 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002972 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002973 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002974 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002975
Nirav Davee833c6c2016-11-08 18:31:04 +00002976 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2977 return true;
2978
Tim Northover3b0846e2014-05-24 12:50:23 +00002979 return false;
2980}
2981
Alex Bradbury58eba092016-11-01 16:32:05 +00002982OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002983AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002984 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002985 const AsmToken &Tok = Parser.getTok();
2986
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002987 if (Mnemonic == "tsb" && Tok.isNot(AsmToken::Identifier)) {
2988 TokError("'csync' operand expected");
2989 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002990 // Can be either a #imm style literal or an option name
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002991 } else if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002992 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002993 const MCExpr *ImmVal;
2994 SMLoc ExprLoc = getLoc();
2995 if (getParser().parseExpression(ImmVal))
2996 return MatchOperand_ParseFail;
2997 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2998 if (!MCE) {
2999 Error(ExprLoc, "immediate value expected for barrier operand");
3000 return MatchOperand_ParseFail;
3001 }
3002 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
3003 Error(ExprLoc, "barrier operand out of range");
3004 return MatchOperand_ParseFail;
3005 }
Tim Northovere6ae6762016-07-05 21:23:04 +00003006 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
3007 Operands.push_back(AArch64Operand::CreateBarrier(
3008 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003009 return MatchOperand_Success;
3010 }
3011
3012 if (Tok.isNot(AsmToken::Identifier)) {
3013 TokError("invalid operand for instruction");
3014 return MatchOperand_ParseFail;
3015 }
3016
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003017 auto TSB = AArch64TSB::lookupTSBByName(Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003018 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00003019 auto DB = AArch64DB::lookupDBByName(Tok.getString());
3020 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003021 TokError("'sy' or #imm operand expected");
3022 return MatchOperand_ParseFail;
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003023 // The only valid named option for TSB is 'csync'
3024 } else if (Mnemonic == "tsb" && (!TSB || TSB->Encoding != AArch64TSB::csync)) {
3025 TokError("'csync' operand expected");
3026 return MatchOperand_ParseFail;
3027 } else if (!DB && !TSB) {
Sjoerd Meijere5b85572017-04-24 08:22:20 +00003028 TokError("invalid barrier option name");
3029 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003030 }
3031
Tim Northovere6ae6762016-07-05 21:23:04 +00003032 Operands.push_back(AArch64Operand::CreateBarrier(
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003033 DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003034 Parser.Lex(); // Consume the option
3035
3036 return MatchOperand_Success;
3037}
3038
Alex Bradbury58eba092016-11-01 16:32:05 +00003039OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003040AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003041 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003042 const AsmToken &Tok = Parser.getTok();
3043
3044 if (Tok.isNot(AsmToken::Identifier))
3045 return MatchOperand_NoMatch;
3046
Tim Northovere6ae6762016-07-05 21:23:04 +00003047 int MRSReg, MSRReg;
3048 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
3049 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
3050 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
3051 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
3052 } else
3053 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00003054
Tim Northovere6ae6762016-07-05 21:23:04 +00003055 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
3056 unsigned PStateImm = -1;
3057 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
3058 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00003059
Tim Northovere6ae6762016-07-05 21:23:04 +00003060 Operands.push_back(
3061 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
3062 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003063 Parser.Lex(); // Eat identifier
3064
3065 return MatchOperand_Success;
3066}
3067
Florian Hahnc4422242017-11-07 13:07:50 +00003068/// tryParseNeonVectorRegister - Parse a vector register operand.
3069bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003070 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003071 if (Parser.getTok().isNot(AsmToken::Identifier))
3072 return true;
3073
3074 SMLoc S = getLoc();
3075 // Check for a vector register specifier first.
3076 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003077 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00003078 OperandMatchResultTy Res =
3079 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
3080 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00003081 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00003082
3083 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
3084 if (!KindRes)
3085 return true;
3086
3087 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00003088 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00003089 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
3090 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00003091
Tim Northover3b0846e2014-05-24 12:50:23 +00003092 // If there was an explicit qualifier, that goes on as a literal text
3093 // operand.
3094 if (!Kind.empty())
3095 Operands.push_back(
3096 AArch64Operand::CreateToken(Kind, false, S, getContext()));
3097
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003098 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3099}
3100
3101OperandMatchResultTy
3102AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00003103 SMLoc SIdx = getLoc();
3104 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003105 const MCExpr *ImmVal;
3106 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003107 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00003108 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3109 if (!MCE) {
3110 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003111 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00003112 }
3113
3114 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003115
Nirav Davee833c6c2016-11-08 18:31:04 +00003116 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003117 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00003118
3119 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
3120 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003121 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003122 }
3123
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003124 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00003125}
3126
Sander de Smalen73937b72018-04-11 07:36:10 +00003127// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00003128// optional kind specifier. If it is a register specifier, eat the token
3129// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00003130OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00003131AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00003132 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00003133 MCAsmParser &Parser = getParser();
3134 const AsmToken &Tok = Parser.getTok();
3135
Florian Hahn91f11e52017-11-07 16:45:48 +00003136 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00003137 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003138
3139 StringRef Name = Tok.getString();
3140 // If there is a kind specifier, it's separated from the register name by
3141 // a '.'.
3142 size_t Start = 0, Next = Name.find('.');
3143 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00003144 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00003145
3146 if (RegNum) {
3147 if (Next != StringRef::npos) {
3148 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00003149 if (!isValidVectorKind(Kind, MatchKind)) {
3150 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00003151 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00003152 }
3153 }
Sander de Smalen8e607342017-11-15 15:44:43 +00003154 Parser.Lex(); // Eat the register token.
3155
3156 Reg = RegNum;
3157 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00003158 }
3159
Sander de Smalen8e607342017-11-15 15:44:43 +00003160 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003161}
3162
Sander de Smalencd6be962017-12-20 11:02:42 +00003163/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
3164OperandMatchResultTy
3165AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
3166 // Check for a SVE predicate register specifier first.
3167 const SMLoc S = getLoc();
3168 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003169 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00003170 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00003171 if (Res != MatchOperand_Success)
3172 return Res;
3173
Sander de Smalen73937b72018-04-11 07:36:10 +00003174 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
3175 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00003176 return MatchOperand_NoMatch;
3177
Sander de Smalen73937b72018-04-11 07:36:10 +00003178 unsigned ElementWidth = KindRes->second;
3179 Operands.push_back(AArch64Operand::CreateVectorReg(
3180 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
3181 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00003182
Sander de Smalen7868e742018-01-09 11:17:06 +00003183 // Not all predicates are followed by a '/m' or '/z'.
3184 MCAsmParser &Parser = getParser();
3185 if (Parser.getTok().isNot(AsmToken::Slash))
3186 return MatchOperand_Success;
3187
3188 // But when they do they shouldn't have an element type suffix.
3189 if (!Kind.empty()) {
3190 Error(S, "not expecting size suffix");
3191 return MatchOperand_ParseFail;
3192 }
3193
3194 // Add a literal slash as operand
3195 Operands.push_back(
3196 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
3197
3198 Parser.Lex(); // Eat the slash.
3199
3200 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00003201 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00003202 if (Pred != "z" && Pred != "m") {
3203 Error(getLoc(), "expecting 'm' or 'z' predication");
3204 return MatchOperand_ParseFail;
3205 }
3206
3207 // Add zero/merge token.
3208 const char *ZM = Pred == "z" ? "z" : "m";
3209 Operands.push_back(
3210 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
3211
3212 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00003213 return MatchOperand_Success;
3214}
3215
Sander de Smalen50d87022018-04-19 07:35:08 +00003216/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00003217bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003218 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00003219 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00003220 return false;
3221
Sander de Smalen149916d2018-04-20 07:24:20 +00003222 // Otherwise try for a scalar register.
3223 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
3224 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003225
Sander de Smalen149916d2018-04-20 07:24:20 +00003226 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003227}
3228
3229bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003230 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003231 bool HasELFModifier = false;
3232 AArch64MCExpr::VariantKind RefKind;
3233
Nirav Davee833c6c2016-11-08 18:31:04 +00003234 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003235 HasELFModifier = true;
3236
Nirav Davee833c6c2016-11-08 18:31:04 +00003237 if (Parser.getTok().isNot(AsmToken::Identifier))
3238 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003239
3240 std::string LowerCase = Parser.getTok().getIdentifier().lower();
3241 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
3242 .Case("lo12", AArch64MCExpr::VK_LO12)
3243 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
3244 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
3245 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
3246 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
3247 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
3248 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
3249 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
3250 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
3251 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
3252 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
3253 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
3254 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
3255 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3256 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3257 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3258 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3259 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3260 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3261 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3262 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3263 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3264 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3265 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3266 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3267 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3268 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3269 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3270 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3271 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3272 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3273 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3274 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3275 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3276 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003277 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3278 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00003279 .Default(AArch64MCExpr::VK_INVALID);
3280
Nirav Davee833c6c2016-11-08 18:31:04 +00003281 if (RefKind == AArch64MCExpr::VK_INVALID)
3282 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003283
3284 Parser.Lex(); // Eat identifier
3285
Nirav Davee833c6c2016-11-08 18:31:04 +00003286 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003287 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003288 }
3289
3290 if (getParser().parseExpression(ImmVal))
3291 return true;
3292
3293 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003294 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003295
3296 return false;
3297}
3298
Sander de Smalen650234b2018-04-12 11:40:52 +00003299template <RegKind VectorKind>
3300OperandMatchResultTy
3301AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3302 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003303 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003304 if (!Parser.getTok().is(AsmToken::LCurly))
3305 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003306
3307 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003308 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003309 bool NoMatchIsError) {
3310 auto RegTok = Parser.getTok();
3311 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3312 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003313 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003314 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003315 llvm_unreachable("Expected a valid vector kind");
3316 }
3317
Sander de Smalen650234b2018-04-12 11:40:52 +00003318 if (RegTok.isNot(AsmToken::Identifier) ||
3319 ParseRes == MatchOperand_ParseFail ||
3320 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3321 Error(Loc, "vector register expected");
3322 return MatchOperand_ParseFail;
3323 }
3324
3325 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003326 };
3327
Tim Northover3b0846e2014-05-24 12:50:23 +00003328 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003329 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003330 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003331
Tim Northover3b0846e2014-05-24 12:50:23 +00003332 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003333 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003334 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3335
3336 // Put back the original left bracket if there was no match, so that
3337 // different types of list-operands can be matched (e.g. SVE, Neon).
3338 if (ParseRes == MatchOperand_NoMatch)
3339 Parser.getLexer().UnLex(LCurly);
3340
3341 if (ParseRes != MatchOperand_Success)
3342 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003343
Tim Northover3b0846e2014-05-24 12:50:23 +00003344 int64_t PrevReg = FirstReg;
3345 unsigned Count = 1;
3346
Nirav Davee833c6c2016-11-08 18:31:04 +00003347 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003348 SMLoc Loc = getLoc();
3349 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003350
Sander de Smalen50d87022018-04-19 07:35:08 +00003351 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003352 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3353 if (ParseRes != MatchOperand_Success)
3354 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003355
Tim Northover3b0846e2014-05-24 12:50:23 +00003356 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003357 if (Kind != NextKind) {
3358 Error(Loc, "mismatched register size suffix");
3359 return MatchOperand_ParseFail;
3360 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003361
3362 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3363
3364 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003365 Error(Loc, "invalid number of vectors");
3366 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003367 }
3368
3369 Count += Space;
3370 }
3371 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003372 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003373 SMLoc Loc = getLoc();
3374 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003375 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003376 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3377 if (ParseRes != MatchOperand_Success)
3378 return ParseRes;
3379
Tim Northover3b0846e2014-05-24 12:50:23 +00003380 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003381 if (Kind != NextKind) {
3382 Error(Loc, "mismatched register size suffix");
3383 return MatchOperand_ParseFail;
3384 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003385
3386 // Registers must be incremental (with wraparound at 31)
3387 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003388 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3389 Error(Loc, "registers must be sequential");
3390 return MatchOperand_ParseFail;
3391 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003392
3393 PrevReg = Reg;
3394 ++Count;
3395 }
3396 }
3397
Nirav Davee833c6c2016-11-08 18:31:04 +00003398 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003399 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003400
Sander de Smalen650234b2018-04-12 11:40:52 +00003401 if (Count > 4) {
3402 Error(S, "invalid number of vectors");
3403 return MatchOperand_ParseFail;
3404 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003405
3406 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003407 unsigned ElementWidth = 0;
3408 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003409 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003410 std::tie(NumElements, ElementWidth) = *VK;
3411 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003412
3413 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003414 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3415 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003416
Sander de Smalen650234b2018-04-12 11:40:52 +00003417 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003418}
3419
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003420/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3421bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003422 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3423 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003424 return true;
3425
3426 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3427}
3428
Alex Bradbury58eba092016-11-01 16:32:05 +00003429OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003430AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003431 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003432
Sander de Smalen50d87022018-04-19 07:35:08 +00003433 unsigned RegNum;
3434 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3435 if (Res != MatchOperand_Success)
3436 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003437
Nirav Davee833c6c2016-11-08 18:31:04 +00003438 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003439 Operands.push_back(AArch64Operand::CreateReg(
3440 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003441 return MatchOperand_Success;
3442 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003443
Nirav Davee833c6c2016-11-08 18:31:04 +00003444 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003445
Sander de Smalen50d87022018-04-19 07:35:08 +00003446 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003447 Error(getLoc(), "index must be absent or #0");
3448 return MatchOperand_ParseFail;
3449 }
3450
3451 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003452 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003453 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3454 Error(getLoc(), "index must be absent or #0");
3455 return MatchOperand_ParseFail;
3456 }
3457
Sander de Smalen50d87022018-04-19 07:35:08 +00003458 Operands.push_back(AArch64Operand::CreateReg(
3459 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003460 return MatchOperand_Success;
3461}
3462
Sander de Smalen0325e302018-07-02 07:34:52 +00003463template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
Sander de Smalen149916d2018-04-20 07:24:20 +00003464OperandMatchResultTy
3465AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3466 SMLoc StartLoc = getLoc();
3467
3468 unsigned RegNum;
3469 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3470 if (Res != MatchOperand_Success)
3471 return Res;
3472
3473 // No shift/extend is the default.
3474 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3475 Operands.push_back(AArch64Operand::CreateReg(
Sander de Smalen0325e302018-07-02 07:34:52 +00003476 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
Sander de Smalen149916d2018-04-20 07:24:20 +00003477 return MatchOperand_Success;
3478 }
3479
3480 // Eat the comma
3481 getParser().Lex();
3482
3483 // Match the shift
3484 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3485 Res = tryParseOptionalShiftExtend(ExtOpnd);
3486 if (Res != MatchOperand_Success)
3487 return Res;
3488
3489 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
Sander de Smalen0325e302018-07-02 07:34:52 +00003490 Operands.push_back(AArch64Operand::CreateReg(
3491 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3492 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3493 Ext->hasShiftExtendAmount()));
Sander de Smalen149916d2018-04-20 07:24:20 +00003494
3495 return MatchOperand_Success;
3496}
3497
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003498bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
Sander de Smalen5c625982018-04-13 12:56:14 +00003499 MCAsmParser &Parser = getParser();
3500
3501 // Some SVE instructions have a decoration after the immediate, i.e.
3502 // "mul vl". We parse them here and add tokens, which must be present in the
3503 // asm string in the tablegen instruction.
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003504 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3505 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
Sander de Smalen5c625982018-04-13 12:56:14 +00003506 if (!Parser.getTok().getString().equals_lower("mul") ||
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003507 !(NextIsVL || NextIsHash))
Sander de Smalen5c625982018-04-13 12:56:14 +00003508 return true;
3509
Sander de Smalen5c625982018-04-13 12:56:14 +00003510 Operands.push_back(
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003511 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
Sander de Smalen5c625982018-04-13 12:56:14 +00003512 Parser.Lex(); // Eat the "mul"
3513
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003514 if (NextIsVL) {
3515 Operands.push_back(
3516 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3517 Parser.Lex(); // Eat the "vl"
3518 return false;
3519 }
Sander de Smalen5c625982018-04-13 12:56:14 +00003520
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003521 if (NextIsHash) {
3522 Parser.Lex(); // Eat the #
3523 SMLoc S = getLoc();
3524
3525 // Parse immediate operand.
3526 const MCExpr *ImmVal;
3527 if (!Parser.parseExpression(ImmVal))
3528 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3529 Operands.push_back(AArch64Operand::CreateImm(
3530 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3531 getContext()));
3532 return MatchOperand_Success;
3533 }
3534 }
3535
3536 return Error(getLoc(), "expected 'vl' or '#<imm>'");
Sander de Smalen5c625982018-04-13 12:56:14 +00003537}
3538
Tim Northover3b0846e2014-05-24 12:50:23 +00003539/// parseOperand - Parse a arm instruction operand. For now this parses the
3540/// operand regardless of the mnemonic.
3541bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3542 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003543 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003544
3545 OperandMatchResultTy ResTy =
3546 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3547
Tim Northover3b0846e2014-05-24 12:50:23 +00003548 // Check if the current operand has a custom associated parser, if so, try to
3549 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003550 if (ResTy == MatchOperand_Success)
3551 return false;
3552 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3553 // there was a match, but an error occurred, in which case, just return that
3554 // the operand parsing failed.
3555 if (ResTy == MatchOperand_ParseFail)
3556 return true;
3557
3558 // Nothing custom, so do general case parsing.
3559 SMLoc S, E;
3560 switch (getLexer().getKind()) {
3561 default: {
3562 SMLoc S = getLoc();
3563 const MCExpr *Expr;
3564 if (parseSymbolicImmVal(Expr))
3565 return Error(S, "invalid operand");
3566
3567 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3568 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3569 return false;
3570 }
3571 case AsmToken::LBrac: {
3572 SMLoc Loc = Parser.getTok().getLoc();
3573 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3574 getContext()));
3575 Parser.Lex(); // Eat '['
3576
3577 // There's no comma after a '[', so we can parse the next operand
3578 // immediately.
3579 return parseOperand(Operands, false, false);
3580 }
3581 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003582 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003583 case AsmToken::Identifier: {
3584 // If we're expecting a Condition Code operand, then just parse that.
3585 if (isCondCode)
3586 return parseCondCode(Operands, invertCondCode);
3587
3588 // If it's a register name, parse it.
3589 if (!parseRegister(Operands))
3590 return false;
3591
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003592 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3593 // by SVE instructions.
3594 if (!parseOptionalMulOperand(Operands))
Sander de Smalen5c625982018-04-13 12:56:14 +00003595 return false;
3596
Tim Northover3b0846e2014-05-24 12:50:23 +00003597 // This could be an optional "shift" or "extend" operand.
3598 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3599 // We can only continue if no tokens were eaten.
3600 if (GotShift != MatchOperand_NoMatch)
3601 return GotShift;
3602
3603 // This was not a register so parse other operands that start with an
3604 // identifier (like labels) as expressions and create them as immediates.
3605 const MCExpr *IdVal;
3606 S = getLoc();
3607 if (getParser().parseExpression(IdVal))
3608 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003609 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3610 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3611 return false;
3612 }
3613 case AsmToken::Integer:
3614 case AsmToken::Real:
3615 case AsmToken::Hash: {
3616 // #42 -> immediate.
3617 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003618
3619 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003620
3621 // Parse a negative sign
3622 bool isNegative = false;
3623 if (Parser.getTok().is(AsmToken::Minus)) {
3624 isNegative = true;
3625 // We need to consume this token only when we have a Real, otherwise
3626 // we let parseSymbolicImmVal take care of it
3627 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3628 Parser.Lex();
3629 }
3630
3631 // The only Real that should come through here is a literal #0.0 for
3632 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3633 // so convert the value.
3634 const AsmToken &Tok = Parser.getTok();
3635 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003636 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003637 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3638 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3639 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
Sander de Smalen8fcc3f52018-07-03 09:07:23 +00003640 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
Tim Northover3b0846e2014-05-24 12:50:23 +00003641 return TokError("unexpected floating point literal");
3642 else if (IntVal != 0 || isNegative)
3643 return TokError("expected floating-point constant #0.0");
3644 Parser.Lex(); // Eat the token.
3645
3646 Operands.push_back(
3647 AArch64Operand::CreateToken("#0", false, S, getContext()));
3648 Operands.push_back(
3649 AArch64Operand::CreateToken(".0", false, S, getContext()));
3650 return false;
3651 }
3652
3653 const MCExpr *ImmVal;
3654 if (parseSymbolicImmVal(ImmVal))
3655 return true;
3656
3657 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3658 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3659 return false;
3660 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003661 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003662 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003663 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003664 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003665 Parser.Lex(); // Eat '='
3666 const MCExpr *SubExprVal;
3667 if (getParser().parseExpression(SubExprVal))
3668 return true;
3669
David Peixottoae5ba762014-07-18 16:05:14 +00003670 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003671 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003672 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003673
3674 bool IsXReg =
3675 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3676 Operands[1]->getReg());
3677
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003678 MCContext& Ctx = getContext();
3679 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3680 // If the op is an imm and can be fit into a mov, then replace ldr with mov.
David Peixottoae5ba762014-07-18 16:05:14 +00003681 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003682 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3683 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3684 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3685 ShiftAmt += 16;
3686 Imm >>= 16;
3687 }
3688 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3689 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3690 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003691 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003692 if (ShiftAmt)
3693 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3694 ShiftAmt, true, S, E, Ctx));
3695 return false;
3696 }
David Peixottoae5ba762014-07-18 16:05:14 +00003697 APInt Simm = APInt(64, Imm << ShiftAmt);
3698 // check if the immediate is an unsigned or signed 32-bit int for W regs
3699 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3700 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003701 }
3702 // If it is a label or an imm that cannot fit in a movz, put it into CP.
David Peixottoae5ba762014-07-18 16:05:14 +00003703 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003704 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003705 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3706 return false;
3707 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003708 }
3709}
3710
Sander de Smalen0325e302018-07-02 07:34:52 +00003711bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3712 const MCParsedAsmOperand &Op2) const {
3713 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3714 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3715 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3716 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3717 return MCTargetAsmParser::regsEqual(Op1, Op2);
3718
3719 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3720 "Testing equality of non-scalar registers not supported");
3721
3722 // Check if a registers match their sub/super register classes.
3723 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3724 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3725 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3726 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3727 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3728 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3729 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3730 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3731
3732 return false;
3733}
3734
Tim Northover3b0846e2014-05-24 12:50:23 +00003735/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3736/// operands.
3737bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3738 StringRef Name, SMLoc NameLoc,
3739 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003740 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003741 Name = StringSwitch<StringRef>(Name.lower())
3742 .Case("beq", "b.eq")
3743 .Case("bne", "b.ne")
3744 .Case("bhs", "b.hs")
3745 .Case("bcs", "b.cs")
3746 .Case("blo", "b.lo")
3747 .Case("bcc", "b.cc")
3748 .Case("bmi", "b.mi")
3749 .Case("bpl", "b.pl")
3750 .Case("bvs", "b.vs")
3751 .Case("bvc", "b.vc")
3752 .Case("bhi", "b.hi")
3753 .Case("bls", "b.ls")
3754 .Case("bge", "b.ge")
3755 .Case("blt", "b.lt")
3756 .Case("bgt", "b.gt")
3757 .Case("ble", "b.le")
3758 .Case("bal", "b.al")
3759 .Case("bnv", "b.nv")
3760 .Default(Name);
3761
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003762 // First check for the AArch64-specific .req directive.
3763 if (Parser.getTok().is(AsmToken::Identifier) &&
3764 Parser.getTok().getIdentifier() == ".req") {
3765 parseDirectiveReq(Name, NameLoc);
3766 // We always return 'error' for this, as we're done with this
3767 // statement and don't need to match the 'instruction."
3768 return true;
3769 }
3770
Tim Northover3b0846e2014-05-24 12:50:23 +00003771 // Create the leading tokens for the mnemonic, split by '.' characters.
3772 size_t Start = 0, Next = Name.find('.');
3773 StringRef Head = Name.slice(Start, Next);
3774
Oliver Stannard224428c2018-09-27 13:47:40 +00003775 // IC, DC, AT, TLBI and Prediction invalidation instructions are aliases for
3776 // the SYS instruction.
3777 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi" ||
3778 Head == "cfp" || Head == "dvp" || Head == "cpp")
Nirav Davee833c6c2016-11-08 18:31:04 +00003779 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003780
3781 Operands.push_back(
3782 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3783 Mnemonic = Head;
3784
3785 // Handle condition codes for a branch mnemonic
3786 if (Head == "b" && Next != StringRef::npos) {
3787 Start = Next;
3788 Next = Name.find('.', Start + 1);
3789 Head = Name.slice(Start + 1, Next);
3790
3791 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3792 (Head.data() - Name.data()));
3793 AArch64CC::CondCode CC = parseCondCodeString(Head);
3794 if (CC == AArch64CC::Invalid)
3795 return Error(SuffixLoc, "invalid condition code");
3796 Operands.push_back(
3797 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3798 Operands.push_back(
3799 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3800 }
3801
3802 // Add the remaining tokens in the mnemonic.
3803 while (Next != StringRef::npos) {
3804 Start = Next;
3805 Next = Name.find('.', Start + 1);
3806 Head = Name.slice(Start, Next);
3807 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3808 (Head.data() - Name.data()) + 1);
3809 Operands.push_back(
3810 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3811 }
3812
3813 // Conditional compare instructions have a Condition Code operand, which needs
3814 // to be parsed and an immediate operand created.
3815 bool condCodeFourthOperand =
3816 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3817 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3818 Head == "csinc" || Head == "csinv" || Head == "csneg");
3819
3820 // These instructions are aliases to some of the conditional select
3821 // instructions. However, the condition code is inverted in the aliased
3822 // instruction.
3823 //
3824 // FIXME: Is this the correct way to handle these? Or should the parser
3825 // generate the aliased instructions directly?
3826 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3827 bool condCodeThirdOperand =
3828 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3829
3830 // Read the remaining operands.
3831 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003832
Oliver Stannardc4190282018-10-02 10:04:39 +00003833 unsigned N = 1;
3834 do {
Tim Northover3b0846e2014-05-24 12:50:23 +00003835 // Parse and remember the operand.
3836 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3837 (N == 3 && condCodeThirdOperand) ||
3838 (N == 2 && condCodeSecondOperand),
3839 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003840 return true;
3841 }
3842
3843 // After successfully parsing some operands there are two special cases to
3844 // consider (i.e. notional operands not separated by commas). Both are due
3845 // to memory specifiers:
3846 // + An RBrac will end an address for load/store/prefetch
3847 // + An '!' will indicate a pre-indexed operation.
3848 //
3849 // It's someone else's responsibility to make sure these tokens are sane
3850 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003851
Nirav Davee833c6c2016-11-08 18:31:04 +00003852 SMLoc RLoc = Parser.getTok().getLoc();
3853 if (parseOptionalToken(AsmToken::RBrac))
3854 Operands.push_back(
3855 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3856 SMLoc ELoc = Parser.getTok().getLoc();
3857 if (parseOptionalToken(AsmToken::Exclaim))
3858 Operands.push_back(
3859 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003860
3861 ++N;
Oliver Stannardc4190282018-10-02 10:04:39 +00003862 } while (parseOptionalToken(AsmToken::Comma));
Tim Northover3b0846e2014-05-24 12:50:23 +00003863 }
3864
Nirav Davee833c6c2016-11-08 18:31:04 +00003865 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3866 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003867
Tim Northover3b0846e2014-05-24 12:50:23 +00003868 return false;
3869}
3870
Sander de Smalen9b333092018-07-30 15:42:46 +00003871static inline bool isMatchingOrAlias(unsigned ZReg, unsigned Reg) {
3872 assert((ZReg >= AArch64::Z0) && (ZReg <= AArch64::Z31));
3873 return (ZReg == ((Reg - AArch64::B0) + AArch64::Z0)) ||
3874 (ZReg == ((Reg - AArch64::H0) + AArch64::Z0)) ||
3875 (ZReg == ((Reg - AArch64::S0) + AArch64::Z0)) ||
3876 (ZReg == ((Reg - AArch64::D0) + AArch64::Z0)) ||
3877 (ZReg == ((Reg - AArch64::Q0) + AArch64::Z0)) ||
3878 (ZReg == ((Reg - AArch64::Z0) + AArch64::Z0));
3879}
3880
Tim Northover3b0846e2014-05-24 12:50:23 +00003881// FIXME: This entire function is a giant hack to provide us with decent
3882// operand range validation/diagnostics until TableGen/MC can be extended
3883// to support autogeneration of this kind of validation.
Sander de Smalen9b333092018-07-30 15:42:46 +00003884bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
3885 SmallVectorImpl<SMLoc> &Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003886 const MCRegisterInfo *RI = getContext().getRegisterInfo();
Sander de Smalen9b333092018-07-30 15:42:46 +00003887 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
3888
3889 // A prefix only applies to the instruction following it. Here we extract
3890 // prefix information for the next instruction before validating the current
3891 // one so that in the case of failure we don't erronously continue using the
3892 // current prefix.
3893 PrefixInfo Prefix = NextPrefix;
3894 NextPrefix = PrefixInfo::CreateFromInst(Inst, MCID.TSFlags);
3895
3896 // Before validating the instruction in isolation we run through the rules
3897 // applicable when it follows a prefix instruction.
3898 // NOTE: brk & hlt can be prefixed but require no additional validation.
3899 if (Prefix.isActive() &&
3900 (Inst.getOpcode() != AArch64::BRK) &&
3901 (Inst.getOpcode() != AArch64::HLT)) {
3902
3903 // Prefixed intructions must have a destructive operand.
3904 if ((MCID.TSFlags & AArch64::DestructiveInstTypeMask) ==
3905 AArch64::NotDestructive)
3906 return Error(IDLoc, "instruction is unpredictable when following a"
3907 " movprfx, suggest replacing movprfx with mov");
3908
3909 // Destination operands must match.
3910 if (Inst.getOperand(0).getReg() != Prefix.getDstReg())
3911 return Error(Loc[0], "instruction is unpredictable when following a"
3912 " movprfx writing to a different destination");
3913
3914 // Destination operand must not be used in any other location.
3915 for (unsigned i = 1; i < Inst.getNumOperands(); ++i) {
3916 if (Inst.getOperand(i).isReg() &&
3917 (MCID.getOperandConstraint(i, MCOI::TIED_TO) == -1) &&
3918 isMatchingOrAlias(Prefix.getDstReg(), Inst.getOperand(i).getReg()))
3919 return Error(Loc[0], "instruction is unpredictable when following a"
3920 " movprfx and destination also used as non-destructive"
3921 " source");
3922 }
3923
3924 auto PPRRegClass = AArch64MCRegisterClasses[AArch64::PPRRegClassID];
3925 if (Prefix.isPredicated()) {
3926 int PgIdx = -1;
3927
3928 // Find the instructions general predicate.
3929 for (unsigned i = 1; i < Inst.getNumOperands(); ++i)
3930 if (Inst.getOperand(i).isReg() &&
3931 PPRRegClass.contains(Inst.getOperand(i).getReg())) {
3932 PgIdx = i;
3933 break;
3934 }
3935
3936 // Instruction must be predicated if the movprfx is predicated.
3937 if (PgIdx == -1 ||
3938 (MCID.TSFlags & AArch64::ElementSizeMask) == AArch64::ElementSizeNone)
3939 return Error(IDLoc, "instruction is unpredictable when following a"
3940 " predicated movprfx, suggest using unpredicated movprfx");
3941
3942 // Instruction must use same general predicate as the movprfx.
3943 if (Inst.getOperand(PgIdx).getReg() != Prefix.getPgReg())
3944 return Error(IDLoc, "instruction is unpredictable when following a"
3945 " predicated movprfx using a different general predicate");
3946
3947 // Instruction element type must match the movprfx.
3948 if ((MCID.TSFlags & AArch64::ElementSizeMask) != Prefix.getElementSize())
3949 return Error(IDLoc, "instruction is unpredictable when following a"
3950 " predicated movprfx with a different element size");
3951 }
3952 }
3953
Tim Northover3b0846e2014-05-24 12:50:23 +00003954 // Check for indexed addressing modes w/ the base register being the
3955 // same as a destination/source register or pair load where
3956 // the Rt == Rt2. All of those are undefined behaviour.
3957 switch (Inst.getOpcode()) {
3958 case AArch64::LDPSWpre:
3959 case AArch64::LDPWpost:
3960 case AArch64::LDPWpre:
3961 case AArch64::LDPXpost:
3962 case AArch64::LDPXpre: {
3963 unsigned Rt = Inst.getOperand(1).getReg();
3964 unsigned Rt2 = Inst.getOperand(2).getReg();
3965 unsigned Rn = Inst.getOperand(3).getReg();
3966 if (RI->isSubRegisterEq(Rn, Rt))
3967 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3968 "is also a destination");
3969 if (RI->isSubRegisterEq(Rn, Rt2))
3970 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3971 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003972 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003973 }
3974 case AArch64::LDPDi:
3975 case AArch64::LDPQi:
3976 case AArch64::LDPSi:
3977 case AArch64::LDPSWi:
3978 case AArch64::LDPWi:
3979 case AArch64::LDPXi: {
3980 unsigned Rt = Inst.getOperand(0).getReg();
3981 unsigned Rt2 = Inst.getOperand(1).getReg();
3982 if (Rt == Rt2)
3983 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3984 break;
3985 }
3986 case AArch64::LDPDpost:
3987 case AArch64::LDPDpre:
3988 case AArch64::LDPQpost:
3989 case AArch64::LDPQpre:
3990 case AArch64::LDPSpost:
3991 case AArch64::LDPSpre:
3992 case AArch64::LDPSWpost: {
3993 unsigned Rt = Inst.getOperand(1).getReg();
3994 unsigned Rt2 = Inst.getOperand(2).getReg();
3995 if (Rt == Rt2)
3996 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3997 break;
3998 }
3999 case AArch64::STPDpost:
4000 case AArch64::STPDpre:
4001 case AArch64::STPQpost:
4002 case AArch64::STPQpre:
4003 case AArch64::STPSpost:
4004 case AArch64::STPSpre:
4005 case AArch64::STPWpost:
4006 case AArch64::STPWpre:
4007 case AArch64::STPXpost:
4008 case AArch64::STPXpre: {
4009 unsigned Rt = Inst.getOperand(1).getReg();
4010 unsigned Rt2 = Inst.getOperand(2).getReg();
4011 unsigned Rn = Inst.getOperand(3).getReg();
4012 if (RI->isSubRegisterEq(Rn, Rt))
4013 return Error(Loc[0], "unpredictable STP instruction, writeback base "
4014 "is also a source");
4015 if (RI->isSubRegisterEq(Rn, Rt2))
4016 return Error(Loc[1], "unpredictable STP instruction, writeback base "
4017 "is also a source");
4018 break;
4019 }
4020 case AArch64::LDRBBpre:
4021 case AArch64::LDRBpre:
4022 case AArch64::LDRHHpre:
4023 case AArch64::LDRHpre:
4024 case AArch64::LDRSBWpre:
4025 case AArch64::LDRSBXpre:
4026 case AArch64::LDRSHWpre:
4027 case AArch64::LDRSHXpre:
4028 case AArch64::LDRSWpre:
4029 case AArch64::LDRWpre:
4030 case AArch64::LDRXpre:
4031 case AArch64::LDRBBpost:
4032 case AArch64::LDRBpost:
4033 case AArch64::LDRHHpost:
4034 case AArch64::LDRHpost:
4035 case AArch64::LDRSBWpost:
4036 case AArch64::LDRSBXpost:
4037 case AArch64::LDRSHWpost:
4038 case AArch64::LDRSHXpost:
4039 case AArch64::LDRSWpost:
4040 case AArch64::LDRWpost:
4041 case AArch64::LDRXpost: {
4042 unsigned Rt = Inst.getOperand(1).getReg();
4043 unsigned Rn = Inst.getOperand(2).getReg();
4044 if (RI->isSubRegisterEq(Rn, Rt))
4045 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
4046 "is also a source");
4047 break;
4048 }
4049 case AArch64::STRBBpost:
4050 case AArch64::STRBpost:
4051 case AArch64::STRHHpost:
4052 case AArch64::STRHpost:
4053 case AArch64::STRWpost:
4054 case AArch64::STRXpost:
4055 case AArch64::STRBBpre:
4056 case AArch64::STRBpre:
4057 case AArch64::STRHHpre:
4058 case AArch64::STRHpre:
4059 case AArch64::STRWpre:
4060 case AArch64::STRXpre: {
4061 unsigned Rt = Inst.getOperand(1).getReg();
4062 unsigned Rn = Inst.getOperand(2).getReg();
4063 if (RI->isSubRegisterEq(Rn, Rt))
4064 return Error(Loc[0], "unpredictable STR instruction, writeback base "
4065 "is also a source");
4066 break;
4067 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004068 case AArch64::STXRB:
4069 case AArch64::STXRH:
4070 case AArch64::STXRW:
4071 case AArch64::STXRX:
4072 case AArch64::STLXRB:
4073 case AArch64::STLXRH:
4074 case AArch64::STLXRW:
4075 case AArch64::STLXRX: {
4076 unsigned Rs = Inst.getOperand(0).getReg();
4077 unsigned Rt = Inst.getOperand(1).getReg();
4078 unsigned Rn = Inst.getOperand(2).getReg();
4079 if (RI->isSubRegisterEq(Rt, Rs) ||
4080 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
4081 return Error(Loc[0],
4082 "unpredictable STXR instruction, status is also a source");
4083 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00004084 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004085 case AArch64::STXPW:
4086 case AArch64::STXPX:
4087 case AArch64::STLXPW:
4088 case AArch64::STLXPX: {
4089 unsigned Rs = Inst.getOperand(0).getReg();
4090 unsigned Rt1 = Inst.getOperand(1).getReg();
4091 unsigned Rt2 = Inst.getOperand(2).getReg();
4092 unsigned Rn = Inst.getOperand(3).getReg();
4093 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
4094 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
4095 return Error(Loc[0],
4096 "unpredictable STXP instruction, status is also a source");
4097 break;
4098 }
Oliver Stannardc4190282018-10-02 10:04:39 +00004099 case AArch64::LDGV: {
4100 unsigned Rt = Inst.getOperand(0).getReg();
4101 unsigned Rn = Inst.getOperand(1).getReg();
4102 if (RI->isSubRegisterEq(Rt, Rn)) {
4103 return Error(Loc[0],
4104 "unpredictable LDGV instruction, writeback register is also "
4105 "the target register");
4106 }
4107 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004108 }
4109
Tim Northover3b0846e2014-05-24 12:50:23 +00004110
4111 // Now check immediate ranges. Separate from the above as there is overlap
4112 // in the instructions being checked and this keeps the nested conditionals
4113 // to a minimum.
4114 switch (Inst.getOpcode()) {
4115 case AArch64::ADDSWri:
4116 case AArch64::ADDSXri:
4117 case AArch64::ADDWri:
4118 case AArch64::ADDXri:
4119 case AArch64::SUBSWri:
4120 case AArch64::SUBSXri:
4121 case AArch64::SUBWri:
4122 case AArch64::SUBXri: {
4123 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
4124 // some slight duplication here.
4125 if (Inst.getOperand(2).isExpr()) {
4126 const MCExpr *Expr = Inst.getOperand(2).getExpr();
4127 AArch64MCExpr::VariantKind ELFRefKind;
4128 MCSymbolRefExpr::VariantKind DarwinRefKind;
4129 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00004130 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
4131
4132 // Only allow these with ADDXri.
4133 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
4134 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
4135 Inst.getOpcode() == AArch64::ADDXri)
4136 return false;
4137
4138 // Only allow these with ADDXri/ADDWri
4139 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
4140 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
4141 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
4142 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
4143 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
4144 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
4145 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00004146 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
4147 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
4148 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00004149 (Inst.getOpcode() == AArch64::ADDXri ||
4150 Inst.getOpcode() == AArch64::ADDWri))
4151 return false;
4152
4153 // Don't allow symbol refs in the immediate field otherwise
4154 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
4155 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
4156 // 'cmp w0, 'borked')
4157 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00004158 }
Diana Picusc93518d2016-10-11 09:17:47 +00004159 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00004160 }
4161 return false;
4162 }
4163 default:
4164 return false;
4165 }
4166}
4167
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004168static std::string AArch64MnemonicSpellCheck(StringRef S,
4169 const FeatureBitset &FBS,
Craig Topper05515562017-10-26 06:46:41 +00004170 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004171
4172bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
Sander de Smalen0325e302018-07-02 07:34:52 +00004173 uint64_t ErrorInfo,
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004174 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004175 switch (ErrCode) {
Sander de Smalen0325e302018-07-02 07:34:52 +00004176 case Match_InvalidTiedOperand: {
4177 RegConstraintEqualityTy EqTy =
4178 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
4179 .getRegEqualityTy();
4180 switch (EqTy) {
4181 case RegConstraintEqualityTy::EqualsSubReg:
4182 return Error(Loc, "operand must be 64-bit form of destination register");
4183 case RegConstraintEqualityTy::EqualsSuperReg:
4184 return Error(Loc, "operand must be 32-bit form of destination register");
4185 case RegConstraintEqualityTy::EqualsReg:
4186 return Error(Loc, "operand must match destination register");
4187 }
Simon Pilgrim6dc45e62018-07-05 09:48:01 +00004188 llvm_unreachable("Unknown RegConstraintEqualityTy");
Sander de Smalen0325e302018-07-02 07:34:52 +00004189 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004190 case Match_MissingFeature:
4191 return Error(Loc,
4192 "instruction requires a CPU feature not currently enabled");
4193 case Match_InvalidOperand:
4194 return Error(Loc, "invalid operand for instruction");
4195 case Match_InvalidSuffix:
4196 return Error(Loc, "invalid type suffix for instruction");
4197 case Match_InvalidCondCode:
4198 return Error(Loc, "expected AArch64 condition code");
4199 case Match_AddSubRegExtendSmall:
4200 return Error(Loc,
4201 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
4202 case Match_AddSubRegExtendLarge:
4203 return Error(Loc,
4204 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
4205 case Match_AddSubSecondSource:
4206 return Error(Loc,
4207 "expected compatible register, symbol or integer in range [0, 4095]");
4208 case Match_LogicalSecondSource:
4209 return Error(Loc, "expected compatible register or logical immediate");
4210 case Match_InvalidMovImm32Shift:
4211 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
4212 case Match_InvalidMovImm64Shift:
4213 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
4214 case Match_AddSubRegShift32:
4215 return Error(Loc,
4216 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
4217 case Match_AddSubRegShift64:
4218 return Error(Loc,
4219 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
4220 case Match_InvalidFPImm:
4221 return Error(Loc,
4222 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00004223 case Match_InvalidMemoryIndexedSImm6:
4224 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00004225 case Match_InvalidMemoryIndexedSImm5:
4226 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00004227 case Match_InvalidMemoryIndexed1SImm4:
4228 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00004229 case Match_InvalidMemoryIndexed2SImm4:
4230 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00004231 case Match_InvalidMemoryIndexed3SImm4:
4232 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00004233 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00004234 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004235 case Match_InvalidMemoryIndexed16SImm4:
4236 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00004237 case Match_InvalidMemoryIndexed1SImm6:
4238 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen592718f2018-07-05 07:54:10 +00004239 case Match_InvalidMemoryIndexedSImm8:
4240 return Error(Loc, "index must be an integer in range [-128, 127].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004241 case Match_InvalidMemoryIndexedSImm9:
4242 return Error(Loc, "index must be an integer in range [-256, 255].");
Oliver Stannardc4190282018-10-02 10:04:39 +00004243 case Match_InvalidMemoryIndexed16SImm9:
4244 return Error(Loc, "index must be a multiple of 16 in range [-4096, 4080].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004245 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00004246 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004247 case Match_InvalidMemoryIndexed4SImm7:
4248 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
4249 case Match_InvalidMemoryIndexed8SImm7:
4250 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
4251 case Match_InvalidMemoryIndexed16SImm7:
4252 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00004253 case Match_InvalidMemoryIndexed8UImm5:
4254 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
4255 case Match_InvalidMemoryIndexed4UImm5:
4256 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
4257 case Match_InvalidMemoryIndexed2UImm5:
4258 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00004259 case Match_InvalidMemoryIndexed8UImm6:
4260 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
Oliver Stannardc4190282018-10-02 10:04:39 +00004261 case Match_InvalidMemoryIndexed16UImm6:
4262 return Error(Loc, "index must be a multiple of 16 in range [0, 1008].");
Sander de Smalend8e76492018-05-08 10:46:55 +00004263 case Match_InvalidMemoryIndexed4UImm6:
4264 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
4265 case Match_InvalidMemoryIndexed2UImm6:
4266 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
4267 case Match_InvalidMemoryIndexed1UImm6:
4268 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004269 case Match_InvalidMemoryWExtend8:
4270 return Error(Loc,
4271 "expected 'uxtw' or 'sxtw' with optional shift of #0");
4272 case Match_InvalidMemoryWExtend16:
4273 return Error(Loc,
4274 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
4275 case Match_InvalidMemoryWExtend32:
4276 return Error(Loc,
4277 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
4278 case Match_InvalidMemoryWExtend64:
4279 return Error(Loc,
4280 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
4281 case Match_InvalidMemoryWExtend128:
4282 return Error(Loc,
4283 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
4284 case Match_InvalidMemoryXExtend8:
4285 return Error(Loc,
4286 "expected 'lsl' or 'sxtx' with optional shift of #0");
4287 case Match_InvalidMemoryXExtend16:
4288 return Error(Loc,
4289 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
4290 case Match_InvalidMemoryXExtend32:
4291 return Error(Loc,
4292 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
4293 case Match_InvalidMemoryXExtend64:
4294 return Error(Loc,
4295 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
4296 case Match_InvalidMemoryXExtend128:
4297 return Error(Loc,
4298 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
4299 case Match_InvalidMemoryIndexed1:
4300 return Error(Loc, "index must be an integer in range [0, 4095].");
4301 case Match_InvalidMemoryIndexed2:
4302 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
4303 case Match_InvalidMemoryIndexed4:
4304 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
4305 case Match_InvalidMemoryIndexed8:
4306 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
4307 case Match_InvalidMemoryIndexed16:
4308 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004309 case Match_InvalidImm0_1:
4310 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004311 case Match_InvalidImm0_7:
4312 return Error(Loc, "immediate must be an integer in range [0, 7].");
4313 case Match_InvalidImm0_15:
4314 return Error(Loc, "immediate must be an integer in range [0, 15].");
4315 case Match_InvalidImm0_31:
4316 return Error(Loc, "immediate must be an integer in range [0, 31].");
4317 case Match_InvalidImm0_63:
4318 return Error(Loc, "immediate must be an integer in range [0, 63].");
4319 case Match_InvalidImm0_127:
4320 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004321 case Match_InvalidImm0_255:
4322 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004323 case Match_InvalidImm0_65535:
4324 return Error(Loc, "immediate must be an integer in range [0, 65535].");
4325 case Match_InvalidImm1_8:
4326 return Error(Loc, "immediate must be an integer in range [1, 8].");
4327 case Match_InvalidImm1_16:
4328 return Error(Loc, "immediate must be an integer in range [1, 16].");
4329 case Match_InvalidImm1_32:
4330 return Error(Loc, "immediate must be an integer in range [1, 32].");
4331 case Match_InvalidImm1_64:
4332 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00004333 case Match_InvalidSVEAddSubImm8:
4334 return Error(Loc, "immediate must be an integer in range [0, 255]"
4335 " with a shift amount of 0");
4336 case Match_InvalidSVEAddSubImm16:
4337 case Match_InvalidSVEAddSubImm32:
4338 case Match_InvalidSVEAddSubImm64:
4339 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
4340 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004341 case Match_InvalidSVECpyImm8:
4342 return Error(Loc, "immediate must be an integer in range [-128, 255]"
4343 " with a shift amount of 0");
4344 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00004345 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4346 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004347 case Match_InvalidSVECpyImm32:
4348 case Match_InvalidSVECpyImm64:
4349 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4350 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004351 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004352 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004353 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00004354 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004355 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00004356 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004357 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004358 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004359 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004360 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004361 case Match_InvalidSVEIndexRange0_63:
4362 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4363 case Match_InvalidSVEIndexRange0_31:
4364 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4365 case Match_InvalidSVEIndexRange0_15:
4366 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4367 case Match_InvalidSVEIndexRange0_7:
4368 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4369 case Match_InvalidSVEIndexRange0_3:
4370 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004371 case Match_InvalidLabel:
4372 return Error(Loc, "expected label or encodable integer pc offset");
4373 case Match_MRS:
4374 return Error(Loc, "expected readable system register");
4375 case Match_MSR:
4376 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00004377 case Match_InvalidComplexRotationEven:
4378 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4379 case Match_InvalidComplexRotationOdd:
4380 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004381 case Match_MnemonicFail: {
4382 std::string Suggestion = AArch64MnemonicSpellCheck(
4383 ((AArch64Operand &)*Operands[0]).getToken(),
4384 ComputeAvailableFeatures(STI->getFeatureBits()));
4385 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4386 }
Sander de Smalen367694b2018-04-20 08:54:49 +00004387 case Match_InvalidGPR64shifted8:
4388 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4389 case Match_InvalidGPR64shifted16:
4390 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4391 case Match_InvalidGPR64shifted32:
4392 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4393 case Match_InvalidGPR64shifted64:
4394 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4395 case Match_InvalidGPR64NoXZRshifted8:
4396 return Error(Loc, "register must be x0..x30 without shift");
4397 case Match_InvalidGPR64NoXZRshifted16:
4398 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4399 case Match_InvalidGPR64NoXZRshifted32:
4400 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4401 case Match_InvalidGPR64NoXZRshifted64:
4402 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004403 case Match_InvalidZPR32UXTW8:
4404 case Match_InvalidZPR32SXTW8:
4405 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4406 case Match_InvalidZPR32UXTW16:
4407 case Match_InvalidZPR32SXTW16:
4408 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4409 case Match_InvalidZPR32UXTW32:
4410 case Match_InvalidZPR32SXTW32:
4411 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4412 case Match_InvalidZPR32UXTW64:
4413 case Match_InvalidZPR32SXTW64:
4414 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4415 case Match_InvalidZPR64UXTW8:
4416 case Match_InvalidZPR64SXTW8:
4417 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4418 case Match_InvalidZPR64UXTW16:
4419 case Match_InvalidZPR64SXTW16:
4420 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4421 case Match_InvalidZPR64UXTW32:
4422 case Match_InvalidZPR64SXTW32:
4423 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4424 case Match_InvalidZPR64UXTW64:
4425 case Match_InvalidZPR64SXTW64:
4426 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
Sander de Smalenc69944c2018-07-09 09:58:24 +00004427 case Match_InvalidZPR32LSL8:
4428 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s'");
4429 case Match_InvalidZPR32LSL16:
4430 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #1'");
4431 case Match_InvalidZPR32LSL32:
4432 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #2'");
4433 case Match_InvalidZPR32LSL64:
4434 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004435 case Match_InvalidZPR64LSL8:
4436 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4437 case Match_InvalidZPR64LSL16:
4438 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4439 case Match_InvalidZPR64LSL32:
4440 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4441 case Match_InvalidZPR64LSL64:
4442 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00004443 case Match_InvalidZPR0:
Sander de Smalene1eab422019-03-27 17:23:38 +00004444 return Error(Loc, "expected register without element width suffix");
Sander de Smalen22176a22018-05-16 15:45:17 +00004445 case Match_InvalidZPR8:
4446 case Match_InvalidZPR16:
4447 case Match_InvalidZPR32:
4448 case Match_InvalidZPR64:
4449 case Match_InvalidZPR128:
4450 return Error(Loc, "invalid element width");
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004451 case Match_InvalidZPR_3b8:
4452 return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b");
4453 case Match_InvalidZPR_3b16:
4454 return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h");
4455 case Match_InvalidZPR_3b32:
4456 return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s");
4457 case Match_InvalidZPR_4b16:
4458 return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h");
4459 case Match_InvalidZPR_4b32:
4460 return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s");
4461 case Match_InvalidZPR_4b64:
4462 return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004463 case Match_InvalidSVEPattern:
4464 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004465 case Match_InvalidSVEPredicateAnyReg:
4466 case Match_InvalidSVEPredicateBReg:
4467 case Match_InvalidSVEPredicateHReg:
4468 case Match_InvalidSVEPredicateSReg:
4469 case Match_InvalidSVEPredicateDReg:
4470 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004471 case Match_InvalidSVEPredicate3bAnyReg:
4472 case Match_InvalidSVEPredicate3bBReg:
4473 case Match_InvalidSVEPredicate3bHReg:
4474 case Match_InvalidSVEPredicate3bSReg:
4475 case Match_InvalidSVEPredicate3bDReg:
4476 return Error(Loc, "restricted predicate has range [0, 7].");
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004477 case Match_InvalidSVEExactFPImmOperandHalfOne:
4478 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4479 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4480 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4481 case Match_InvalidSVEExactFPImmOperandZeroOne:
4482 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004483 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004484 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004485 }
4486}
4487
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004488static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004489
4490bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4491 OperandVector &Operands,
4492 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004493 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004494 bool MatchingInlineAsm) {
4495 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004496 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4497 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004498
David Blaikie960ea3f2014-06-08 16:18:35 +00004499 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004500 unsigned NumOperands = Operands.size();
4501
4502 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004503 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4504 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004505 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004506 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004507 if (Op3CE) {
4508 uint64_t Op3Val = Op3CE->getValue();
4509 uint64_t NewOp3Val = 0;
4510 uint64_t NewOp4Val = 0;
4511 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004512 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004513 NewOp3Val = (32 - Op3Val) & 0x1f;
4514 NewOp4Val = 31 - Op3Val;
4515 } else {
4516 NewOp3Val = (64 - Op3Val) & 0x3f;
4517 NewOp4Val = 63 - Op3Val;
4518 }
4519
Jim Grosbach13760bd2015-05-30 01:25:56 +00004520 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4521 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004522
4523 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004524 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004525 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004526 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4527 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4528 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004529 }
4530 }
Tim Northover03b99f62015-04-30 18:28:58 +00004531 } else if (NumOperands == 4 && Tok == "bfc") {
4532 // FIXME: Horrible hack to handle BFC->BFM alias.
4533 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4534 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4535 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4536
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004537 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004538 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4539 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4540
4541 if (LSBCE && WidthCE) {
4542 uint64_t LSB = LSBCE->getValue();
4543 uint64_t Width = WidthCE->getValue();
4544
4545 uint64_t RegWidth = 0;
4546 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4547 Op1.getReg()))
4548 RegWidth = 64;
4549 else
4550 RegWidth = 32;
4551
4552 if (LSB >= RegWidth)
4553 return Error(LSBOp.getStartLoc(),
4554 "expected integer in range [0, 31]");
4555 if (Width < 1 || Width > RegWidth)
4556 return Error(WidthOp.getStartLoc(),
4557 "expected integer in range [1, 32]");
4558
4559 uint64_t ImmR = 0;
4560 if (RegWidth == 32)
4561 ImmR = (32 - LSB) & 0x1f;
4562 else
4563 ImmR = (64 - LSB) & 0x3f;
4564
4565 uint64_t ImmS = Width - 1;
4566
4567 if (ImmR != 0 && ImmS >= ImmR)
4568 return Error(WidthOp.getStartLoc(),
4569 "requested insert overflows register");
4570
Jim Grosbach13760bd2015-05-30 01:25:56 +00004571 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4572 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004573 Operands[0] = AArch64Operand::CreateToken(
4574 "bfm", false, Op.getStartLoc(), getContext());
4575 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004576 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4577 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004578 Operands[3] = AArch64Operand::CreateImm(
4579 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4580 Operands.emplace_back(
4581 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4582 WidthOp.getEndLoc(), getContext()));
4583 }
4584 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004585 } else if (NumOperands == 5) {
4586 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4587 // UBFIZ -> UBFM aliases.
4588 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004589 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4590 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4591 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004592
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004593 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004594 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4595 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004596
4597 if (Op3CE && Op4CE) {
4598 uint64_t Op3Val = Op3CE->getValue();
4599 uint64_t Op4Val = Op4CE->getValue();
4600
4601 uint64_t RegWidth = 0;
4602 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004603 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004604 RegWidth = 64;
4605 else
4606 RegWidth = 32;
4607
4608 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004609 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004610 "expected integer in range [0, 31]");
4611 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004612 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004613 "expected integer in range [1, 32]");
4614
4615 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004616 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004617 NewOp3Val = (32 - Op3Val) & 0x1f;
4618 else
4619 NewOp3Val = (64 - Op3Val) & 0x3f;
4620
4621 uint64_t NewOp4Val = Op4Val - 1;
4622
4623 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004624 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004625 "requested insert overflows register");
4626
4627 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004628 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004629 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004630 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004631 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004632 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004633 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004634 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004635 if (Tok == "bfi")
4636 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004637 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004638 else if (Tok == "sbfiz")
4639 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004640 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004641 else if (Tok == "ubfiz")
4642 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004643 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004644 else
4645 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004646 }
4647 }
4648
4649 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4650 // UBFX -> UBFM aliases.
4651 } else if (NumOperands == 5 &&
4652 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004653 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4654 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4655 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004656
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004657 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004658 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4659 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004660
4661 if (Op3CE && Op4CE) {
4662 uint64_t Op3Val = Op3CE->getValue();
4663 uint64_t Op4Val = Op4CE->getValue();
4664
4665 uint64_t RegWidth = 0;
4666 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004667 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004668 RegWidth = 64;
4669 else
4670 RegWidth = 32;
4671
4672 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004673 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004674 "expected integer in range [0, 31]");
4675 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004676 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004677 "expected integer in range [1, 32]");
4678
4679 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4680
4681 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004682 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004683 "requested extract overflows register");
4684
4685 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004686 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004687 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004688 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004689 if (Tok == "bfxil")
4690 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004691 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004692 else if (Tok == "sbfx")
4693 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004694 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004695 else if (Tok == "ubfx")
4696 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004697 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004698 else
4699 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004700 }
4701 }
4702 }
4703 }
Tim Northover9097a072017-12-18 10:36:00 +00004704
4705 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4706 // instruction for FP registers correctly in some rare circumstances. Convert
4707 // it to a safe instruction and warn (because silently changing someone's
4708 // assembly is rude).
4709 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4710 NumOperands == 4 && Tok == "movi") {
4711 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4712 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4713 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4714 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4715 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4716 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4717 if (Suffix.lower() == ".2d" &&
4718 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4719 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4720 " correctly on this CPU, converting to equivalent movi.16b");
4721 // Switch the suffix to .16b.
4722 unsigned Idx = Op1.isToken() ? 1 : 2;
4723 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4724 getContext());
4725 }
4726 }
4727 }
4728
Tim Northover3b0846e2014-05-24 12:50:23 +00004729 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4730 // InstAlias can't quite handle this since the reg classes aren't
4731 // subclasses.
4732 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4733 // The source register can be Wn here, but the matcher expects a
4734 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004735 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004736 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004737 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004738 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4739 Op.getStartLoc(), Op.getEndLoc(),
4740 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004741 }
4742 }
4743 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4744 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004745 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004746 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004747 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004748 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004749 // The source register can be Wn here, but the matcher expects a
4750 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004751 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004752 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004753 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004754 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4755 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004756 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004757 }
4758 }
4759 }
4760 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4761 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004762 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004763 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004764 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004765 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004766 // The source register can be Wn here, but the matcher expects a
4767 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004768 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004769 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004770 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004771 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4772 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004773 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004774 }
4775 }
4776 }
4777
Tim Northover3b0846e2014-05-24 12:50:23 +00004778 MCInst Inst;
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004779 FeatureBitset MissingFeatures;
Tim Northover3b0846e2014-05-24 12:50:23 +00004780 // First try to match against the secondary set of tables containing the
4781 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4782 unsigned MatchResult =
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004783 MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
4784 MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004785
4786 // If that fails, try against the alternate table containing long-form NEON:
4787 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004788 if (MatchResult != Match_Success) {
4789 // But first, save the short-form match result: we can use it in case the
4790 // long-form match also fails.
4791 auto ShortFormNEONErrorInfo = ErrorInfo;
4792 auto ShortFormNEONMatchResult = MatchResult;
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004793 auto ShortFormNEONMissingFeatures = MissingFeatures;
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004794
Tim Northover3b0846e2014-05-24 12:50:23 +00004795 MatchResult =
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004796 MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
4797 MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004798
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004799 // Now, both matches failed, and the long-form match failed on the mnemonic
4800 // suffix token operand. The short-form match failure is probably more
4801 // relevant: use it instead.
4802 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004803 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004804 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4805 MatchResult = ShortFormNEONMatchResult;
4806 ErrorInfo = ShortFormNEONErrorInfo;
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004807 MissingFeatures = ShortFormNEONMissingFeatures;
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004808 }
4809 }
4810
Tim Northover3b0846e2014-05-24 12:50:23 +00004811 switch (MatchResult) {
4812 case Match_Success: {
4813 // Perform range checking and other semantic validations
4814 SmallVector<SMLoc, 8> OperandLocs;
4815 NumOperands = Operands.size();
4816 for (unsigned i = 1; i < NumOperands; ++i)
4817 OperandLocs.push_back(Operands[i]->getStartLoc());
Sander de Smalen9b333092018-07-30 15:42:46 +00004818 if (validateInstruction(Inst, IDLoc, OperandLocs))
Tim Northover3b0846e2014-05-24 12:50:23 +00004819 return true;
4820
4821 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004822 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004823 return false;
4824 }
4825 case Match_MissingFeature: {
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004826 assert(MissingFeatures.any() && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004827 // Special case the error message for the very common case where only
4828 // a single subtarget feature is missing (neon, e.g.).
4829 std::string Msg = "instruction requires:";
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004830 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
4831 if (MissingFeatures[i]) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004832 Msg += " ";
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004833 Msg += getSubtargetFeatureName(i);
Tim Northover3b0846e2014-05-24 12:50:23 +00004834 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004835 }
4836 return Error(IDLoc, Msg);
4837 }
4838 case Match_MnemonicFail:
Sander de Smalen0325e302018-07-02 07:34:52 +00004839 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004840 case Match_InvalidOperand: {
4841 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004842
Tim Northover26bb14e2014-08-18 11:49:42 +00004843 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004844 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004845 return Error(IDLoc, "too few operands for instruction",
4846 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004847
David Blaikie960ea3f2014-06-08 16:18:35 +00004848 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004849 if (ErrorLoc == SMLoc())
4850 ErrorLoc = IDLoc;
4851 }
4852 // If the match failed on a suffix token operand, tweak the diagnostic
4853 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004854 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4855 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004856 MatchResult = Match_InvalidSuffix;
4857
Sander de Smalen0325e302018-07-02 07:34:52 +00004858 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004859 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004860 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004861 case Match_InvalidMemoryIndexed1:
4862 case Match_InvalidMemoryIndexed2:
4863 case Match_InvalidMemoryIndexed4:
4864 case Match_InvalidMemoryIndexed8:
4865 case Match_InvalidMemoryIndexed16:
4866 case Match_InvalidCondCode:
4867 case Match_AddSubRegExtendSmall:
4868 case Match_AddSubRegExtendLarge:
4869 case Match_AddSubSecondSource:
4870 case Match_LogicalSecondSource:
4871 case Match_AddSubRegShift32:
4872 case Match_AddSubRegShift64:
4873 case Match_InvalidMovImm32Shift:
4874 case Match_InvalidMovImm64Shift:
4875 case Match_InvalidFPImm:
4876 case Match_InvalidMemoryWExtend8:
4877 case Match_InvalidMemoryWExtend16:
4878 case Match_InvalidMemoryWExtend32:
4879 case Match_InvalidMemoryWExtend64:
4880 case Match_InvalidMemoryWExtend128:
4881 case Match_InvalidMemoryXExtend8:
4882 case Match_InvalidMemoryXExtend16:
4883 case Match_InvalidMemoryXExtend32:
4884 case Match_InvalidMemoryXExtend64:
4885 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004886 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004887 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004888 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004889 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004890 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004891 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004892 case Match_InvalidMemoryIndexed4SImm7:
4893 case Match_InvalidMemoryIndexed8SImm7:
4894 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004895 case Match_InvalidMemoryIndexed8UImm5:
4896 case Match_InvalidMemoryIndexed4UImm5:
4897 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004898 case Match_InvalidMemoryIndexed1UImm6:
4899 case Match_InvalidMemoryIndexed2UImm6:
4900 case Match_InvalidMemoryIndexed4UImm6:
4901 case Match_InvalidMemoryIndexed8UImm6:
Oliver Stannardc4190282018-10-02 10:04:39 +00004902 case Match_InvalidMemoryIndexed16UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004903 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004904 case Match_InvalidMemoryIndexedSImm5:
Sander de Smalen592718f2018-07-05 07:54:10 +00004905 case Match_InvalidMemoryIndexedSImm8:
Tim Northover3b0846e2014-05-24 12:50:23 +00004906 case Match_InvalidMemoryIndexedSImm9:
Oliver Stannardc4190282018-10-02 10:04:39 +00004907 case Match_InvalidMemoryIndexed16SImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004908 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004909 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004910 case Match_InvalidImm0_7:
4911 case Match_InvalidImm0_15:
4912 case Match_InvalidImm0_31:
4913 case Match_InvalidImm0_63:
4914 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004915 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004916 case Match_InvalidImm0_65535:
4917 case Match_InvalidImm1_8:
4918 case Match_InvalidImm1_16:
4919 case Match_InvalidImm1_32:
4920 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004921 case Match_InvalidSVEAddSubImm8:
4922 case Match_InvalidSVEAddSubImm16:
4923 case Match_InvalidSVEAddSubImm32:
4924 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004925 case Match_InvalidSVECpyImm8:
4926 case Match_InvalidSVECpyImm16:
4927 case Match_InvalidSVECpyImm32:
4928 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004929 case Match_InvalidIndexRange1_1:
4930 case Match_InvalidIndexRange0_15:
4931 case Match_InvalidIndexRange0_7:
4932 case Match_InvalidIndexRange0_3:
4933 case Match_InvalidIndexRange0_1:
4934 case Match_InvalidSVEIndexRange0_63:
4935 case Match_InvalidSVEIndexRange0_31:
4936 case Match_InvalidSVEIndexRange0_15:
4937 case Match_InvalidSVEIndexRange0_7:
4938 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004939 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004940 case Match_InvalidComplexRotationEven:
4941 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004942 case Match_InvalidGPR64shifted8:
4943 case Match_InvalidGPR64shifted16:
4944 case Match_InvalidGPR64shifted32:
4945 case Match_InvalidGPR64shifted64:
4946 case Match_InvalidGPR64NoXZRshifted8:
4947 case Match_InvalidGPR64NoXZRshifted16:
4948 case Match_InvalidGPR64NoXZRshifted32:
4949 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004950 case Match_InvalidZPR32UXTW8:
4951 case Match_InvalidZPR32UXTW16:
4952 case Match_InvalidZPR32UXTW32:
4953 case Match_InvalidZPR32UXTW64:
4954 case Match_InvalidZPR32SXTW8:
4955 case Match_InvalidZPR32SXTW16:
4956 case Match_InvalidZPR32SXTW32:
4957 case Match_InvalidZPR32SXTW64:
4958 case Match_InvalidZPR64UXTW8:
4959 case Match_InvalidZPR64SXTW8:
4960 case Match_InvalidZPR64UXTW16:
4961 case Match_InvalidZPR64SXTW16:
4962 case Match_InvalidZPR64UXTW32:
4963 case Match_InvalidZPR64SXTW32:
4964 case Match_InvalidZPR64UXTW64:
4965 case Match_InvalidZPR64SXTW64:
Sander de Smalenc69944c2018-07-09 09:58:24 +00004966 case Match_InvalidZPR32LSL8:
4967 case Match_InvalidZPR32LSL16:
4968 case Match_InvalidZPR32LSL32:
4969 case Match_InvalidZPR32LSL64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004970 case Match_InvalidZPR64LSL8:
4971 case Match_InvalidZPR64LSL16:
4972 case Match_InvalidZPR64LSL32:
4973 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004974 case Match_InvalidZPR0:
4975 case Match_InvalidZPR8:
4976 case Match_InvalidZPR16:
4977 case Match_InvalidZPR32:
4978 case Match_InvalidZPR64:
4979 case Match_InvalidZPR128:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004980 case Match_InvalidZPR_3b8:
4981 case Match_InvalidZPR_3b16:
4982 case Match_InvalidZPR_3b32:
4983 case Match_InvalidZPR_4b16:
4984 case Match_InvalidZPR_4b32:
4985 case Match_InvalidZPR_4b64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004986 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004987 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004988 case Match_InvalidSVEPredicateBReg:
4989 case Match_InvalidSVEPredicateHReg:
4990 case Match_InvalidSVEPredicateSReg:
4991 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004992 case Match_InvalidSVEPredicate3bAnyReg:
4993 case Match_InvalidSVEPredicate3bBReg:
4994 case Match_InvalidSVEPredicate3bHReg:
4995 case Match_InvalidSVEPredicate3bSReg:
4996 case Match_InvalidSVEPredicate3bDReg:
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004997 case Match_InvalidSVEExactFPImmOperandHalfOne:
4998 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4999 case Match_InvalidSVEExactFPImmOperandZeroOne:
Tim Northover3b0846e2014-05-24 12:50:23 +00005000 case Match_MSR:
5001 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00005002 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00005003 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00005004 // Any time we get here, there's nothing fancy to do. Just get the
5005 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00005006 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00005007 if (ErrorLoc == SMLoc())
5008 ErrorLoc = IDLoc;
Sander de Smalen0325e302018-07-02 07:34:52 +00005009 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00005010 }
5011 }
5012
5013 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00005014}
5015
5016/// ParseDirective parses the arm specific directives
5017bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00005018 const MCObjectFileInfo::Environment Format =
5019 getContext().getObjectFileInfo()->getObjectFileType();
5020 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005021
Tim Northover3b0846e2014-05-24 12:50:23 +00005022 StringRef IDVal = DirectiveID.getIdentifier();
5023 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005024 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00005025 parseDirectiveArch(Loc);
5026 else if (IDVal == ".cpu")
5027 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00005028 else if (IDVal == ".tlsdesccall")
5029 parseDirectiveTLSDescCall(Loc);
5030 else if (IDVal == ".ltorg" || IDVal == ".pool")
5031 parseDirectiveLtorg(Loc);
5032 else if (IDVal == ".unreq")
5033 parseDirectiveUnreq(Loc);
Martin Storsjo3e3d39d2018-07-31 09:26:52 +00005034 else if (IDVal == ".inst")
5035 parseDirectiveInst(Loc);
Luke Cheesemanf57d7d82018-12-18 10:37:42 +00005036 else if (IDVal == ".cfi_negate_ra_state")
5037 parseDirectiveCFINegateRAState();
Luke Cheeseman41a9e532018-12-21 10:45:08 +00005038 else if (IDVal == ".cfi_b_key_frame")
5039 parseDirectiveCFIBKeyFrame();
Martin Storsjo20187772018-12-30 21:06:32 +00005040 else if (IDVal == ".arch_extension")
5041 parseDirectiveArchExtension(Loc);
Martin Storsjod4590c32018-08-01 06:50:18 +00005042 else if (IsMachO) {
5043 if (IDVal == MCLOHDirectiveName())
5044 parseDirectiveLOH(IDVal, Loc);
5045 else
5046 return true;
5047 } else
Nirav Davee833c6c2016-11-08 18:31:04 +00005048 return true;
5049 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00005050}
5051
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005052static void ExpandCryptoAEK(AArch64::ArchKind ArchKind,
5053 SmallVector<StringRef, 4> &RequestedExtensions) {
5054 const bool NoCrypto =
5055 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
5056 "nocrypto") != std::end(RequestedExtensions));
5057 const bool Crypto =
5058 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
5059 "crypto") != std::end(RequestedExtensions));
5060
5061 if (!NoCrypto && Crypto) {
5062 switch (ArchKind) {
5063 default:
5064 // Map 'generic' (and others) to sha2 and aes, because
5065 // that was the traditional meaning of crypto.
5066 case AArch64::ArchKind::ARMV8_1A:
5067 case AArch64::ArchKind::ARMV8_2A:
5068 case AArch64::ArchKind::ARMV8_3A:
5069 RequestedExtensions.push_back("sha2");
5070 RequestedExtensions.push_back("aes");
5071 break;
5072 case AArch64::ArchKind::ARMV8_4A:
Oliver Stannard7c3c4ba2018-09-26 12:48:21 +00005073 case AArch64::ArchKind::ARMV8_5A:
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005074 RequestedExtensions.push_back("sm4");
5075 RequestedExtensions.push_back("sha3");
5076 RequestedExtensions.push_back("sha2");
5077 RequestedExtensions.push_back("aes");
5078 break;
5079 }
5080 } else if (NoCrypto) {
5081 switch (ArchKind) {
5082 default:
5083 // Map 'generic' (and others) to sha2 and aes, because
5084 // that was the traditional meaning of crypto.
5085 case AArch64::ArchKind::ARMV8_1A:
5086 case AArch64::ArchKind::ARMV8_2A:
5087 case AArch64::ArchKind::ARMV8_3A:
5088 RequestedExtensions.push_back("nosha2");
5089 RequestedExtensions.push_back("noaes");
5090 break;
5091 case AArch64::ArchKind::ARMV8_4A:
Oliver Stannard7c3c4ba2018-09-26 12:48:21 +00005092 case AArch64::ArchKind::ARMV8_5A:
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005093 RequestedExtensions.push_back("nosm4");
5094 RequestedExtensions.push_back("nosha3");
5095 RequestedExtensions.push_back("nosha2");
5096 RequestedExtensions.push_back("noaes");
5097 break;
5098 }
5099 }
5100}
5101
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005102/// parseDirectiveArch
5103/// ::= .arch token
5104bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
5105 SMLoc ArchLoc = getLoc();
5106
5107 StringRef Arch, ExtensionString;
5108 std::tie(Arch, ExtensionString) =
5109 getParser().parseStringToEndOfStatement().trim().split('+');
5110
Florian Hahn67ddd1d2017-07-27 16:27:56 +00005111 AArch64::ArchKind ID = AArch64::parseArch(Arch);
5112 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00005113 return Error(ArchLoc, "unknown arch name");
5114
5115 if (parseToken(AsmToken::EndOfStatement))
5116 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005117
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005118 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00005119 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005120 AArch64::getArchFeatures(ID, AArch64Features);
5121 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
5122 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005123
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005124 MCSubtargetInfo &STI = copySTI();
5125 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
5126 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
5127
5128 SmallVector<StringRef, 4> RequestedExtensions;
5129 if (!ExtensionString.empty())
5130 ExtensionString.split(RequestedExtensions, '+');
5131
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005132 ExpandCryptoAEK(ID, RequestedExtensions);
5133
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005134 FeatureBitset Features = STI.getFeatureBits();
5135 for (auto Name : RequestedExtensions) {
5136 bool EnableFeature = true;
5137
5138 if (Name.startswith_lower("no")) {
5139 EnableFeature = false;
5140 Name = Name.substr(2);
5141 }
5142
5143 for (const auto &Extension : ExtensionMap) {
5144 if (Extension.Name != Name)
5145 continue;
5146
5147 if (Extension.Features.none())
5148 report_fatal_error("unsupported architectural extension: " + Name);
5149
5150 FeatureBitset ToggleFeatures = EnableFeature
5151 ? (~Features & Extension.Features)
5152 : ( Features & Extension.Features);
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00005153 FeatureBitset Features =
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005154 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5155 setAvailableFeatures(Features);
5156 break;
5157 }
5158 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005159 return false;
5160}
5161
Martin Storsjo20187772018-12-30 21:06:32 +00005162/// parseDirectiveArchExtension
5163/// ::= .arch_extension [no]feature
5164bool AArch64AsmParser::parseDirectiveArchExtension(SMLoc L) {
5165 MCAsmParser &Parser = getParser();
5166
5167 if (getLexer().isNot(AsmToken::Identifier))
5168 return Error(getLexer().getLoc(), "expected architecture extension name");
5169
5170 const AsmToken &Tok = Parser.getTok();
5171 StringRef Name = Tok.getString();
5172 SMLoc ExtLoc = Tok.getLoc();
5173 Lex();
5174
5175 if (parseToken(AsmToken::EndOfStatement,
5176 "unexpected token in '.arch_extension' directive"))
5177 return true;
5178
5179 bool EnableFeature = true;
5180 if (Name.startswith_lower("no")) {
5181 EnableFeature = false;
5182 Name = Name.substr(2);
5183 }
5184
5185 MCSubtargetInfo &STI = copySTI();
5186 FeatureBitset Features = STI.getFeatureBits();
5187 for (const auto &Extension : ExtensionMap) {
5188 if (Extension.Name != Name)
5189 continue;
5190
5191 if (Extension.Features.none())
5192 return Error(ExtLoc, "unsupported architectural extension: " + Name);
5193
5194 FeatureBitset ToggleFeatures = EnableFeature
5195 ? (~Features & Extension.Features)
5196 : (Features & Extension.Features);
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00005197 FeatureBitset Features =
Martin Storsjo20187772018-12-30 21:06:32 +00005198 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5199 setAvailableFeatures(Features);
5200 return false;
5201 }
5202
5203 return Error(ExtLoc, "unknown architectural extension: " + Name);
5204}
5205
Tim Northover8b96c7e2017-05-15 19:42:15 +00005206static SMLoc incrementLoc(SMLoc L, int Offset) {
5207 return SMLoc::getFromPointer(L.getPointer() + Offset);
5208}
5209
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005210/// parseDirectiveCPU
5211/// ::= .cpu id
5212bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005213 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005214
5215 StringRef CPU, ExtensionString;
5216 std::tie(CPU, ExtensionString) =
5217 getParser().parseStringToEndOfStatement().trim().split('+');
5218
Nirav Davee833c6c2016-11-08 18:31:04 +00005219 if (parseToken(AsmToken::EndOfStatement))
5220 return true;
5221
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005222 SmallVector<StringRef, 4> RequestedExtensions;
5223 if (!ExtensionString.empty())
5224 ExtensionString.split(RequestedExtensions, '+');
5225
5226 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
5227 // once that is tablegen'ed
5228 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005229 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005230 return false;
5231 }
5232
5233 MCSubtargetInfo &STI = copySTI();
5234 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00005235 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005236
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005237 ExpandCryptoAEK(llvm::AArch64::getCPUArchKind(CPU), RequestedExtensions);
5238
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005239 FeatureBitset Features = STI.getFeatureBits();
5240 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005241 // Advance source location past '+'.
5242 CurLoc = incrementLoc(CurLoc, 1);
5243
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005244 bool EnableFeature = true;
5245
5246 if (Name.startswith_lower("no")) {
5247 EnableFeature = false;
5248 Name = Name.substr(2);
5249 }
5250
Tim Northover8b96c7e2017-05-15 19:42:15 +00005251 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005252 for (const auto &Extension : ExtensionMap) {
5253 if (Extension.Name != Name)
5254 continue;
5255
5256 if (Extension.Features.none())
5257 report_fatal_error("unsupported architectural extension: " + Name);
5258
5259 FeatureBitset ToggleFeatures = EnableFeature
5260 ? (~Features & Extension.Features)
5261 : ( Features & Extension.Features);
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00005262 FeatureBitset Features =
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005263 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5264 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00005265 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005266
5267 break;
5268 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00005269
5270 if (!FoundExtension)
5271 Error(CurLoc, "unsupported architectural extension");
5272
5273 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005274 }
5275 return false;
5276}
5277
Chad Rosierdcd2a302014-10-22 20:35:57 +00005278/// parseDirectiveInst
5279/// ::= .inst opcode [, ...]
5280bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005281 if (getLexer().is(AsmToken::EndOfStatement))
5282 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005283
Nirav Davee833c6c2016-11-08 18:31:04 +00005284 auto parseOp = [&]() -> bool {
5285 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00005286 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00005287 if (check(getParser().parseExpression(Expr), L, "expected expression"))
5288 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005289 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00005290 if (check(!Value, L, "expected constant expression"))
5291 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005292 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00005293 return false;
5294 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00005295
Nirav Davee833c6c2016-11-08 18:31:04 +00005296 if (parseMany(parseOp))
5297 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005298 return false;
5299}
5300
Tim Northover3b0846e2014-05-24 12:50:23 +00005301// parseDirectiveTLSDescCall:
5302// ::= .tlsdesccall symbol
5303bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
5304 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00005305 if (check(getParser().parseIdentifier(Name), L,
5306 "expected symbol after directive") ||
5307 parseToken(AsmToken::EndOfStatement))
5308 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005309
Jim Grosbach6f482002015-05-18 18:43:14 +00005310 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00005311 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
5312 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00005313
5314 MCInst Inst;
5315 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00005316 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00005317
Akira Hatanakabd9fc282015-11-14 05:20:05 +00005318 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00005319 return false;
5320}
5321
5322/// ::= .loh <lohName | lohId> label1, ..., labelN
5323/// The number of arguments depends on the loh identifier.
5324bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00005325 MCLOHType Kind;
5326 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5327 if (getParser().getTok().isNot(AsmToken::Integer))
5328 return TokError("expected an identifier or a number in directive");
5329 // We successfully get a numeric value for the identifier.
5330 // Check if it is valid.
5331 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00005332 if (Id <= -1U && !isValidMCLOHType(Id))
5333 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00005334 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00005335 } else {
5336 StringRef Name = getTok().getIdentifier();
5337 // We successfully parse an identifier.
5338 // Check if it is a recognized one.
5339 int Id = MCLOHNameToId(Name);
5340
5341 if (Id == -1)
5342 return TokError("invalid identifier in directive");
5343 Kind = (MCLOHType)Id;
5344 }
5345 // Consume the identifier.
5346 Lex();
5347 // Get the number of arguments of this LOH.
5348 int NbArgs = MCLOHIdToNbArgs(Kind);
5349
5350 assert(NbArgs != -1 && "Invalid number of arguments");
5351
5352 SmallVector<MCSymbol *, 3> Args;
5353 for (int Idx = 0; Idx < NbArgs; ++Idx) {
5354 StringRef Name;
5355 if (getParser().parseIdentifier(Name))
5356 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00005357 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00005358
5359 if (Idx + 1 == NbArgs)
5360 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00005361 if (parseToken(AsmToken::Comma,
5362 "unexpected token in '" + Twine(IDVal) + "' directive"))
5363 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005364 }
Nirav Davee833c6c2016-11-08 18:31:04 +00005365 if (parseToken(AsmToken::EndOfStatement,
5366 "unexpected token in '" + Twine(IDVal) + "' directive"))
5367 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005368
5369 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
5370 return false;
5371}
5372
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005373/// parseDirectiveLtorg
5374/// ::= .ltorg | .pool
5375bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005376 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5377 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005378 getTargetStreamer().emitCurrentConstantPool();
5379 return false;
5380}
5381
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005382/// parseDirectiveReq
5383/// ::= name .req registername
5384bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005385 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005386 Parser.Lex(); // Eat the '.req' token.
5387 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00005388 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00005389 unsigned RegNum;
5390 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005391
Sander de Smalen50d87022018-04-19 07:35:08 +00005392 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005393 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00005394 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005395 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00005396
Sander de Smalen50d87022018-04-19 07:35:08 +00005397 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00005398 return true;
5399
Sander de Smalen50d87022018-04-19 07:35:08 +00005400 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00005401 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005402 }
5403
Sander de Smalen50d87022018-04-19 07:35:08 +00005404 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005405 StringRef Kind;
5406 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005407 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00005408 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005409
Sander de Smalen50d87022018-04-19 07:35:08 +00005410 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00005411 return true;
5412
Sander de Smalen50d87022018-04-19 07:35:08 +00005413 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00005414 return Error(SRegLoc,
5415 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00005416 }
5417
Sander de Smalen50d87022018-04-19 07:35:08 +00005418 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00005419 StringRef Kind;
5420 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005421 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00005422
Sander de Smalen50d87022018-04-19 07:35:08 +00005423 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00005424 return true;
5425
Sander de Smalen50d87022018-04-19 07:35:08 +00005426 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00005427 return Error(SRegLoc,
5428 "sve predicate register without type specifier expected");
5429 }
5430
Sander de Smalen50d87022018-04-19 07:35:08 +00005431 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00005432 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005433
5434 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00005435 if (parseToken(AsmToken::EndOfStatement,
5436 "unexpected input in .req directive"))
5437 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005438
Sander de Smalen8e607342017-11-15 15:44:43 +00005439 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00005440 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005441 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
5442
Nirav Dave2364748a2016-09-16 18:30:20 +00005443 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005444}
5445
5446/// parseDirectiveUneq
5447/// ::= .unreq registername
5448bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005449 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00005450 if (getTok().isNot(AsmToken::Identifier))
5451 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005452 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
5453 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00005454 if (parseToken(AsmToken::EndOfStatement))
5455 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005456 return false;
5457}
5458
Luke Cheesemanf57d7d82018-12-18 10:37:42 +00005459bool AArch64AsmParser::parseDirectiveCFINegateRAState() {
5460 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5461 return true;
5462 getStreamer().EmitCFINegateRAState();
5463 return false;
5464}
5465
Luke Cheeseman41a9e532018-12-21 10:45:08 +00005466/// parseDirectiveCFIBKeyFrame
5467/// ::= .cfi_b_key
5468bool AArch64AsmParser::parseDirectiveCFIBKeyFrame() {
5469 if (parseToken(AsmToken::EndOfStatement,
5470 "unexpected token in '.cfi_b_key_frame'"))
5471 return true;
5472 getStreamer().EmitCFIBKeyFrame();
5473 return false;
5474}
5475
Tim Northover3b0846e2014-05-24 12:50:23 +00005476bool
5477AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
5478 AArch64MCExpr::VariantKind &ELFRefKind,
5479 MCSymbolRefExpr::VariantKind &DarwinRefKind,
5480 int64_t &Addend) {
5481 ELFRefKind = AArch64MCExpr::VK_INVALID;
5482 DarwinRefKind = MCSymbolRefExpr::VK_None;
5483 Addend = 0;
5484
5485 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5486 ELFRefKind = AE->getKind();
5487 Expr = AE->getSubExpr();
5488 }
5489
5490 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5491 if (SE) {
5492 // It's a simple symbol reference with no addend.
5493 DarwinRefKind = SE->getKind();
5494 return true;
5495 }
5496
David Green85d6a552018-09-18 09:44:53 +00005497 // Check that it looks like a symbol + an addend
5498 MCValue Res;
5499 bool Relocatable = Expr->evaluateAsRelocatable(Res, nullptr, nullptr);
Eli Friedman48397102018-12-20 19:46:14 +00005500 if (!Relocatable || Res.getSymB())
Tim Northover3b0846e2014-05-24 12:50:23 +00005501 return false;
5502
Eli Friedman48397102018-12-20 19:46:14 +00005503 // Treat expressions with an ELFRefKind (like ":abs_g1:3", or
5504 // ":abs_g1:x" where x is constant) as symbolic even if there is no symbol.
5505 if (!Res.getSymA() && ELFRefKind == AArch64MCExpr::VK_INVALID)
5506 return false;
5507
5508 if (Res.getSymA())
5509 DarwinRefKind = Res.getSymA()->getKind();
David Green85d6a552018-09-18 09:44:53 +00005510 Addend = Res.getConstant();
Tim Northover3b0846e2014-05-24 12:50:23 +00005511
5512 // It's some symbol reference + a constant addend, but really
5513 // shouldn't use both Darwin and ELF syntax.
5514 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5515 DarwinRefKind == MCSymbolRefExpr::VK_None;
5516}
5517
5518/// Force static initialization.
5519extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00005520 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5521 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5522 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00005523}
5524
5525#define GET_REGISTER_MATCHER
5526#define GET_SUBTARGET_FEATURE_NAME
5527#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00005528#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00005529#include "AArch64GenAsmMatcher.inc"
5530
5531// Define this matcher function after the auto-generated include so we
5532// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00005533unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00005534 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005535 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00005536 // If the kind is a token for a literal immediate, check if our asm
5537 // operand matches. This is for InstAliases which have a fixed-value
5538 // immediate in the syntax.
5539 int64_t ExpectedVal;
5540 switch (Kind) {
5541 default:
5542 return Match_InvalidOperand;
5543 case MCK__35_0:
5544 ExpectedVal = 0;
5545 break;
5546 case MCK__35_1:
5547 ExpectedVal = 1;
5548 break;
5549 case MCK__35_12:
5550 ExpectedVal = 12;
5551 break;
5552 case MCK__35_16:
5553 ExpectedVal = 16;
5554 break;
5555 case MCK__35_2:
5556 ExpectedVal = 2;
5557 break;
5558 case MCK__35_24:
5559 ExpectedVal = 24;
5560 break;
5561 case MCK__35_3:
5562 ExpectedVal = 3;
5563 break;
5564 case MCK__35_32:
5565 ExpectedVal = 32;
5566 break;
5567 case MCK__35_4:
5568 ExpectedVal = 4;
5569 break;
5570 case MCK__35_48:
5571 ExpectedVal = 48;
5572 break;
5573 case MCK__35_6:
5574 ExpectedVal = 6;
5575 break;
5576 case MCK__35_64:
5577 ExpectedVal = 64;
5578 break;
5579 case MCK__35_8:
5580 ExpectedVal = 8;
5581 break;
5582 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005583 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005584 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005586 if (!CE)
5587 return Match_InvalidOperand;
5588 if (CE->getValue() == ExpectedVal)
5589 return Match_Success;
5590 return Match_InvalidOperand;
5591}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005592
Alex Bradbury58eba092016-11-01 16:32:05 +00005593OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005594AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5595
5596 SMLoc S = getLoc();
5597
5598 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5599 Error(S, "expected register");
5600 return MatchOperand_ParseFail;
5601 }
5602
Sander de Smalen50d87022018-04-19 07:35:08 +00005603 unsigned FirstReg;
5604 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5605 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005606 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005607
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005608 const MCRegisterClass &WRegClass =
5609 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5610 const MCRegisterClass &XRegClass =
5611 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5612
5613 bool isXReg = XRegClass.contains(FirstReg),
5614 isWReg = WRegClass.contains(FirstReg);
5615 if (!isXReg && !isWReg) {
5616 Error(S, "expected first even register of a "
5617 "consecutive same-size even/odd register pair");
5618 return MatchOperand_ParseFail;
5619 }
5620
5621 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5622 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5623
5624 if (FirstEncoding & 0x1) {
5625 Error(S, "expected first even register of a "
5626 "consecutive same-size even/odd register pair");
5627 return MatchOperand_ParseFail;
5628 }
5629
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005630 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005631 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005632 return MatchOperand_ParseFail;
5633 }
5634 // Eat the comma
5635 getParser().Lex();
5636
5637 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005638 unsigned SecondReg;
5639 Res = tryParseScalarRegister(SecondReg);
5640 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005641 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005642
Eugene Zelenko049b0172017-01-06 00:30:53 +00005643 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005644 (isXReg && !XRegClass.contains(SecondReg)) ||
5645 (isWReg && !WRegClass.contains(SecondReg))) {
5646 Error(E,"expected second odd register of a "
5647 "consecutive same-size even/odd register pair");
5648 return MatchOperand_ParseFail;
5649 }
Joel Jones504bf332016-10-24 13:37:13 +00005650
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005651 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005652 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005653 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5654 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5655 } else {
5656 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5657 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5658 }
5659
Florian Hahnc4422242017-11-07 13:07:50 +00005660 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5661 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005662
5663 return MatchOperand_Success;
5664}
Florian Hahn91f11e52017-11-07 16:45:48 +00005665
Sander de Smaleneb896b12018-04-25 09:26:47 +00005666template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005667OperandMatchResultTy
5668AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005669 const SMLoc S = getLoc();
5670 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005671 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005672 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005673
Sander de Smalen8e607342017-11-15 15:44:43 +00005674 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005675 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005676
5677 if (Res != MatchOperand_Success)
5678 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005679
5680 if (ParseSuffix && Kind.empty())
5681 return MatchOperand_NoMatch;
5682
Sander de Smalen73937b72018-04-11 07:36:10 +00005683 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5684 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005685 return MatchOperand_NoMatch;
5686
Sander de Smalen73937b72018-04-11 07:36:10 +00005687 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005688
5689 // No shift/extend is the default.
5690 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5691 Operands.push_back(AArch64Operand::CreateVectorReg(
5692 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5693
Sander de Smalenc33d6682018-06-04 06:40:55 +00005694 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5695 if (Res == MatchOperand_ParseFail)
5696 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005697 return MatchOperand_Success;
5698 }
5699
5700 // Eat the comma
5701 getParser().Lex();
5702
5703 // Match the shift
5704 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5705 Res = tryParseOptionalShiftExtend(ExtOpnd);
5706 if (Res != MatchOperand_Success)
5707 return Res;
5708
5709 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005710 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005711 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5712 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5713 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005714
5715 return MatchOperand_Success;
5716}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005717
5718OperandMatchResultTy
5719AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5720 MCAsmParser &Parser = getParser();
5721
5722 SMLoc SS = getLoc();
5723 const AsmToken &TokE = Parser.getTok();
5724 bool IsHash = TokE.is(AsmToken::Hash);
5725
5726 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5727 return MatchOperand_NoMatch;
5728
5729 int64_t Pattern;
5730 if (IsHash) {
5731 Parser.Lex(); // Eat hash
5732
5733 // Parse the immediate operand.
5734 const MCExpr *ImmVal;
5735 SS = getLoc();
5736 if (Parser.parseExpression(ImmVal))
5737 return MatchOperand_ParseFail;
5738
5739 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5740 if (!MCE)
5741 return MatchOperand_ParseFail;
5742
5743 Pattern = MCE->getValue();
5744 } else {
5745 // Parse the pattern
5746 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5747 if (!Pat)
5748 return MatchOperand_NoMatch;
5749
5750 Parser.Lex();
5751 Pattern = Pat->Encoding;
5752 assert(Pattern >= 0 && Pattern < 32);
5753 }
5754
5755 Operands.push_back(
5756 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5757 SS, getLoc(), getContext()));
5758
5759 return MatchOperand_Success;
5760}