blob: f1aa8a701b01909796268e98cb597f957f2ea899 [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;
Eli Friedman723835382019-05-03 00:59:52 +00001273 // Make sure the extend expects a 32-bit source register.
Tim Northover3b0846e2014-05-24 12:50:23 +00001274 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
Eli Friedman723835382019-05-03 00:59:52 +00001275 return ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1276 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1277 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW;
Tim Northover3b0846e2014-05-24 12:50:23 +00001278 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001279
Tim Northover3b0846e2014-05-24 12:50:23 +00001280 bool isExtendLSL64() const {
1281 if (!isExtend())
1282 return false;
1283 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1284 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1285 ET == AArch64_AM::LSL) &&
1286 getShiftExtendAmount() <= 4;
1287 }
1288
1289 template<int Width> bool isMemXExtend() const {
1290 if (!isExtend())
1291 return false;
1292 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1293 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1294 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1295 getShiftExtendAmount() == 0);
1296 }
1297
1298 template<int Width> bool isMemWExtend() const {
1299 if (!isExtend())
1300 return false;
1301 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1302 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1303 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1304 getShiftExtendAmount() == 0);
1305 }
1306
1307 template <unsigned width>
1308 bool isArithmeticShifter() const {
1309 if (!isShifter())
1310 return false;
1311
1312 // An arithmetic shifter is LSL, LSR, or ASR.
1313 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1314 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1315 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1316 }
1317
1318 template <unsigned width>
1319 bool isLogicalShifter() const {
1320 if (!isShifter())
1321 return false;
1322
1323 // A logical shifter is LSL, LSR, ASR or ROR.
1324 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1325 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1326 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1327 getShiftExtendAmount() < width;
1328 }
1329
1330 bool isMovImm32Shifter() const {
1331 if (!isShifter())
1332 return false;
1333
1334 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1335 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1336 if (ST != AArch64_AM::LSL)
1337 return false;
1338 uint64_t Val = getShiftExtendAmount();
1339 return (Val == 0 || Val == 16);
1340 }
1341
1342 bool isMovImm64Shifter() const {
1343 if (!isShifter())
1344 return false;
1345
1346 // A MOVi shifter is LSL of 0 or 16.
1347 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1348 if (ST != AArch64_AM::LSL)
1349 return false;
1350 uint64_t Val = getShiftExtendAmount();
1351 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1352 }
1353
1354 bool isLogicalVecShifter() const {
1355 if (!isShifter())
1356 return false;
1357
1358 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1359 unsigned Shift = getShiftExtendAmount();
1360 return getShiftExtendType() == AArch64_AM::LSL &&
1361 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1362 }
1363
1364 bool isLogicalVecHalfWordShifter() const {
1365 if (!isLogicalVecShifter())
1366 return false;
1367
1368 // A logical vector shifter is a left shift by 0 or 8.
1369 unsigned Shift = getShiftExtendAmount();
1370 return getShiftExtendType() == AArch64_AM::LSL &&
1371 (Shift == 0 || Shift == 8);
1372 }
1373
1374 bool isMoveVecShifter() const {
1375 if (!isShiftExtend())
1376 return false;
1377
1378 // A logical vector shifter is a left shift by 8 or 16.
1379 unsigned Shift = getShiftExtendAmount();
1380 return getShiftExtendType() == AArch64_AM::MSL &&
1381 (Shift == 8 || Shift == 16);
1382 }
1383
1384 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1385 // to LDUR/STUR when the offset is not legal for the former but is for
1386 // the latter. As such, in addition to checking for being a legal unscaled
1387 // address, also check that it is not a legal scaled address. This avoids
1388 // ambiguity in the matcher.
1389 template<int Width>
1390 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001391 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001392 }
1393
1394 bool isAdrpLabel() const {
1395 // Validation was handled during parsing, so we just sanity check that
1396 // something didn't go haywire.
1397 if (!isImm())
1398 return false;
1399
1400 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1401 int64_t Val = CE->getValue();
1402 int64_t Min = - (4096 * (1LL << (21 - 1)));
1403 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1404 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1405 }
1406
1407 return true;
1408 }
1409
1410 bool isAdrLabel() const {
1411 // Validation was handled during parsing, so we just sanity check that
1412 // something didn't go haywire.
1413 if (!isImm())
1414 return false;
1415
1416 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1417 int64_t Val = CE->getValue();
1418 int64_t Min = - (1LL << (21 - 1));
1419 int64_t Max = ((1LL << (21 - 1)) - 1);
1420 return Val >= Min && Val <= Max;
1421 }
1422
1423 return true;
1424 }
1425
1426 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1427 // Add as immediates when possible. Null MCExpr = 0.
1428 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001429 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001430 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001431 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001432 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001433 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 }
1435
1436 void addRegOperands(MCInst &Inst, unsigned N) const {
1437 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001438 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001439 }
1440
1441 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1442 assert(N == 1 && "Invalid number of operands!");
1443 assert(
1444 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1445
1446 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1447 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1448 RI->getEncodingValue(getReg()));
1449
Jim Grosbache9119e42015-05-13 18:37:00 +00001450 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001451 }
1452
Sander de Smalen0325e302018-07-02 07:34:52 +00001453 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1454 assert(N == 1 && "Invalid number of operands!");
1455 assert(
1456 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(getReg()));
1457
1458 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1459 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID).getRegister(
1460 RI->getEncodingValue(getReg()));
1461
1462 Inst.addOperand(MCOperand::createReg(Reg));
1463 }
1464
Sander de Smalenfd54a782018-06-04 07:07:35 +00001465 template <int Width>
1466 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1467 unsigned Base;
1468 switch (Width) {
1469 case 8: Base = AArch64::B0; break;
1470 case 16: Base = AArch64::H0; break;
1471 case 32: Base = AArch64::S0; break;
1472 case 64: Base = AArch64::D0; break;
1473 case 128: Base = AArch64::Q0; break;
1474 default:
1475 llvm_unreachable("Unsupported width");
1476 }
1477 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1478 }
1479
Tim Northover3b0846e2014-05-24 12:50:23 +00001480 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1481 assert(N == 1 && "Invalid number of operands!");
1482 assert(
1483 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001484 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001485 }
1486
1487 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1488 assert(N == 1 && "Invalid number of operands!");
1489 assert(
1490 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001491 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001492 }
1493
1494 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1495 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001496 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001497 }
1498
Sander de Smalen525e3222018-04-12 13:19:32 +00001499 enum VecListIndexType {
1500 VecListIdx_DReg = 0,
1501 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001502 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001503 };
1504
1505 template <VecListIndexType RegTy, unsigned NumRegs>
1506 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001507 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001508 static const unsigned FirstRegs[][5] = {
1509 /* DReg */ { AArch64::Q0,
1510 AArch64::D0, AArch64::D0_D1,
1511 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1512 /* QReg */ { AArch64::Q0,
1513 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001514 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1515 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001516 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001517 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001518 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001519
Sander de Smalen7a210db2018-04-16 10:46:18 +00001520 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1521 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001522
Sander de Smalen525e3222018-04-12 13:19:32 +00001523 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1524 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1525 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001526 }
1527
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001528 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001529 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001530 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001531 }
1532
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001533 template <unsigned ImmIs0, unsigned ImmIs1>
1534 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1535 assert(N == 1 && "Invalid number of operands!");
1536 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1537 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1538 }
1539
Tim Northover3b0846e2014-05-24 12:50:23 +00001540 void addImmOperands(MCInst &Inst, unsigned N) const {
1541 assert(N == 1 && "Invalid number of operands!");
1542 // If this is a pageoff symrefexpr with an addend, adjust the addend
1543 // to be only the page-offset portion. Otherwise, just add the expr
1544 // as-is.
1545 addExpr(Inst, getImm());
1546 }
1547
Sander de Smalen62770792018-05-25 09:47:52 +00001548 template <int Shift>
1549 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001550 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001551 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1552 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1553 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1554 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001555 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001556 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001557 } else {
1558 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001559 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001560 }
1561 }
1562
Sander de Smalen62770792018-05-25 09:47:52 +00001563 template <int Shift>
1564 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001565 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001566 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1567 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1568 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1569 } else
1570 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001571 }
1572
Tim Northover3b0846e2014-05-24 12:50:23 +00001573 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1574 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001575 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001576 }
1577
1578 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1579 assert(N == 1 && "Invalid number of operands!");
1580 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1581 if (!MCE)
1582 addExpr(Inst, getImm());
1583 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001584 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001585 }
1586
1587 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1588 addImmOperands(Inst, N);
1589 }
1590
1591 template<int Scale>
1592 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1593 assert(N == 1 && "Invalid number of operands!");
1594 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1595
1596 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001597 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001598 return;
1599 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001600 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001601 }
1602
Sjoerd Meijera3dad802018-07-06 12:32:33 +00001603 void addUImm6Operands(MCInst &Inst, unsigned N) const {
1604 assert(N == 1 && "Invalid number of operands!");
1605 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1606 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1607 }
1608
Sander de Smalen5c625982018-04-13 12:56:14 +00001609 template <int Scale>
1610 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1611 assert(N == 1 && "Invalid number of operands!");
1612 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1613 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1614 }
1615
Sander de Smalena1c259c2018-01-29 13:05:38 +00001616 template <typename T>
1617 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001618 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001619 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001620 typename std::make_unsigned<T>::type Val = MCE->getValue();
1621 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001622 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001623 }
1624
Sander de Smalena1c259c2018-01-29 13:05:38 +00001625 template <typename T>
1626 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001627 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001628 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001629 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1630 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001631 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001632 }
1633
Tim Northover3b0846e2014-05-24 12:50:23 +00001634 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1635 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001636 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001637 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001638 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001639 }
1640
1641 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1642 // Branch operands don't encode the low bits, so shift them off
1643 // here. If it's a label, however, just put it on directly as there's
1644 // not enough information now to do anything.
1645 assert(N == 1 && "Invalid number of operands!");
1646 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1647 if (!MCE) {
1648 addExpr(Inst, getImm());
1649 return;
1650 }
1651 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001652 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001653 }
1654
1655 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1656 // Branch operands don't encode the low bits, so shift them off
1657 // here. If it's a label, however, just put it on directly as there's
1658 // not enough information now to do anything.
1659 assert(N == 1 && "Invalid number of operands!");
1660 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1661 if (!MCE) {
1662 addExpr(Inst, getImm());
1663 return;
1664 }
1665 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001666 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001667 }
1668
1669 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1670 // Branch operands don't encode the low bits, so shift them off
1671 // here. If it's a label, however, just put it on directly as there's
1672 // not enough information now to do anything.
1673 assert(N == 1 && "Invalid number of operands!");
1674 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1675 if (!MCE) {
1676 addExpr(Inst, getImm());
1677 return;
1678 }
1679 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001680 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001681 }
1682
1683 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1684 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001685 Inst.addOperand(MCOperand::createImm(
1686 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
Tim Northover3b0846e2014-05-24 12:50:23 +00001687 }
1688
1689 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1690 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001691 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001692 }
1693
1694 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1695 assert(N == 1 && "Invalid number of operands!");
1696
Jim Grosbache9119e42015-05-13 18:37:00 +00001697 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001698 }
1699
1700 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1701 assert(N == 1 && "Invalid number of operands!");
1702
Jim Grosbache9119e42015-05-13 18:37:00 +00001703 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001704 }
1705
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001706 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1707 assert(N == 1 && "Invalid number of operands!");
1708
1709 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1710 }
1711
1712 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001713 assert(N == 1 && "Invalid number of operands!");
1714
Jim Grosbache9119e42015-05-13 18:37:00 +00001715 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001716 }
1717
1718 void addSysCROperands(MCInst &Inst, unsigned N) const {
1719 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001720 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001721 }
1722
1723 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1724 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001725 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001726 }
1727
Oliver Stannarda34e4702015-12-01 10:48:51 +00001728 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1729 assert(N == 1 && "Invalid number of operands!");
1730 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1731 }
1732
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001733 void addBTIHintOperands(MCInst &Inst, unsigned N) const {
1734 assert(N == 1 && "Invalid number of operands!");
1735 Inst.addOperand(MCOperand::createImm(getBTIHint()));
1736 }
1737
Tim Northover3b0846e2014-05-24 12:50:23 +00001738 void addShifterOperands(MCInst &Inst, unsigned N) const {
1739 assert(N == 1 && "Invalid number of operands!");
1740 unsigned Imm =
1741 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001742 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001743 }
1744
1745 void addExtendOperands(MCInst &Inst, unsigned N) const {
1746 assert(N == 1 && "Invalid number of operands!");
1747 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1748 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1749 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001750 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001751 }
1752
1753 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1754 assert(N == 1 && "Invalid number of operands!");
1755 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1756 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1757 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001758 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001759 }
1760
1761 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1762 assert(N == 2 && "Invalid number of operands!");
1763 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1764 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001765 Inst.addOperand(MCOperand::createImm(IsSigned));
1766 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001767 }
1768
1769 // For 8-bit load/store instructions with a register offset, both the
1770 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1771 // they're disambiguated by whether the shift was explicit or implicit rather
1772 // than its size.
1773 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1774 assert(N == 2 && "Invalid number of operands!");
1775 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1776 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001777 Inst.addOperand(MCOperand::createImm(IsSigned));
1778 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001779 }
1780
1781 template<int Shift>
1782 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1783 assert(N == 1 && "Invalid number of operands!");
1784
1785 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1786 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001787 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001788 }
1789
1790 template<int Shift>
1791 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1792 assert(N == 1 && "Invalid number of operands!");
1793
1794 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1795 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001796 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001797 }
1798
Sam Parker5f934642017-08-31 09:27:04 +00001799 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1800 assert(N == 1 && "Invalid number of operands!");
1801 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1802 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1803 }
1804
1805 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1806 assert(N == 1 && "Invalid number of operands!");
1807 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1808 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1809 }
1810
Tim Northover3b0846e2014-05-24 12:50:23 +00001811 void print(raw_ostream &OS) const override;
1812
David Blaikie960ea3f2014-06-08 16:18:35 +00001813 static std::unique_ptr<AArch64Operand>
1814 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1815 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001816 Op->Tok.Data = Str.data();
1817 Op->Tok.Length = Str.size();
1818 Op->Tok.IsSuffix = IsSuffix;
1819 Op->StartLoc = S;
1820 Op->EndLoc = S;
1821 return Op;
1822 }
1823
David Blaikie960ea3f2014-06-08 16:18:35 +00001824 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001825 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
Sander de Smalen0325e302018-07-02 07:34:52 +00001826 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
Sander de Smalen149916d2018-04-20 07:24:20 +00001827 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1828 unsigned ShiftAmount = 0,
1829 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001830 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001831 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001832 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001833 Op->Reg.ElementWidth = 0;
Sander de Smalen0325e302018-07-02 07:34:52 +00001834 Op->Reg.EqualityTy = EqTy;
Sander de Smalen149916d2018-04-20 07:24:20 +00001835 Op->Reg.ShiftExtend.Type = ExtTy;
1836 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1837 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001838 Op->StartLoc = S;
1839 Op->EndLoc = E;
1840 return Op;
1841 }
1842
David Blaikie960ea3f2014-06-08 16:18:35 +00001843 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001844 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001845 SMLoc S, SMLoc E, MCContext &Ctx,
1846 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1847 unsigned ShiftAmount = 0,
1848 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001849 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1850 Kind == RegKind::SVEPredicateVector) &&
1851 "Invalid vector kind");
Sander de Smalen0325e302018-07-02 07:34:52 +00001852 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
Sander de Smalen149916d2018-04-20 07:24:20 +00001853 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001854 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001855 return Op;
1856 }
1857
1858 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001859 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001860 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1861 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001862 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001863 Op->VectorList.RegNum = RegNum;
1864 Op->VectorList.Count = Count;
1865 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001866 Op->VectorList.ElementWidth = ElementWidth;
1867 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001868 Op->StartLoc = S;
1869 Op->EndLoc = E;
1870 return Op;
1871 }
1872
David Blaikie960ea3f2014-06-08 16:18:35 +00001873 static std::unique_ptr<AArch64Operand>
1874 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1875 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001876 Op->VectorIndex.Val = Idx;
1877 Op->StartLoc = S;
1878 Op->EndLoc = E;
1879 return Op;
1880 }
1881
David Blaikie960ea3f2014-06-08 16:18:35 +00001882 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1883 SMLoc E, MCContext &Ctx) {
1884 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001885 Op->Imm.Val = Val;
1886 Op->StartLoc = S;
1887 Op->EndLoc = E;
1888 return Op;
1889 }
1890
David Blaikie960ea3f2014-06-08 16:18:35 +00001891 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1892 unsigned ShiftAmount,
1893 SMLoc S, SMLoc E,
1894 MCContext &Ctx) {
1895 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001896 Op->ShiftedImm .Val = Val;
1897 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1898 Op->StartLoc = S;
1899 Op->EndLoc = E;
1900 return Op;
1901 }
1902
David Blaikie960ea3f2014-06-08 16:18:35 +00001903 static std::unique_ptr<AArch64Operand>
1904 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1905 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001906 Op->CondCode.Code = Code;
1907 Op->StartLoc = S;
1908 Op->EndLoc = E;
1909 return Op;
1910 }
1911
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001912 static std::unique_ptr<AArch64Operand>
1913 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001914 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001915 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
1916 Op->FPImm.IsExact = IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +00001917 Op->StartLoc = S;
1918 Op->EndLoc = S;
1919 return Op;
1920 }
1921
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001922 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1923 StringRef Str,
1924 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001925 MCContext &Ctx) {
1926 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001927 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001928 Op->Barrier.Data = Str.data();
1929 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001930 Op->StartLoc = S;
1931 Op->EndLoc = S;
1932 return Op;
1933 }
1934
Tim Northover7cd58932015-01-22 17:23:04 +00001935 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1936 uint32_t MRSReg,
1937 uint32_t MSRReg,
1938 uint32_t PStateField,
1939 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001940 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001941 Op->SysReg.Data = Str.data();
1942 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001943 Op->SysReg.MRSReg = MRSReg;
1944 Op->SysReg.MSRReg = MSRReg;
1945 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001946 Op->StartLoc = S;
1947 Op->EndLoc = S;
1948 return Op;
1949 }
1950
David Blaikie960ea3f2014-06-08 16:18:35 +00001951 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1952 SMLoc E, MCContext &Ctx) {
1953 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001954 Op->SysCRImm.Val = Val;
1955 Op->StartLoc = S;
1956 Op->EndLoc = E;
1957 return Op;
1958 }
1959
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001960 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1961 StringRef Str,
1962 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001963 MCContext &Ctx) {
1964 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001965 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001966 Op->Barrier.Data = Str.data();
1967 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001968 Op->StartLoc = S;
1969 Op->EndLoc = S;
1970 return Op;
1971 }
1972
Oliver Stannarda34e4702015-12-01 10:48:51 +00001973 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1974 StringRef Str,
1975 SMLoc S,
1976 MCContext &Ctx) {
1977 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1978 Op->PSBHint.Val = Val;
1979 Op->PSBHint.Data = Str.data();
1980 Op->PSBHint.Length = Str.size();
1981 Op->StartLoc = S;
1982 Op->EndLoc = S;
1983 return Op;
1984 }
1985
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001986 static std::unique_ptr<AArch64Operand> CreateBTIHint(unsigned Val,
1987 StringRef Str,
1988 SMLoc S,
1989 MCContext &Ctx) {
1990 auto Op = make_unique<AArch64Operand>(k_BTIHint, Ctx);
1991 Op->BTIHint.Val = Val << 1 | 32;
1992 Op->BTIHint.Data = Str.data();
1993 Op->BTIHint.Length = Str.size();
1994 Op->StartLoc = S;
1995 Op->EndLoc = S;
1996 return Op;
1997 }
1998
David Blaikie960ea3f2014-06-08 16:18:35 +00001999 static std::unique_ptr<AArch64Operand>
2000 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
2001 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
2002 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00002003 Op->ShiftExtend.Type = ShOp;
2004 Op->ShiftExtend.Amount = Val;
2005 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
2006 Op->StartLoc = S;
2007 Op->EndLoc = E;
2008 return Op;
2009 }
2010};
2011
2012} // end anonymous namespace.
2013
2014void AArch64Operand::print(raw_ostream &OS) const {
2015 switch (Kind) {
2016 case k_FPImm:
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002017 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
2018 if (!getFPImmIsExact())
2019 OS << " (inexact)";
2020 OS << ">";
Tim Northover3b0846e2014-05-24 12:50:23 +00002021 break;
2022 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00002023 StringRef Name = getBarrierName();
2024 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00002025 OS << "<barrier " << Name << ">";
2026 else
2027 OS << "<barrier invalid #" << getBarrier() << ">";
2028 break;
2029 }
2030 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00002031 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00002032 break;
2033 case k_ShiftedImm: {
2034 unsigned Shift = getShiftedImmShift();
2035 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00002036 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00002037 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
2038 break;
2039 }
2040 case k_CondCode:
2041 OS << "<condcode " << getCondCode() << ">";
2042 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00002043 case k_VectorList: {
2044 OS << "<vectorlist ";
2045 unsigned Reg = getVectorListStart();
2046 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
2047 OS << Reg + i << " ";
2048 OS << ">";
2049 break;
2050 }
2051 case k_VectorIndex:
2052 OS << "<vectorindex " << getVectorIndex() << ">";
2053 break;
2054 case k_SysReg:
2055 OS << "<sysreg: " << getSysReg() << '>';
2056 break;
2057 case k_Token:
2058 OS << "'" << getToken() << "'";
2059 break;
2060 case k_SysCR:
2061 OS << "c" << getSysCR();
2062 break;
2063 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00002064 StringRef Name = getPrefetchName();
2065 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00002066 OS << "<prfop " << Name << ">";
2067 else
2068 OS << "<prfop invalid #" << getPrefetch() << ">";
2069 break;
2070 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00002071 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00002072 OS << getPSBHintName();
2073 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00002074 case k_Register:
2075 OS << "<register " << getReg() << ">";
2076 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
2077 break;
2078 LLVM_FALLTHROUGH;
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00002079 case k_BTIHint:
2080 OS << getBTIHintName();
2081 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00002082 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00002083 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
2084 << getShiftExtendAmount();
2085 if (!hasShiftExtendAmount())
2086 OS << "<imp>";
2087 OS << '>';
2088 break;
2089 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002090}
2091
2092/// @name Auto-generated Match Functions
2093/// {
2094
2095static unsigned MatchRegisterName(StringRef Name);
2096
2097/// }
2098
Florian Hahnc4422242017-11-07 13:07:50 +00002099static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00002100 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00002101 .Case("v0", AArch64::Q0)
2102 .Case("v1", AArch64::Q1)
2103 .Case("v2", AArch64::Q2)
2104 .Case("v3", AArch64::Q3)
2105 .Case("v4", AArch64::Q4)
2106 .Case("v5", AArch64::Q5)
2107 .Case("v6", AArch64::Q6)
2108 .Case("v7", AArch64::Q7)
2109 .Case("v8", AArch64::Q8)
2110 .Case("v9", AArch64::Q9)
2111 .Case("v10", AArch64::Q10)
2112 .Case("v11", AArch64::Q11)
2113 .Case("v12", AArch64::Q12)
2114 .Case("v13", AArch64::Q13)
2115 .Case("v14", AArch64::Q14)
2116 .Case("v15", AArch64::Q15)
2117 .Case("v16", AArch64::Q16)
2118 .Case("v17", AArch64::Q17)
2119 .Case("v18", AArch64::Q18)
2120 .Case("v19", AArch64::Q19)
2121 .Case("v20", AArch64::Q20)
2122 .Case("v21", AArch64::Q21)
2123 .Case("v22", AArch64::Q22)
2124 .Case("v23", AArch64::Q23)
2125 .Case("v24", AArch64::Q24)
2126 .Case("v25", AArch64::Q25)
2127 .Case("v26", AArch64::Q26)
2128 .Case("v27", AArch64::Q27)
2129 .Case("v28", AArch64::Q28)
2130 .Case("v29", AArch64::Q29)
2131 .Case("v30", AArch64::Q30)
2132 .Case("v31", AArch64::Q31)
2133 .Default(0);
2134}
2135
Sander de Smalen73937b72018-04-11 07:36:10 +00002136/// Returns an optional pair of (#elements, element-width) if Suffix
2137/// is a valid vector kind. Where the number of elements in a vector
2138/// or the vector width is implicit or explicitly unknown (but still a
2139/// valid suffix kind), 0 is used.
2140static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2141 RegKind VectorKind) {
2142 std::pair<int, int> Res = {-1, -1};
2143
2144 switch (VectorKind) {
2145 case RegKind::NeonVector:
2146 Res =
2147 StringSwitch<std::pair<int, int>>(Suffix.lower())
2148 .Case("", {0, 0})
2149 .Case(".1d", {1, 64})
2150 .Case(".1q", {1, 128})
2151 // '.2h' needed for fp16 scalar pairwise reductions
2152 .Case(".2h", {2, 16})
2153 .Case(".2s", {2, 32})
2154 .Case(".2d", {2, 64})
2155 // '.4b' is another special case for the ARMv8.2a dot product
2156 // operand
2157 .Case(".4b", {4, 8})
2158 .Case(".4h", {4, 16})
2159 .Case(".4s", {4, 32})
2160 .Case(".8b", {8, 8})
2161 .Case(".8h", {8, 16})
2162 .Case(".16b", {16, 8})
2163 // Accept the width neutral ones, too, for verbose syntax. If those
2164 // aren't used in the right places, the token operand won't match so
2165 // all will work out.
2166 .Case(".b", {0, 8})
2167 .Case(".h", {0, 16})
2168 .Case(".s", {0, 32})
2169 .Case(".d", {0, 64})
2170 .Default({-1, -1});
2171 break;
2172 case RegKind::SVEPredicateVector:
2173 case RegKind::SVEDataVector:
2174 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2175 .Case("", {0, 0})
2176 .Case(".b", {0, 8})
2177 .Case(".h", {0, 16})
2178 .Case(".s", {0, 32})
2179 .Case(".d", {0, 64})
2180 .Case(".q", {0, 128})
2181 .Default({-1, -1});
2182 break;
2183 default:
2184 llvm_unreachable("Unsupported RegKind");
2185 }
2186
2187 if (Res == std::make_pair(-1, -1))
2188 return Optional<std::pair<int, int>>();
2189
2190 return Optional<std::pair<int, int>>(Res);
2191}
2192
2193static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2194 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002195}
2196
Florian Hahn91f11e52017-11-07 16:45:48 +00002197static unsigned matchSVEDataVectorRegName(StringRef Name) {
2198 return StringSwitch<unsigned>(Name.lower())
2199 .Case("z0", AArch64::Z0)
2200 .Case("z1", AArch64::Z1)
2201 .Case("z2", AArch64::Z2)
2202 .Case("z3", AArch64::Z3)
2203 .Case("z4", AArch64::Z4)
2204 .Case("z5", AArch64::Z5)
2205 .Case("z6", AArch64::Z6)
2206 .Case("z7", AArch64::Z7)
2207 .Case("z8", AArch64::Z8)
2208 .Case("z9", AArch64::Z9)
2209 .Case("z10", AArch64::Z10)
2210 .Case("z11", AArch64::Z11)
2211 .Case("z12", AArch64::Z12)
2212 .Case("z13", AArch64::Z13)
2213 .Case("z14", AArch64::Z14)
2214 .Case("z15", AArch64::Z15)
2215 .Case("z16", AArch64::Z16)
2216 .Case("z17", AArch64::Z17)
2217 .Case("z18", AArch64::Z18)
2218 .Case("z19", AArch64::Z19)
2219 .Case("z20", AArch64::Z20)
2220 .Case("z21", AArch64::Z21)
2221 .Case("z22", AArch64::Z22)
2222 .Case("z23", AArch64::Z23)
2223 .Case("z24", AArch64::Z24)
2224 .Case("z25", AArch64::Z25)
2225 .Case("z26", AArch64::Z26)
2226 .Case("z27", AArch64::Z27)
2227 .Case("z28", AArch64::Z28)
2228 .Case("z29", AArch64::Z29)
2229 .Case("z30", AArch64::Z30)
2230 .Case("z31", AArch64::Z31)
2231 .Default(0);
2232}
2233
Sander de Smalencd6be962017-12-20 11:02:42 +00002234static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2235 return StringSwitch<unsigned>(Name.lower())
2236 .Case("p0", AArch64::P0)
2237 .Case("p1", AArch64::P1)
2238 .Case("p2", AArch64::P2)
2239 .Case("p3", AArch64::P3)
2240 .Case("p4", AArch64::P4)
2241 .Case("p5", AArch64::P5)
2242 .Case("p6", AArch64::P6)
2243 .Case("p7", AArch64::P7)
2244 .Case("p8", AArch64::P8)
2245 .Case("p9", AArch64::P9)
2246 .Case("p10", AArch64::P10)
2247 .Case("p11", AArch64::P11)
2248 .Case("p12", AArch64::P12)
2249 .Case("p13", AArch64::P13)
2250 .Case("p14", AArch64::P14)
2251 .Case("p15", AArch64::P15)
2252 .Default(0);
2253}
2254
Tim Northover3b0846e2014-05-24 12:50:23 +00002255bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2256 SMLoc &EndLoc) {
2257 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002258 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002259 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002260 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002261}
2262
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002263// Matches a register name or register alias previously defined by '.req'
2264unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002265 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002266 unsigned RegNum = 0;
2267 if ((RegNum = matchSVEDataVectorRegName(Name)))
2268 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2269
Sander de Smalencd6be962017-12-20 11:02:42 +00002270 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2271 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2272
Sander de Smalenc067c302017-12-20 09:45:45 +00002273 if ((RegNum = MatchNeonVectorRegName(Name)))
2274 return Kind == RegKind::NeonVector ? RegNum : 0;
2275
2276 // The parsed register must be of RegKind Scalar
2277 if ((RegNum = MatchRegisterName(Name)))
2278 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002279
Florian Hahnc4422242017-11-07 13:07:50 +00002280 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002281 // Handle a few common aliases of registers.
2282 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2283 .Case("fp", AArch64::FP)
2284 .Case("lr", AArch64::LR)
2285 .Case("x31", AArch64::XZR)
2286 .Case("w31", AArch64::WZR)
2287 .Default(0))
2288 return Kind == RegKind::Scalar ? RegNum : 0;
2289
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002290 // Check for aliases registered via .req. Canonicalize to lower case.
2291 // That's more consistent since register names are case insensitive, and
2292 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2293 auto Entry = RegisterReqs.find(Name.lower());
2294 if (Entry == RegisterReqs.end())
2295 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002296
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002297 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002298 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002299 RegNum = Entry->getValue().second;
2300 }
2301 return RegNum;
2302}
2303
Sander de Smalen50d87022018-04-19 07:35:08 +00002304/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002305/// Identifier when called, and if it is a register name the token is eaten and
2306/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002307OperandMatchResultTy
2308AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002309 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002310 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002311 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002312 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002313
2314 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002315 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2316 if (Reg == 0)
2317 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002318
Sander de Smalen50d87022018-04-19 07:35:08 +00002319 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002320 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002321 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002322}
2323
Tim Northover3b0846e2014-05-24 12:50:23 +00002324/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002325OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002326AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002327 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002328 SMLoc S = getLoc();
2329
2330 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2331 Error(S, "Expected cN operand where 0 <= N <= 15");
2332 return MatchOperand_ParseFail;
2333 }
2334
2335 StringRef Tok = Parser.getTok().getIdentifier();
2336 if (Tok[0] != 'c' && Tok[0] != 'C') {
2337 Error(S, "Expected cN operand where 0 <= N <= 15");
2338 return MatchOperand_ParseFail;
2339 }
2340
2341 uint32_t CRNum;
2342 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2343 if (BadNum || CRNum > 15) {
2344 Error(S, "Expected cN operand where 0 <= N <= 15");
2345 return MatchOperand_ParseFail;
2346 }
2347
2348 Parser.Lex(); // Eat identifier token.
2349 Operands.push_back(
2350 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2351 return MatchOperand_Success;
2352}
2353
2354/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002355template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002356OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002357AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002358 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002359 SMLoc S = getLoc();
2360 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002361
2362 auto LookupByName = [](StringRef N) {
2363 if (IsSVEPrefetch) {
2364 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2365 return Optional<unsigned>(Res->Encoding);
2366 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2367 return Optional<unsigned>(Res->Encoding);
2368 return Optional<unsigned>();
2369 };
2370
2371 auto LookupByEncoding = [](unsigned E) {
2372 if (IsSVEPrefetch) {
2373 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2374 return Optional<StringRef>(Res->Name);
2375 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2376 return Optional<StringRef>(Res->Name);
2377 return Optional<StringRef>();
2378 };
2379 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2380
Tim Northover3b0846e2014-05-24 12:50:23 +00002381 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002382 // Eat optional hash.
2383 if (parseOptionalToken(AsmToken::Hash) ||
2384 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002385 const MCExpr *ImmVal;
2386 if (getParser().parseExpression(ImmVal))
2387 return MatchOperand_ParseFail;
2388
2389 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2390 if (!MCE) {
2391 TokError("immediate value expected for prefetch operand");
2392 return MatchOperand_ParseFail;
2393 }
2394 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002395 if (prfop > MaxVal) {
2396 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2397 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002398 return MatchOperand_ParseFail;
2399 }
2400
Sander de Smalen93380372018-05-14 11:54:41 +00002401 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002402 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002403 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002404 return MatchOperand_Success;
2405 }
2406
2407 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002408 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002409 return MatchOperand_ParseFail;
2410 }
2411
Sander de Smalen93380372018-05-14 11:54:41 +00002412 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002413 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002414 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002415 return MatchOperand_ParseFail;
2416 }
2417
2418 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002419 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002420 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002421 return MatchOperand_Success;
2422}
2423
Oliver Stannarda34e4702015-12-01 10:48:51 +00002424/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002425OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002426AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2427 MCAsmParser &Parser = getParser();
2428 SMLoc S = getLoc();
2429 const AsmToken &Tok = Parser.getTok();
2430 if (Tok.isNot(AsmToken::Identifier)) {
2431 TokError("invalid operand for instruction");
2432 return MatchOperand_ParseFail;
2433 }
2434
Tim Northovere6ae6762016-07-05 21:23:04 +00002435 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2436 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002437 TokError("invalid operand for instruction");
2438 return MatchOperand_ParseFail;
2439 }
2440
2441 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002442 Operands.push_back(AArch64Operand::CreatePSBHint(
2443 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002444 return MatchOperand_Success;
2445}
2446
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00002447/// tryParseBTIHint - Try to parse a BTI operand, mapped to Hint command
2448OperandMatchResultTy
2449AArch64AsmParser::tryParseBTIHint(OperandVector &Operands) {
2450 MCAsmParser &Parser = getParser();
2451 SMLoc S = getLoc();
2452 const AsmToken &Tok = Parser.getTok();
2453 if (Tok.isNot(AsmToken::Identifier)) {
2454 TokError("invalid operand for instruction");
2455 return MatchOperand_ParseFail;
2456 }
2457
2458 auto BTI = AArch64BTIHint::lookupBTIByName(Tok.getString());
2459 if (!BTI) {
2460 TokError("invalid operand for instruction");
2461 return MatchOperand_ParseFail;
2462 }
2463
2464 Parser.Lex(); // Eat identifier token.
2465 Operands.push_back(AArch64Operand::CreateBTIHint(
2466 BTI->Encoding, Tok.getString(), S, getContext()));
2467 return MatchOperand_Success;
2468}
2469
Tim Northover3b0846e2014-05-24 12:50:23 +00002470/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2471/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002472OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002473AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002474 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002475 SMLoc S = getLoc();
2476 const MCExpr *Expr;
2477
2478 if (Parser.getTok().is(AsmToken::Hash)) {
2479 Parser.Lex(); // Eat hash token.
2480 }
2481
2482 if (parseSymbolicImmVal(Expr))
2483 return MatchOperand_ParseFail;
2484
2485 AArch64MCExpr::VariantKind ELFRefKind;
2486 MCSymbolRefExpr::VariantKind DarwinRefKind;
2487 int64_t Addend;
2488 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2489 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2490 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2491 // No modifier was specified at all; this is the syntax for an ELF basic
2492 // ADRP relocation (unfortunately).
2493 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002494 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002495 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2496 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2497 Addend != 0) {
2498 Error(S, "gotpage label reference not allowed an addend");
2499 return MatchOperand_ParseFail;
2500 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2501 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2502 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2503 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2504 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2505 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2506 // The operand must be an @page or @gotpage qualified symbolref.
2507 Error(S, "page or gotpage label reference expected");
2508 return MatchOperand_ParseFail;
2509 }
2510 }
2511
2512 // We have either a label reference possibly with addend or an immediate. The
2513 // addend is a raw value here. The linker will adjust it to only reference the
2514 // page.
2515 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2516 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2517
2518 return MatchOperand_Success;
2519}
2520
2521/// tryParseAdrLabel - Parse and validate a source label for the ADR
2522/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002523OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002524AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2525 SMLoc S = getLoc();
2526 const MCExpr *Expr;
2527
David Green9dd1d452018-08-22 11:31:39 +00002528 // Leave anything with a bracket to the default for SVE
2529 if (getParser().getTok().is(AsmToken::LBrac))
2530 return MatchOperand_NoMatch;
2531
2532 if (getParser().getTok().is(AsmToken::Hash))
2533 getParser().Lex(); // Eat hash token.
2534
2535 if (parseSymbolicImmVal(Expr))
2536 return MatchOperand_ParseFail;
2537
2538 AArch64MCExpr::VariantKind ELFRefKind;
2539 MCSymbolRefExpr::VariantKind DarwinRefKind;
2540 int64_t Addend;
2541 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2542 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2543 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2544 // No modifier was specified at all; this is the syntax for an ELF basic
2545 // ADR relocation (unfortunately).
2546 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS, getContext());
2547 } else {
2548 Error(S, "unexpected adr label");
Sander de Smalenc69944c2018-07-09 09:58:24 +00002549 return MatchOperand_ParseFail;
David Green9dd1d452018-08-22 11:31:39 +00002550 }
Sander de Smalenc69944c2018-07-09 09:58:24 +00002551 }
David Green9dd1d452018-08-22 11:31:39 +00002552
2553 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2554 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2555 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002556}
2557
2558/// tryParseFPImm - A floating point immediate expression operand.
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002559template<bool AddFPZeroAsLiteral>
Alex Bradbury58eba092016-11-01 16:32:05 +00002560OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002561AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002562 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002563 SMLoc S = getLoc();
2564
Nirav Davee833c6c2016-11-08 18:31:04 +00002565 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002566
2567 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002568 bool isNegative = parseOptionalToken(AsmToken::Minus);
2569
Tim Northover3b0846e2014-05-24 12:50:23 +00002570 const AsmToken &Tok = Parser.getTok();
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002571 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2572 if (!Hash)
2573 return MatchOperand_NoMatch;
2574 TokError("invalid floating point immediate");
2575 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002576 }
2577
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002578 // Parse hexadecimal representation.
2579 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2580 if (Tok.getIntVal() > 255 || isNegative) {
2581 TokError("encoded floating point value out of range");
2582 return MatchOperand_ParseFail;
2583 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002584
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002585 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2586 Operands.push_back(
2587 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2588 } else {
2589 // Parse FP representation.
2590 APFloat RealVal(APFloat::IEEEdouble());
2591 auto Status =
2592 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2593 if (isNegative)
2594 RealVal.changeSign();
2595
2596 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2597 Operands.push_back(
2598 AArch64Operand::CreateToken("#0", false, S, getContext()));
2599 Operands.push_back(
2600 AArch64Operand::CreateToken(".0", false, S, getContext()));
2601 } else
2602 Operands.push_back(AArch64Operand::CreateFPImm(
2603 RealVal, Status == APFloat::opOK, S, getContext()));
2604 }
2605
2606 Parser.Lex(); // Eat the token.
2607
2608 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002609}
2610
Sander de Smalen62770792018-05-25 09:47:52 +00002611/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2612/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002613OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002614AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002615 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002616 SMLoc S = getLoc();
2617
2618 if (Parser.getTok().is(AsmToken::Hash))
2619 Parser.Lex(); // Eat '#'
2620 else if (Parser.getTok().isNot(AsmToken::Integer))
2621 // Operand should start from # or should be integer, emit error otherwise.
2622 return MatchOperand_NoMatch;
2623
2624 const MCExpr *Imm;
2625 if (parseSymbolicImmVal(Imm))
2626 return MatchOperand_ParseFail;
2627 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002628 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002629 Operands.push_back(
2630 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002631 return MatchOperand_Success;
2632 }
2633
2634 // Eat ','
2635 Parser.Lex();
2636
2637 // The optional operand must be "lsl #N" where N is non-negative.
2638 if (!Parser.getTok().is(AsmToken::Identifier) ||
2639 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2640 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2641 return MatchOperand_ParseFail;
2642 }
2643
2644 // Eat 'lsl'
2645 Parser.Lex();
2646
Nirav Davee833c6c2016-11-08 18:31:04 +00002647 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002648
2649 if (Parser.getTok().isNot(AsmToken::Integer)) {
2650 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2651 return MatchOperand_ParseFail;
2652 }
2653
2654 int64_t ShiftAmount = Parser.getTok().getIntVal();
2655
2656 if (ShiftAmount < 0) {
2657 Error(Parser.getTok().getLoc(), "positive shift amount required");
2658 return MatchOperand_ParseFail;
2659 }
2660 Parser.Lex(); // Eat the number
2661
Sander de Smalen62770792018-05-25 09:47:52 +00002662 // Just in case the optional lsl #0 is used for immediates other than zero.
2663 if (ShiftAmount == 0 && Imm != 0) {
2664 SMLoc E = Parser.getTok().getLoc();
2665 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2666 return MatchOperand_Success;
2667 }
2668
Tim Northover3b0846e2014-05-24 12:50:23 +00002669 SMLoc E = Parser.getTok().getLoc();
2670 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2671 S, E, getContext()));
2672 return MatchOperand_Success;
2673}
2674
2675/// parseCondCodeString - Parse a Condition Code string.
2676AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2677 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2678 .Case("eq", AArch64CC::EQ)
2679 .Case("ne", AArch64CC::NE)
2680 .Case("cs", AArch64CC::HS)
2681 .Case("hs", AArch64CC::HS)
2682 .Case("cc", AArch64CC::LO)
2683 .Case("lo", AArch64CC::LO)
2684 .Case("mi", AArch64CC::MI)
2685 .Case("pl", AArch64CC::PL)
2686 .Case("vs", AArch64CC::VS)
2687 .Case("vc", AArch64CC::VC)
2688 .Case("hi", AArch64CC::HI)
2689 .Case("ls", AArch64CC::LS)
2690 .Case("ge", AArch64CC::GE)
2691 .Case("lt", AArch64CC::LT)
2692 .Case("gt", AArch64CC::GT)
2693 .Case("le", AArch64CC::LE)
2694 .Case("al", AArch64CC::AL)
2695 .Case("nv", AArch64CC::NV)
2696 .Default(AArch64CC::Invalid);
Sander de Smalene31e6d42018-07-04 08:50:49 +00002697
2698 if (CC == AArch64CC::Invalid &&
2699 getSTI().getFeatureBits()[AArch64::FeatureSVE])
2700 CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2701 .Case("none", AArch64CC::EQ)
2702 .Case("any", AArch64CC::NE)
2703 .Case("nlast", AArch64CC::HS)
2704 .Case("last", AArch64CC::LO)
2705 .Case("first", AArch64CC::MI)
2706 .Case("nfrst", AArch64CC::PL)
2707 .Case("pmore", AArch64CC::HI)
2708 .Case("plast", AArch64CC::LS)
2709 .Case("tcont", AArch64CC::GE)
2710 .Case("tstop", AArch64CC::LT)
2711 .Default(AArch64CC::Invalid);
2712
Tim Northover3b0846e2014-05-24 12:50:23 +00002713 return CC;
2714}
2715
2716/// parseCondCode - Parse a Condition Code operand.
2717bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2718 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002719 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002720 SMLoc S = getLoc();
2721 const AsmToken &Tok = Parser.getTok();
2722 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2723
2724 StringRef Cond = Tok.getString();
2725 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2726 if (CC == AArch64CC::Invalid)
2727 return TokError("invalid condition code");
2728 Parser.Lex(); // Eat identifier token.
2729
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002730 if (invertCondCode) {
2731 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2732 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002733 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002734 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002735
2736 Operands.push_back(
2737 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2738 return false;
2739}
2740
2741/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2742/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002743OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002744AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002745 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002746 const AsmToken &Tok = Parser.getTok();
2747 std::string LowerID = Tok.getString().lower();
2748 AArch64_AM::ShiftExtendType ShOp =
2749 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2750 .Case("lsl", AArch64_AM::LSL)
2751 .Case("lsr", AArch64_AM::LSR)
2752 .Case("asr", AArch64_AM::ASR)
2753 .Case("ror", AArch64_AM::ROR)
2754 .Case("msl", AArch64_AM::MSL)
2755 .Case("uxtb", AArch64_AM::UXTB)
2756 .Case("uxth", AArch64_AM::UXTH)
2757 .Case("uxtw", AArch64_AM::UXTW)
2758 .Case("uxtx", AArch64_AM::UXTX)
2759 .Case("sxtb", AArch64_AM::SXTB)
2760 .Case("sxth", AArch64_AM::SXTH)
2761 .Case("sxtw", AArch64_AM::SXTW)
2762 .Case("sxtx", AArch64_AM::SXTX)
2763 .Default(AArch64_AM::InvalidShiftExtend);
2764
2765 if (ShOp == AArch64_AM::InvalidShiftExtend)
2766 return MatchOperand_NoMatch;
2767
2768 SMLoc S = Tok.getLoc();
2769 Parser.Lex();
2770
Nirav Davee833c6c2016-11-08 18:31:04 +00002771 bool Hash = parseOptionalToken(AsmToken::Hash);
2772
Tim Northover3b0846e2014-05-24 12:50:23 +00002773 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2774 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2775 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2776 ShOp == AArch64_AM::MSL) {
2777 // We expect a number here.
2778 TokError("expected #imm after shift specifier");
2779 return MatchOperand_ParseFail;
2780 }
2781
Chad Rosier2ff37b82016-12-27 16:58:09 +00002782 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002783 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2784 Operands.push_back(
2785 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2786 return MatchOperand_Success;
2787 }
2788
Chad Rosier2ff37b82016-12-27 16:58:09 +00002789 // Make sure we do actually have a number, identifier or a parenthesized
2790 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002791 SMLoc E = Parser.getTok().getLoc();
2792 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002793 !Parser.getTok().is(AsmToken::LParen) &&
2794 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002795 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002796 return MatchOperand_ParseFail;
2797 }
2798
2799 const MCExpr *ImmVal;
2800 if (getParser().parseExpression(ImmVal))
2801 return MatchOperand_ParseFail;
2802
2803 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2804 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002805 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002806 return MatchOperand_ParseFail;
2807 }
2808
Jim Grosbach57fd2622014-09-23 22:16:02 +00002809 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002810 Operands.push_back(AArch64Operand::CreateShiftExtend(
2811 ShOp, MCE->getValue(), true, S, E, getContext()));
2812 return MatchOperand_Success;
2813}
2814
Oliver Stannard89b16042018-09-26 13:52:27 +00002815static const struct Extension {
2816 const char *Name;
2817 const FeatureBitset Features;
2818} ExtensionMap[] = {
Diogo N. Sampaio9c906732018-12-06 15:39:17 +00002819 {"crc", {AArch64::FeatureCRC}},
2820 {"sm4", {AArch64::FeatureSM4}},
2821 {"sha3", {AArch64::FeatureSHA3}},
2822 {"sha2", {AArch64::FeatureSHA2}},
2823 {"aes", {AArch64::FeatureAES}},
2824 {"crypto", {AArch64::FeatureCrypto}},
2825 {"fp", {AArch64::FeatureFPARMv8}},
2826 {"simd", {AArch64::FeatureNEON}},
2827 {"ras", {AArch64::FeatureRAS}},
2828 {"lse", {AArch64::FeatureLSE}},
Diogo N. Sampaio1eb31c82019-01-09 11:24:15 +00002829 {"predres", {AArch64::FeaturePredRes}},
Diogo N. Sampaio9c906732018-12-06 15:39:17 +00002830 {"ccdp", {AArch64::FeatureCacheDeepPersist}},
2831 {"mte", {AArch64::FeatureMTE}},
2832 {"tlb-rmi", {AArch64::FeatureTLB_RMI}},
2833 {"pan-rwv", {AArch64::FeaturePAN_RWV}},
2834 {"ccpp", {AArch64::FeatureCCPP}},
Martin Storsjo74d93f92018-12-31 10:22:04 +00002835 {"sve", {AArch64::FeatureSVE}},
Diogo N. Sampaio9c906732018-12-06 15:39:17 +00002836 // FIXME: Unsupported extensions
2837 {"pan", {}},
2838 {"lor", {}},
2839 {"rdma", {}},
2840 {"profile", {}},
Oliver Stannard89b16042018-09-26 13:52:27 +00002841};
2842
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002843static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2844 if (FBS[AArch64::HasV8_1aOps])
2845 Str += "ARMv8.1a";
2846 else if (FBS[AArch64::HasV8_2aOps])
2847 Str += "ARMv8.2a";
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002848 else if (FBS[AArch64::HasV8_3aOps])
2849 Str += "ARMv8.3a";
2850 else if (FBS[AArch64::HasV8_4aOps])
2851 Str += "ARMv8.4a";
Oliver Stannard89b16042018-09-26 13:52:27 +00002852 else if (FBS[AArch64::HasV8_5aOps])
2853 Str += "ARMv8.5a";
2854 else {
2855 auto ext = std::find_if(std::begin(ExtensionMap),
2856 std::end(ExtensionMap),
2857 [&](const Extension& e)
2858 // Use & in case multiple features are enabled
2859 { return (FBS & e.Features) != FeatureBitset(); }
2860 );
2861
2862 Str += ext != std::end(ExtensionMap) ? ext->Name : "(unknown)";
2863 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002864}
2865
2866void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2867 SMLoc S) {
2868 const uint16_t Op2 = Encoding & 7;
2869 const uint16_t Cm = (Encoding & 0x78) >> 3;
2870 const uint16_t Cn = (Encoding & 0x780) >> 7;
2871 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2872
2873 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2874
2875 Operands.push_back(
2876 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2877 Operands.push_back(
2878 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2879 Operands.push_back(
2880 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2881 Expr = MCConstantExpr::create(Op2, getContext());
2882 Operands.push_back(
2883 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2884}
2885
Tim Northover3b0846e2014-05-24 12:50:23 +00002886/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2887/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2888bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2889 OperandVector &Operands) {
2890 if (Name.find('.') != StringRef::npos)
2891 return TokError("invalid operand");
2892
2893 Mnemonic = Name;
2894 Operands.push_back(
2895 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2896
Rafael Espindola961d4692014-11-11 05:18:41 +00002897 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002898 const AsmToken &Tok = Parser.getTok();
2899 StringRef Op = Tok.getString();
2900 SMLoc S = Tok.getLoc();
2901
Tim Northover3b0846e2014-05-24 12:50:23 +00002902 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002903 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2904 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002905 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002906 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2907 std::string Str("IC " + std::string(IC->Name) + " requires ");
2908 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2909 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002910 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002911 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002912 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002913 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2914 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002915 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002916 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2917 std::string Str("DC " + std::string(DC->Name) + " requires ");
2918 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2919 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002920 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002921 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002922 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002923 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2924 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002925 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002926 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2927 std::string Str("AT " + std::string(AT->Name) + " requires ");
2928 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2929 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002930 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002931 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002932 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002933 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2934 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002935 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002936 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2937 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2938 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2939 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002940 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002941 createSysAlias(TLBI->Encoding, Operands, S);
Oliver Stannard224428c2018-09-27 13:47:40 +00002942 } else if (Mnemonic == "cfp" || Mnemonic == "dvp" || Mnemonic == "cpp") {
2943 const AArch64PRCTX::PRCTX *PRCTX = AArch64PRCTX::lookupPRCTXByName(Op);
2944 if (!PRCTX)
2945 return TokError("invalid operand for prediction restriction instruction");
2946 else if (!PRCTX->haveFeatures(getSTI().getFeatureBits())) {
2947 std::string Str(
2948 Mnemonic.upper() + std::string(PRCTX->Name) + " requires ");
2949 setRequiredFeatureString(PRCTX->getRequiredFeatures(), Str);
2950 return TokError(Str.c_str());
2951 }
2952 uint16_t PRCTX_Op2 =
2953 Mnemonic == "cfp" ? 4 :
2954 Mnemonic == "dvp" ? 5 :
2955 Mnemonic == "cpp" ? 7 :
2956 0;
2957 assert(PRCTX_Op2 && "Invalid mnemonic for prediction restriction instruction");
2958 createSysAlias(PRCTX->Encoding << 3 | PRCTX_Op2 , Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002959 }
2960
Tim Northover3b0846e2014-05-24 12:50:23 +00002961 Parser.Lex(); // Eat operand.
2962
2963 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2964 bool HasRegister = false;
2965
2966 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002967 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002968 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2969 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002970 HasRegister = true;
2971 }
2972
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002973 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002974 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002975 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002976 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002977
Nirav Davee833c6c2016-11-08 18:31:04 +00002978 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2979 return true;
2980
Tim Northover3b0846e2014-05-24 12:50:23 +00002981 return false;
2982}
2983
Alex Bradbury58eba092016-11-01 16:32:05 +00002984OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002985AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002986 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002987 const AsmToken &Tok = Parser.getTok();
2988
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002989 if (Mnemonic == "tsb" && Tok.isNot(AsmToken::Identifier)) {
2990 TokError("'csync' operand expected");
2991 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002992 // Can be either a #imm style literal or an option name
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002993 } else if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002994 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002995 const MCExpr *ImmVal;
2996 SMLoc ExprLoc = getLoc();
2997 if (getParser().parseExpression(ImmVal))
2998 return MatchOperand_ParseFail;
2999 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3000 if (!MCE) {
3001 Error(ExprLoc, "immediate value expected for barrier operand");
3002 return MatchOperand_ParseFail;
3003 }
3004 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
3005 Error(ExprLoc, "barrier operand out of range");
3006 return MatchOperand_ParseFail;
3007 }
Tim Northovere6ae6762016-07-05 21:23:04 +00003008 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
3009 Operands.push_back(AArch64Operand::CreateBarrier(
3010 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003011 return MatchOperand_Success;
3012 }
3013
3014 if (Tok.isNot(AsmToken::Identifier)) {
3015 TokError("invalid operand for instruction");
3016 return MatchOperand_ParseFail;
3017 }
3018
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003019 auto TSB = AArch64TSB::lookupTSBByName(Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003020 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00003021 auto DB = AArch64DB::lookupDBByName(Tok.getString());
3022 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003023 TokError("'sy' or #imm operand expected");
3024 return MatchOperand_ParseFail;
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003025 // The only valid named option for TSB is 'csync'
3026 } else if (Mnemonic == "tsb" && (!TSB || TSB->Encoding != AArch64TSB::csync)) {
3027 TokError("'csync' operand expected");
3028 return MatchOperand_ParseFail;
3029 } else if (!DB && !TSB) {
Sjoerd Meijere5b85572017-04-24 08:22:20 +00003030 TokError("invalid barrier option name");
3031 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003032 }
3033
Tim Northovere6ae6762016-07-05 21:23:04 +00003034 Operands.push_back(AArch64Operand::CreateBarrier(
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003035 DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003036 Parser.Lex(); // Consume the option
3037
3038 return MatchOperand_Success;
3039}
3040
Alex Bradbury58eba092016-11-01 16:32:05 +00003041OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003042AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003043 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003044 const AsmToken &Tok = Parser.getTok();
3045
3046 if (Tok.isNot(AsmToken::Identifier))
3047 return MatchOperand_NoMatch;
3048
Tim Northovere6ae6762016-07-05 21:23:04 +00003049 int MRSReg, MSRReg;
3050 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
3051 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
3052 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
3053 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
3054 } else
3055 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00003056
Tim Northovere6ae6762016-07-05 21:23:04 +00003057 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
3058 unsigned PStateImm = -1;
3059 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
3060 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00003061
Tim Northovere6ae6762016-07-05 21:23:04 +00003062 Operands.push_back(
3063 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
3064 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003065 Parser.Lex(); // Eat identifier
3066
3067 return MatchOperand_Success;
3068}
3069
Florian Hahnc4422242017-11-07 13:07:50 +00003070/// tryParseNeonVectorRegister - Parse a vector register operand.
3071bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003072 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003073 if (Parser.getTok().isNot(AsmToken::Identifier))
3074 return true;
3075
3076 SMLoc S = getLoc();
3077 // Check for a vector register specifier first.
3078 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003079 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00003080 OperandMatchResultTy Res =
3081 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
3082 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00003083 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00003084
3085 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
3086 if (!KindRes)
3087 return true;
3088
3089 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00003090 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00003091 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
3092 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00003093
Tim Northover3b0846e2014-05-24 12:50:23 +00003094 // If there was an explicit qualifier, that goes on as a literal text
3095 // operand.
3096 if (!Kind.empty())
3097 Operands.push_back(
3098 AArch64Operand::CreateToken(Kind, false, S, getContext()));
3099
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003100 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3101}
3102
3103OperandMatchResultTy
3104AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00003105 SMLoc SIdx = getLoc();
3106 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003107 const MCExpr *ImmVal;
3108 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003109 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00003110 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3111 if (!MCE) {
3112 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003113 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00003114 }
3115
3116 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003117
Nirav Davee833c6c2016-11-08 18:31:04 +00003118 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003119 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00003120
3121 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
3122 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003123 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003124 }
3125
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003126 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00003127}
3128
Sander de Smalen73937b72018-04-11 07:36:10 +00003129// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00003130// optional kind specifier. If it is a register specifier, eat the token
3131// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00003132OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00003133AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00003134 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00003135 MCAsmParser &Parser = getParser();
3136 const AsmToken &Tok = Parser.getTok();
3137
Florian Hahn91f11e52017-11-07 16:45:48 +00003138 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00003139 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003140
3141 StringRef Name = Tok.getString();
3142 // If there is a kind specifier, it's separated from the register name by
3143 // a '.'.
3144 size_t Start = 0, Next = Name.find('.');
3145 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00003146 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00003147
3148 if (RegNum) {
3149 if (Next != StringRef::npos) {
3150 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00003151 if (!isValidVectorKind(Kind, MatchKind)) {
3152 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00003153 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00003154 }
3155 }
Sander de Smalen8e607342017-11-15 15:44:43 +00003156 Parser.Lex(); // Eat the register token.
3157
3158 Reg = RegNum;
3159 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00003160 }
3161
Sander de Smalen8e607342017-11-15 15:44:43 +00003162 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003163}
3164
Sander de Smalencd6be962017-12-20 11:02:42 +00003165/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
3166OperandMatchResultTy
3167AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
3168 // Check for a SVE predicate register specifier first.
3169 const SMLoc S = getLoc();
3170 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003171 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00003172 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00003173 if (Res != MatchOperand_Success)
3174 return Res;
3175
Sander de Smalen73937b72018-04-11 07:36:10 +00003176 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
3177 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00003178 return MatchOperand_NoMatch;
3179
Sander de Smalen73937b72018-04-11 07:36:10 +00003180 unsigned ElementWidth = KindRes->second;
3181 Operands.push_back(AArch64Operand::CreateVectorReg(
3182 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
3183 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00003184
Sander de Smalen7868e742018-01-09 11:17:06 +00003185 // Not all predicates are followed by a '/m' or '/z'.
3186 MCAsmParser &Parser = getParser();
3187 if (Parser.getTok().isNot(AsmToken::Slash))
3188 return MatchOperand_Success;
3189
3190 // But when they do they shouldn't have an element type suffix.
3191 if (!Kind.empty()) {
3192 Error(S, "not expecting size suffix");
3193 return MatchOperand_ParseFail;
3194 }
3195
3196 // Add a literal slash as operand
3197 Operands.push_back(
3198 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
3199
3200 Parser.Lex(); // Eat the slash.
3201
3202 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00003203 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00003204 if (Pred != "z" && Pred != "m") {
3205 Error(getLoc(), "expecting 'm' or 'z' predication");
3206 return MatchOperand_ParseFail;
3207 }
3208
3209 // Add zero/merge token.
3210 const char *ZM = Pred == "z" ? "z" : "m";
3211 Operands.push_back(
3212 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
3213
3214 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00003215 return MatchOperand_Success;
3216}
3217
Sander de Smalen50d87022018-04-19 07:35:08 +00003218/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00003219bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003220 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00003221 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00003222 return false;
3223
Sander de Smalen149916d2018-04-20 07:24:20 +00003224 // Otherwise try for a scalar register.
3225 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
3226 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003227
Sander de Smalen149916d2018-04-20 07:24:20 +00003228 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003229}
3230
3231bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003232 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003233 bool HasELFModifier = false;
3234 AArch64MCExpr::VariantKind RefKind;
3235
Nirav Davee833c6c2016-11-08 18:31:04 +00003236 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003237 HasELFModifier = true;
3238
Nirav Davee833c6c2016-11-08 18:31:04 +00003239 if (Parser.getTok().isNot(AsmToken::Identifier))
3240 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003241
3242 std::string LowerCase = Parser.getTok().getIdentifier().lower();
3243 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
3244 .Case("lo12", AArch64MCExpr::VK_LO12)
3245 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
3246 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
3247 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
3248 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
3249 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
3250 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
3251 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
3252 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
3253 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
3254 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
3255 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
3256 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
3257 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3258 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3259 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3260 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3261 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3262 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3263 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3264 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3265 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3266 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3267 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3268 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3269 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3270 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3271 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3272 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3273 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3274 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3275 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3276 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3277 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3278 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003279 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3280 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00003281 .Default(AArch64MCExpr::VK_INVALID);
3282
Nirav Davee833c6c2016-11-08 18:31:04 +00003283 if (RefKind == AArch64MCExpr::VK_INVALID)
3284 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003285
3286 Parser.Lex(); // Eat identifier
3287
Nirav Davee833c6c2016-11-08 18:31:04 +00003288 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003289 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003290 }
3291
3292 if (getParser().parseExpression(ImmVal))
3293 return true;
3294
3295 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003296 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003297
3298 return false;
3299}
3300
Sander de Smalen650234b2018-04-12 11:40:52 +00003301template <RegKind VectorKind>
3302OperandMatchResultTy
3303AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3304 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003305 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003306 if (!Parser.getTok().is(AsmToken::LCurly))
3307 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003308
3309 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003310 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003311 bool NoMatchIsError) {
3312 auto RegTok = Parser.getTok();
3313 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3314 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003315 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003316 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003317 llvm_unreachable("Expected a valid vector kind");
3318 }
3319
Sander de Smalen650234b2018-04-12 11:40:52 +00003320 if (RegTok.isNot(AsmToken::Identifier) ||
3321 ParseRes == MatchOperand_ParseFail ||
3322 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3323 Error(Loc, "vector register expected");
3324 return MatchOperand_ParseFail;
3325 }
3326
3327 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003328 };
3329
Tim Northover3b0846e2014-05-24 12:50:23 +00003330 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003331 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003332 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003333
Tim Northover3b0846e2014-05-24 12:50:23 +00003334 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003335 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003336 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3337
3338 // Put back the original left bracket if there was no match, so that
3339 // different types of list-operands can be matched (e.g. SVE, Neon).
3340 if (ParseRes == MatchOperand_NoMatch)
3341 Parser.getLexer().UnLex(LCurly);
3342
3343 if (ParseRes != MatchOperand_Success)
3344 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003345
Tim Northover3b0846e2014-05-24 12:50:23 +00003346 int64_t PrevReg = FirstReg;
3347 unsigned Count = 1;
3348
Nirav Davee833c6c2016-11-08 18:31:04 +00003349 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003350 SMLoc Loc = getLoc();
3351 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003352
Sander de Smalen50d87022018-04-19 07:35:08 +00003353 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003354 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3355 if (ParseRes != MatchOperand_Success)
3356 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003357
Tim Northover3b0846e2014-05-24 12:50:23 +00003358 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003359 if (Kind != NextKind) {
3360 Error(Loc, "mismatched register size suffix");
3361 return MatchOperand_ParseFail;
3362 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003363
3364 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3365
3366 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003367 Error(Loc, "invalid number of vectors");
3368 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003369 }
3370
3371 Count += Space;
3372 }
3373 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003374 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003375 SMLoc Loc = getLoc();
3376 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003377 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003378 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3379 if (ParseRes != MatchOperand_Success)
3380 return ParseRes;
3381
Tim Northover3b0846e2014-05-24 12:50:23 +00003382 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003383 if (Kind != NextKind) {
3384 Error(Loc, "mismatched register size suffix");
3385 return MatchOperand_ParseFail;
3386 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003387
3388 // Registers must be incremental (with wraparound at 31)
3389 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003390 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3391 Error(Loc, "registers must be sequential");
3392 return MatchOperand_ParseFail;
3393 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003394
3395 PrevReg = Reg;
3396 ++Count;
3397 }
3398 }
3399
Nirav Davee833c6c2016-11-08 18:31:04 +00003400 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003401 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003402
Sander de Smalen650234b2018-04-12 11:40:52 +00003403 if (Count > 4) {
3404 Error(S, "invalid number of vectors");
3405 return MatchOperand_ParseFail;
3406 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003407
3408 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003409 unsigned ElementWidth = 0;
3410 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003411 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003412 std::tie(NumElements, ElementWidth) = *VK;
3413 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003414
3415 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003416 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3417 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003418
Sander de Smalen650234b2018-04-12 11:40:52 +00003419 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003420}
3421
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003422/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3423bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003424 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3425 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003426 return true;
3427
3428 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3429}
3430
Alex Bradbury58eba092016-11-01 16:32:05 +00003431OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003432AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003433 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003434
Sander de Smalen50d87022018-04-19 07:35:08 +00003435 unsigned RegNum;
3436 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3437 if (Res != MatchOperand_Success)
3438 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003439
Nirav Davee833c6c2016-11-08 18:31:04 +00003440 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003441 Operands.push_back(AArch64Operand::CreateReg(
3442 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003443 return MatchOperand_Success;
3444 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003445
Nirav Davee833c6c2016-11-08 18:31:04 +00003446 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003447
Sander de Smalen50d87022018-04-19 07:35:08 +00003448 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003449 Error(getLoc(), "index must be absent or #0");
3450 return MatchOperand_ParseFail;
3451 }
3452
3453 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003454 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003455 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3456 Error(getLoc(), "index must be absent or #0");
3457 return MatchOperand_ParseFail;
3458 }
3459
Sander de Smalen50d87022018-04-19 07:35:08 +00003460 Operands.push_back(AArch64Operand::CreateReg(
3461 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003462 return MatchOperand_Success;
3463}
3464
Sander de Smalen0325e302018-07-02 07:34:52 +00003465template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
Sander de Smalen149916d2018-04-20 07:24:20 +00003466OperandMatchResultTy
3467AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3468 SMLoc StartLoc = getLoc();
3469
3470 unsigned RegNum;
3471 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3472 if (Res != MatchOperand_Success)
3473 return Res;
3474
3475 // No shift/extend is the default.
3476 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3477 Operands.push_back(AArch64Operand::CreateReg(
Sander de Smalen0325e302018-07-02 07:34:52 +00003478 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
Sander de Smalen149916d2018-04-20 07:24:20 +00003479 return MatchOperand_Success;
3480 }
3481
3482 // Eat the comma
3483 getParser().Lex();
3484
3485 // Match the shift
3486 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3487 Res = tryParseOptionalShiftExtend(ExtOpnd);
3488 if (Res != MatchOperand_Success)
3489 return Res;
3490
3491 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
Sander de Smalen0325e302018-07-02 07:34:52 +00003492 Operands.push_back(AArch64Operand::CreateReg(
3493 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3494 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3495 Ext->hasShiftExtendAmount()));
Sander de Smalen149916d2018-04-20 07:24:20 +00003496
3497 return MatchOperand_Success;
3498}
3499
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003500bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
Sander de Smalen5c625982018-04-13 12:56:14 +00003501 MCAsmParser &Parser = getParser();
3502
3503 // Some SVE instructions have a decoration after the immediate, i.e.
3504 // "mul vl". We parse them here and add tokens, which must be present in the
3505 // asm string in the tablegen instruction.
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003506 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3507 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
Sander de Smalen5c625982018-04-13 12:56:14 +00003508 if (!Parser.getTok().getString().equals_lower("mul") ||
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003509 !(NextIsVL || NextIsHash))
Sander de Smalen5c625982018-04-13 12:56:14 +00003510 return true;
3511
Sander de Smalen5c625982018-04-13 12:56:14 +00003512 Operands.push_back(
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003513 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
Sander de Smalen5c625982018-04-13 12:56:14 +00003514 Parser.Lex(); // Eat the "mul"
3515
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003516 if (NextIsVL) {
3517 Operands.push_back(
3518 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3519 Parser.Lex(); // Eat the "vl"
3520 return false;
3521 }
Sander de Smalen5c625982018-04-13 12:56:14 +00003522
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003523 if (NextIsHash) {
3524 Parser.Lex(); // Eat the #
3525 SMLoc S = getLoc();
3526
3527 // Parse immediate operand.
3528 const MCExpr *ImmVal;
3529 if (!Parser.parseExpression(ImmVal))
3530 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3531 Operands.push_back(AArch64Operand::CreateImm(
3532 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3533 getContext()));
3534 return MatchOperand_Success;
3535 }
3536 }
3537
3538 return Error(getLoc(), "expected 'vl' or '#<imm>'");
Sander de Smalen5c625982018-04-13 12:56:14 +00003539}
3540
Tim Northover3b0846e2014-05-24 12:50:23 +00003541/// parseOperand - Parse a arm instruction operand. For now this parses the
3542/// operand regardless of the mnemonic.
3543bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3544 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003545 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003546
3547 OperandMatchResultTy ResTy =
3548 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3549
Tim Northover3b0846e2014-05-24 12:50:23 +00003550 // Check if the current operand has a custom associated parser, if so, try to
3551 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003552 if (ResTy == MatchOperand_Success)
3553 return false;
3554 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3555 // there was a match, but an error occurred, in which case, just return that
3556 // the operand parsing failed.
3557 if (ResTy == MatchOperand_ParseFail)
3558 return true;
3559
3560 // Nothing custom, so do general case parsing.
3561 SMLoc S, E;
3562 switch (getLexer().getKind()) {
3563 default: {
3564 SMLoc S = getLoc();
3565 const MCExpr *Expr;
3566 if (parseSymbolicImmVal(Expr))
3567 return Error(S, "invalid operand");
3568
3569 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3570 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3571 return false;
3572 }
3573 case AsmToken::LBrac: {
3574 SMLoc Loc = Parser.getTok().getLoc();
3575 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3576 getContext()));
3577 Parser.Lex(); // Eat '['
3578
3579 // There's no comma after a '[', so we can parse the next operand
3580 // immediately.
3581 return parseOperand(Operands, false, false);
3582 }
3583 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003584 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003585 case AsmToken::Identifier: {
3586 // If we're expecting a Condition Code operand, then just parse that.
3587 if (isCondCode)
3588 return parseCondCode(Operands, invertCondCode);
3589
3590 // If it's a register name, parse it.
3591 if (!parseRegister(Operands))
3592 return false;
3593
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003594 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3595 // by SVE instructions.
3596 if (!parseOptionalMulOperand(Operands))
Sander de Smalen5c625982018-04-13 12:56:14 +00003597 return false;
3598
Tim Northover3b0846e2014-05-24 12:50:23 +00003599 // This could be an optional "shift" or "extend" operand.
3600 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3601 // We can only continue if no tokens were eaten.
3602 if (GotShift != MatchOperand_NoMatch)
3603 return GotShift;
3604
3605 // This was not a register so parse other operands that start with an
3606 // identifier (like labels) as expressions and create them as immediates.
3607 const MCExpr *IdVal;
3608 S = getLoc();
3609 if (getParser().parseExpression(IdVal))
3610 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003611 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3612 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3613 return false;
3614 }
3615 case AsmToken::Integer:
3616 case AsmToken::Real:
3617 case AsmToken::Hash: {
3618 // #42 -> immediate.
3619 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003620
3621 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003622
3623 // Parse a negative sign
3624 bool isNegative = false;
3625 if (Parser.getTok().is(AsmToken::Minus)) {
3626 isNegative = true;
3627 // We need to consume this token only when we have a Real, otherwise
3628 // we let parseSymbolicImmVal take care of it
3629 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3630 Parser.Lex();
3631 }
3632
3633 // The only Real that should come through here is a literal #0.0 for
3634 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3635 // so convert the value.
3636 const AsmToken &Tok = Parser.getTok();
3637 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003638 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003639 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3640 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3641 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
Sander de Smalen8fcc3f52018-07-03 09:07:23 +00003642 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
Tim Northover3b0846e2014-05-24 12:50:23 +00003643 return TokError("unexpected floating point literal");
3644 else if (IntVal != 0 || isNegative)
3645 return TokError("expected floating-point constant #0.0");
3646 Parser.Lex(); // Eat the token.
3647
3648 Operands.push_back(
3649 AArch64Operand::CreateToken("#0", false, S, getContext()));
3650 Operands.push_back(
3651 AArch64Operand::CreateToken(".0", false, S, getContext()));
3652 return false;
3653 }
3654
3655 const MCExpr *ImmVal;
3656 if (parseSymbolicImmVal(ImmVal))
3657 return true;
3658
3659 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3660 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3661 return false;
3662 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003663 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003664 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003665 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003666 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003667 Parser.Lex(); // Eat '='
3668 const MCExpr *SubExprVal;
3669 if (getParser().parseExpression(SubExprVal))
3670 return true;
3671
David Peixottoae5ba762014-07-18 16:05:14 +00003672 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003673 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003674 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003675
3676 bool IsXReg =
3677 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3678 Operands[1]->getReg());
3679
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003680 MCContext& Ctx = getContext();
3681 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3682 // 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 +00003683 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003684 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3685 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3686 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3687 ShiftAmt += 16;
3688 Imm >>= 16;
3689 }
3690 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3691 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3692 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003693 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003694 if (ShiftAmt)
3695 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3696 ShiftAmt, true, S, E, Ctx));
3697 return false;
3698 }
David Peixottoae5ba762014-07-18 16:05:14 +00003699 APInt Simm = APInt(64, Imm << ShiftAmt);
3700 // check if the immediate is an unsigned or signed 32-bit int for W regs
3701 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3702 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003703 }
3704 // 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 +00003705 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003706 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003707 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3708 return false;
3709 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003710 }
3711}
3712
Sander de Smalen0325e302018-07-02 07:34:52 +00003713bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3714 const MCParsedAsmOperand &Op2) const {
3715 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3716 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3717 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3718 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3719 return MCTargetAsmParser::regsEqual(Op1, Op2);
3720
3721 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3722 "Testing equality of non-scalar registers not supported");
3723
3724 // Check if a registers match their sub/super register classes.
3725 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3726 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3727 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3728 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3729 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3730 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3731 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3732 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3733
3734 return false;
3735}
3736
Tim Northover3b0846e2014-05-24 12:50:23 +00003737/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3738/// operands.
3739bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3740 StringRef Name, SMLoc NameLoc,
3741 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003742 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003743 Name = StringSwitch<StringRef>(Name.lower())
3744 .Case("beq", "b.eq")
3745 .Case("bne", "b.ne")
3746 .Case("bhs", "b.hs")
3747 .Case("bcs", "b.cs")
3748 .Case("blo", "b.lo")
3749 .Case("bcc", "b.cc")
3750 .Case("bmi", "b.mi")
3751 .Case("bpl", "b.pl")
3752 .Case("bvs", "b.vs")
3753 .Case("bvc", "b.vc")
3754 .Case("bhi", "b.hi")
3755 .Case("bls", "b.ls")
3756 .Case("bge", "b.ge")
3757 .Case("blt", "b.lt")
3758 .Case("bgt", "b.gt")
3759 .Case("ble", "b.le")
3760 .Case("bal", "b.al")
3761 .Case("bnv", "b.nv")
3762 .Default(Name);
3763
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003764 // First check for the AArch64-specific .req directive.
3765 if (Parser.getTok().is(AsmToken::Identifier) &&
3766 Parser.getTok().getIdentifier() == ".req") {
3767 parseDirectiveReq(Name, NameLoc);
3768 // We always return 'error' for this, as we're done with this
3769 // statement and don't need to match the 'instruction."
3770 return true;
3771 }
3772
Tim Northover3b0846e2014-05-24 12:50:23 +00003773 // Create the leading tokens for the mnemonic, split by '.' characters.
3774 size_t Start = 0, Next = Name.find('.');
3775 StringRef Head = Name.slice(Start, Next);
3776
Oliver Stannard224428c2018-09-27 13:47:40 +00003777 // IC, DC, AT, TLBI and Prediction invalidation instructions are aliases for
3778 // the SYS instruction.
3779 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi" ||
3780 Head == "cfp" || Head == "dvp" || Head == "cpp")
Nirav Davee833c6c2016-11-08 18:31:04 +00003781 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003782
3783 Operands.push_back(
3784 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3785 Mnemonic = Head;
3786
3787 // Handle condition codes for a branch mnemonic
3788 if (Head == "b" && Next != StringRef::npos) {
3789 Start = Next;
3790 Next = Name.find('.', Start + 1);
3791 Head = Name.slice(Start + 1, Next);
3792
3793 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3794 (Head.data() - Name.data()));
3795 AArch64CC::CondCode CC = parseCondCodeString(Head);
3796 if (CC == AArch64CC::Invalid)
3797 return Error(SuffixLoc, "invalid condition code");
3798 Operands.push_back(
3799 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3800 Operands.push_back(
3801 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3802 }
3803
3804 // Add the remaining tokens in the mnemonic.
3805 while (Next != StringRef::npos) {
3806 Start = Next;
3807 Next = Name.find('.', Start + 1);
3808 Head = Name.slice(Start, Next);
3809 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3810 (Head.data() - Name.data()) + 1);
3811 Operands.push_back(
3812 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3813 }
3814
3815 // Conditional compare instructions have a Condition Code operand, which needs
3816 // to be parsed and an immediate operand created.
3817 bool condCodeFourthOperand =
3818 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3819 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3820 Head == "csinc" || Head == "csinv" || Head == "csneg");
3821
3822 // These instructions are aliases to some of the conditional select
3823 // instructions. However, the condition code is inverted in the aliased
3824 // instruction.
3825 //
3826 // FIXME: Is this the correct way to handle these? Or should the parser
3827 // generate the aliased instructions directly?
3828 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3829 bool condCodeThirdOperand =
3830 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3831
3832 // Read the remaining operands.
3833 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003834
Oliver Stannardc4190282018-10-02 10:04:39 +00003835 unsigned N = 1;
3836 do {
Tim Northover3b0846e2014-05-24 12:50:23 +00003837 // Parse and remember the operand.
3838 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3839 (N == 3 && condCodeThirdOperand) ||
3840 (N == 2 && condCodeSecondOperand),
3841 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003842 return true;
3843 }
3844
3845 // After successfully parsing some operands there are two special cases to
3846 // consider (i.e. notional operands not separated by commas). Both are due
3847 // to memory specifiers:
3848 // + An RBrac will end an address for load/store/prefetch
3849 // + An '!' will indicate a pre-indexed operation.
3850 //
3851 // It's someone else's responsibility to make sure these tokens are sane
3852 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003853
Nirav Davee833c6c2016-11-08 18:31:04 +00003854 SMLoc RLoc = Parser.getTok().getLoc();
3855 if (parseOptionalToken(AsmToken::RBrac))
3856 Operands.push_back(
3857 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3858 SMLoc ELoc = Parser.getTok().getLoc();
3859 if (parseOptionalToken(AsmToken::Exclaim))
3860 Operands.push_back(
3861 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003862
3863 ++N;
Oliver Stannardc4190282018-10-02 10:04:39 +00003864 } while (parseOptionalToken(AsmToken::Comma));
Tim Northover3b0846e2014-05-24 12:50:23 +00003865 }
3866
Nirav Davee833c6c2016-11-08 18:31:04 +00003867 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3868 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003869
Tim Northover3b0846e2014-05-24 12:50:23 +00003870 return false;
3871}
3872
Sander de Smalen9b333092018-07-30 15:42:46 +00003873static inline bool isMatchingOrAlias(unsigned ZReg, unsigned Reg) {
3874 assert((ZReg >= AArch64::Z0) && (ZReg <= AArch64::Z31));
3875 return (ZReg == ((Reg - AArch64::B0) + AArch64::Z0)) ||
3876 (ZReg == ((Reg - AArch64::H0) + AArch64::Z0)) ||
3877 (ZReg == ((Reg - AArch64::S0) + AArch64::Z0)) ||
3878 (ZReg == ((Reg - AArch64::D0) + AArch64::Z0)) ||
3879 (ZReg == ((Reg - AArch64::Q0) + AArch64::Z0)) ||
3880 (ZReg == ((Reg - AArch64::Z0) + AArch64::Z0));
3881}
3882
Tim Northover3b0846e2014-05-24 12:50:23 +00003883// FIXME: This entire function is a giant hack to provide us with decent
3884// operand range validation/diagnostics until TableGen/MC can be extended
3885// to support autogeneration of this kind of validation.
Sander de Smalen9b333092018-07-30 15:42:46 +00003886bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
3887 SmallVectorImpl<SMLoc> &Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003888 const MCRegisterInfo *RI = getContext().getRegisterInfo();
Sander de Smalen9b333092018-07-30 15:42:46 +00003889 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
3890
3891 // A prefix only applies to the instruction following it. Here we extract
3892 // prefix information for the next instruction before validating the current
3893 // one so that in the case of failure we don't erronously continue using the
3894 // current prefix.
3895 PrefixInfo Prefix = NextPrefix;
3896 NextPrefix = PrefixInfo::CreateFromInst(Inst, MCID.TSFlags);
3897
3898 // Before validating the instruction in isolation we run through the rules
3899 // applicable when it follows a prefix instruction.
3900 // NOTE: brk & hlt can be prefixed but require no additional validation.
3901 if (Prefix.isActive() &&
3902 (Inst.getOpcode() != AArch64::BRK) &&
3903 (Inst.getOpcode() != AArch64::HLT)) {
3904
3905 // Prefixed intructions must have a destructive operand.
3906 if ((MCID.TSFlags & AArch64::DestructiveInstTypeMask) ==
3907 AArch64::NotDestructive)
3908 return Error(IDLoc, "instruction is unpredictable when following a"
3909 " movprfx, suggest replacing movprfx with mov");
3910
3911 // Destination operands must match.
3912 if (Inst.getOperand(0).getReg() != Prefix.getDstReg())
3913 return Error(Loc[0], "instruction is unpredictable when following a"
3914 " movprfx writing to a different destination");
3915
3916 // Destination operand must not be used in any other location.
3917 for (unsigned i = 1; i < Inst.getNumOperands(); ++i) {
3918 if (Inst.getOperand(i).isReg() &&
3919 (MCID.getOperandConstraint(i, MCOI::TIED_TO) == -1) &&
3920 isMatchingOrAlias(Prefix.getDstReg(), Inst.getOperand(i).getReg()))
3921 return Error(Loc[0], "instruction is unpredictable when following a"
3922 " movprfx and destination also used as non-destructive"
3923 " source");
3924 }
3925
3926 auto PPRRegClass = AArch64MCRegisterClasses[AArch64::PPRRegClassID];
3927 if (Prefix.isPredicated()) {
3928 int PgIdx = -1;
3929
3930 // Find the instructions general predicate.
3931 for (unsigned i = 1; i < Inst.getNumOperands(); ++i)
3932 if (Inst.getOperand(i).isReg() &&
3933 PPRRegClass.contains(Inst.getOperand(i).getReg())) {
3934 PgIdx = i;
3935 break;
3936 }
3937
3938 // Instruction must be predicated if the movprfx is predicated.
3939 if (PgIdx == -1 ||
3940 (MCID.TSFlags & AArch64::ElementSizeMask) == AArch64::ElementSizeNone)
3941 return Error(IDLoc, "instruction is unpredictable when following a"
3942 " predicated movprfx, suggest using unpredicated movprfx");
3943
3944 // Instruction must use same general predicate as the movprfx.
3945 if (Inst.getOperand(PgIdx).getReg() != Prefix.getPgReg())
3946 return Error(IDLoc, "instruction is unpredictable when following a"
3947 " predicated movprfx using a different general predicate");
3948
3949 // Instruction element type must match the movprfx.
3950 if ((MCID.TSFlags & AArch64::ElementSizeMask) != Prefix.getElementSize())
3951 return Error(IDLoc, "instruction is unpredictable when following a"
3952 " predicated movprfx with a different element size");
3953 }
3954 }
3955
Tim Northover3b0846e2014-05-24 12:50:23 +00003956 // Check for indexed addressing modes w/ the base register being the
3957 // same as a destination/source register or pair load where
3958 // the Rt == Rt2. All of those are undefined behaviour.
3959 switch (Inst.getOpcode()) {
3960 case AArch64::LDPSWpre:
3961 case AArch64::LDPWpost:
3962 case AArch64::LDPWpre:
3963 case AArch64::LDPXpost:
3964 case AArch64::LDPXpre: {
3965 unsigned Rt = Inst.getOperand(1).getReg();
3966 unsigned Rt2 = Inst.getOperand(2).getReg();
3967 unsigned Rn = Inst.getOperand(3).getReg();
3968 if (RI->isSubRegisterEq(Rn, Rt))
3969 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3970 "is also a destination");
3971 if (RI->isSubRegisterEq(Rn, Rt2))
3972 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3973 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003974 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003975 }
3976 case AArch64::LDPDi:
3977 case AArch64::LDPQi:
3978 case AArch64::LDPSi:
3979 case AArch64::LDPSWi:
3980 case AArch64::LDPWi:
3981 case AArch64::LDPXi: {
3982 unsigned Rt = Inst.getOperand(0).getReg();
3983 unsigned Rt2 = Inst.getOperand(1).getReg();
3984 if (Rt == Rt2)
3985 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3986 break;
3987 }
3988 case AArch64::LDPDpost:
3989 case AArch64::LDPDpre:
3990 case AArch64::LDPQpost:
3991 case AArch64::LDPQpre:
3992 case AArch64::LDPSpost:
3993 case AArch64::LDPSpre:
3994 case AArch64::LDPSWpost: {
3995 unsigned Rt = Inst.getOperand(1).getReg();
3996 unsigned Rt2 = Inst.getOperand(2).getReg();
3997 if (Rt == Rt2)
3998 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3999 break;
4000 }
4001 case AArch64::STPDpost:
4002 case AArch64::STPDpre:
4003 case AArch64::STPQpost:
4004 case AArch64::STPQpre:
4005 case AArch64::STPSpost:
4006 case AArch64::STPSpre:
4007 case AArch64::STPWpost:
4008 case AArch64::STPWpre:
4009 case AArch64::STPXpost:
4010 case AArch64::STPXpre: {
4011 unsigned Rt = Inst.getOperand(1).getReg();
4012 unsigned Rt2 = Inst.getOperand(2).getReg();
4013 unsigned Rn = Inst.getOperand(3).getReg();
4014 if (RI->isSubRegisterEq(Rn, Rt))
4015 return Error(Loc[0], "unpredictable STP instruction, writeback base "
4016 "is also a source");
4017 if (RI->isSubRegisterEq(Rn, Rt2))
4018 return Error(Loc[1], "unpredictable STP instruction, writeback base "
4019 "is also a source");
4020 break;
4021 }
4022 case AArch64::LDRBBpre:
4023 case AArch64::LDRBpre:
4024 case AArch64::LDRHHpre:
4025 case AArch64::LDRHpre:
4026 case AArch64::LDRSBWpre:
4027 case AArch64::LDRSBXpre:
4028 case AArch64::LDRSHWpre:
4029 case AArch64::LDRSHXpre:
4030 case AArch64::LDRSWpre:
4031 case AArch64::LDRWpre:
4032 case AArch64::LDRXpre:
4033 case AArch64::LDRBBpost:
4034 case AArch64::LDRBpost:
4035 case AArch64::LDRHHpost:
4036 case AArch64::LDRHpost:
4037 case AArch64::LDRSBWpost:
4038 case AArch64::LDRSBXpost:
4039 case AArch64::LDRSHWpost:
4040 case AArch64::LDRSHXpost:
4041 case AArch64::LDRSWpost:
4042 case AArch64::LDRWpost:
4043 case AArch64::LDRXpost: {
4044 unsigned Rt = Inst.getOperand(1).getReg();
4045 unsigned Rn = Inst.getOperand(2).getReg();
4046 if (RI->isSubRegisterEq(Rn, Rt))
4047 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
4048 "is also a source");
4049 break;
4050 }
4051 case AArch64::STRBBpost:
4052 case AArch64::STRBpost:
4053 case AArch64::STRHHpost:
4054 case AArch64::STRHpost:
4055 case AArch64::STRWpost:
4056 case AArch64::STRXpost:
4057 case AArch64::STRBBpre:
4058 case AArch64::STRBpre:
4059 case AArch64::STRHHpre:
4060 case AArch64::STRHpre:
4061 case AArch64::STRWpre:
4062 case AArch64::STRXpre: {
4063 unsigned Rt = Inst.getOperand(1).getReg();
4064 unsigned Rn = Inst.getOperand(2).getReg();
4065 if (RI->isSubRegisterEq(Rn, Rt))
4066 return Error(Loc[0], "unpredictable STR instruction, writeback base "
4067 "is also a source");
4068 break;
4069 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004070 case AArch64::STXRB:
4071 case AArch64::STXRH:
4072 case AArch64::STXRW:
4073 case AArch64::STXRX:
4074 case AArch64::STLXRB:
4075 case AArch64::STLXRH:
4076 case AArch64::STLXRW:
4077 case AArch64::STLXRX: {
4078 unsigned Rs = Inst.getOperand(0).getReg();
4079 unsigned Rt = Inst.getOperand(1).getReg();
4080 unsigned Rn = Inst.getOperand(2).getReg();
4081 if (RI->isSubRegisterEq(Rt, Rs) ||
4082 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
4083 return Error(Loc[0],
4084 "unpredictable STXR instruction, status is also a source");
4085 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00004086 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004087 case AArch64::STXPW:
4088 case AArch64::STXPX:
4089 case AArch64::STLXPW:
4090 case AArch64::STLXPX: {
4091 unsigned Rs = Inst.getOperand(0).getReg();
4092 unsigned Rt1 = Inst.getOperand(1).getReg();
4093 unsigned Rt2 = Inst.getOperand(2).getReg();
4094 unsigned Rn = Inst.getOperand(3).getReg();
4095 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
4096 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
4097 return Error(Loc[0],
4098 "unpredictable STXP instruction, status is also a source");
4099 break;
4100 }
4101 }
4102
Tim Northover3b0846e2014-05-24 12:50:23 +00004103
4104 // Now check immediate ranges. Separate from the above as there is overlap
4105 // in the instructions being checked and this keeps the nested conditionals
4106 // to a minimum.
4107 switch (Inst.getOpcode()) {
4108 case AArch64::ADDSWri:
4109 case AArch64::ADDSXri:
4110 case AArch64::ADDWri:
4111 case AArch64::ADDXri:
4112 case AArch64::SUBSWri:
4113 case AArch64::SUBSXri:
4114 case AArch64::SUBWri:
4115 case AArch64::SUBXri: {
4116 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
4117 // some slight duplication here.
4118 if (Inst.getOperand(2).isExpr()) {
4119 const MCExpr *Expr = Inst.getOperand(2).getExpr();
4120 AArch64MCExpr::VariantKind ELFRefKind;
4121 MCSymbolRefExpr::VariantKind DarwinRefKind;
4122 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00004123 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
4124
4125 // Only allow these with ADDXri.
4126 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
4127 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
4128 Inst.getOpcode() == AArch64::ADDXri)
4129 return false;
4130
4131 // Only allow these with ADDXri/ADDWri
4132 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
4133 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
4134 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
4135 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
4136 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
4137 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
4138 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00004139 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
4140 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
4141 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00004142 (Inst.getOpcode() == AArch64::ADDXri ||
4143 Inst.getOpcode() == AArch64::ADDWri))
4144 return false;
4145
4146 // Don't allow symbol refs in the immediate field otherwise
4147 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
4148 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
4149 // 'cmp w0, 'borked')
4150 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00004151 }
Diana Picusc93518d2016-10-11 09:17:47 +00004152 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00004153 }
4154 return false;
4155 }
4156 default:
4157 return false;
4158 }
4159}
4160
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004161static std::string AArch64MnemonicSpellCheck(StringRef S,
4162 const FeatureBitset &FBS,
Craig Topper05515562017-10-26 06:46:41 +00004163 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004164
4165bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
Sander de Smalen0325e302018-07-02 07:34:52 +00004166 uint64_t ErrorInfo,
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004167 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004168 switch (ErrCode) {
Sander de Smalen0325e302018-07-02 07:34:52 +00004169 case Match_InvalidTiedOperand: {
4170 RegConstraintEqualityTy EqTy =
4171 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
4172 .getRegEqualityTy();
4173 switch (EqTy) {
4174 case RegConstraintEqualityTy::EqualsSubReg:
4175 return Error(Loc, "operand must be 64-bit form of destination register");
4176 case RegConstraintEqualityTy::EqualsSuperReg:
4177 return Error(Loc, "operand must be 32-bit form of destination register");
4178 case RegConstraintEqualityTy::EqualsReg:
4179 return Error(Loc, "operand must match destination register");
4180 }
Simon Pilgrim6dc45e62018-07-05 09:48:01 +00004181 llvm_unreachable("Unknown RegConstraintEqualityTy");
Sander de Smalen0325e302018-07-02 07:34:52 +00004182 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004183 case Match_MissingFeature:
4184 return Error(Loc,
4185 "instruction requires a CPU feature not currently enabled");
4186 case Match_InvalidOperand:
4187 return Error(Loc, "invalid operand for instruction");
4188 case Match_InvalidSuffix:
4189 return Error(Loc, "invalid type suffix for instruction");
4190 case Match_InvalidCondCode:
4191 return Error(Loc, "expected AArch64 condition code");
4192 case Match_AddSubRegExtendSmall:
4193 return Error(Loc,
Eli Friedman723835382019-05-03 00:59:52 +00004194 "expected '[su]xt[bhw]' with optional integer in range [0, 4]");
Tim Northover3b0846e2014-05-24 12:50:23 +00004195 case Match_AddSubRegExtendLarge:
4196 return Error(Loc,
4197 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
4198 case Match_AddSubSecondSource:
4199 return Error(Loc,
4200 "expected compatible register, symbol or integer in range [0, 4095]");
4201 case Match_LogicalSecondSource:
4202 return Error(Loc, "expected compatible register or logical immediate");
4203 case Match_InvalidMovImm32Shift:
4204 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
4205 case Match_InvalidMovImm64Shift:
4206 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
4207 case Match_AddSubRegShift32:
4208 return Error(Loc,
4209 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
4210 case Match_AddSubRegShift64:
4211 return Error(Loc,
4212 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
4213 case Match_InvalidFPImm:
4214 return Error(Loc,
4215 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00004216 case Match_InvalidMemoryIndexedSImm6:
4217 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00004218 case Match_InvalidMemoryIndexedSImm5:
4219 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00004220 case Match_InvalidMemoryIndexed1SImm4:
4221 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00004222 case Match_InvalidMemoryIndexed2SImm4:
4223 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00004224 case Match_InvalidMemoryIndexed3SImm4:
4225 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00004226 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00004227 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004228 case Match_InvalidMemoryIndexed16SImm4:
4229 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00004230 case Match_InvalidMemoryIndexed1SImm6:
4231 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen592718f2018-07-05 07:54:10 +00004232 case Match_InvalidMemoryIndexedSImm8:
4233 return Error(Loc, "index must be an integer in range [-128, 127].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004234 case Match_InvalidMemoryIndexedSImm9:
4235 return Error(Loc, "index must be an integer in range [-256, 255].");
Oliver Stannardc4190282018-10-02 10:04:39 +00004236 case Match_InvalidMemoryIndexed16SImm9:
4237 return Error(Loc, "index must be a multiple of 16 in range [-4096, 4080].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004238 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00004239 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004240 case Match_InvalidMemoryIndexed4SImm7:
4241 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
4242 case Match_InvalidMemoryIndexed8SImm7:
4243 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
4244 case Match_InvalidMemoryIndexed16SImm7:
4245 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00004246 case Match_InvalidMemoryIndexed8UImm5:
4247 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
4248 case Match_InvalidMemoryIndexed4UImm5:
4249 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
4250 case Match_InvalidMemoryIndexed2UImm5:
4251 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00004252 case Match_InvalidMemoryIndexed8UImm6:
4253 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
Oliver Stannardc4190282018-10-02 10:04:39 +00004254 case Match_InvalidMemoryIndexed16UImm6:
4255 return Error(Loc, "index must be a multiple of 16 in range [0, 1008].");
Sander de Smalend8e76492018-05-08 10:46:55 +00004256 case Match_InvalidMemoryIndexed4UImm6:
4257 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
4258 case Match_InvalidMemoryIndexed2UImm6:
4259 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
4260 case Match_InvalidMemoryIndexed1UImm6:
4261 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004262 case Match_InvalidMemoryWExtend8:
4263 return Error(Loc,
4264 "expected 'uxtw' or 'sxtw' with optional shift of #0");
4265 case Match_InvalidMemoryWExtend16:
4266 return Error(Loc,
4267 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
4268 case Match_InvalidMemoryWExtend32:
4269 return Error(Loc,
4270 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
4271 case Match_InvalidMemoryWExtend64:
4272 return Error(Loc,
4273 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
4274 case Match_InvalidMemoryWExtend128:
4275 return Error(Loc,
4276 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
4277 case Match_InvalidMemoryXExtend8:
4278 return Error(Loc,
4279 "expected 'lsl' or 'sxtx' with optional shift of #0");
4280 case Match_InvalidMemoryXExtend16:
4281 return Error(Loc,
4282 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
4283 case Match_InvalidMemoryXExtend32:
4284 return Error(Loc,
4285 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
4286 case Match_InvalidMemoryXExtend64:
4287 return Error(Loc,
4288 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
4289 case Match_InvalidMemoryXExtend128:
4290 return Error(Loc,
4291 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
4292 case Match_InvalidMemoryIndexed1:
4293 return Error(Loc, "index must be an integer in range [0, 4095].");
4294 case Match_InvalidMemoryIndexed2:
4295 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
4296 case Match_InvalidMemoryIndexed4:
4297 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
4298 case Match_InvalidMemoryIndexed8:
4299 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
4300 case Match_InvalidMemoryIndexed16:
4301 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004302 case Match_InvalidImm0_1:
4303 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004304 case Match_InvalidImm0_7:
4305 return Error(Loc, "immediate must be an integer in range [0, 7].");
4306 case Match_InvalidImm0_15:
4307 return Error(Loc, "immediate must be an integer in range [0, 15].");
4308 case Match_InvalidImm0_31:
4309 return Error(Loc, "immediate must be an integer in range [0, 31].");
4310 case Match_InvalidImm0_63:
4311 return Error(Loc, "immediate must be an integer in range [0, 63].");
4312 case Match_InvalidImm0_127:
4313 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004314 case Match_InvalidImm0_255:
4315 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004316 case Match_InvalidImm0_65535:
4317 return Error(Loc, "immediate must be an integer in range [0, 65535].");
4318 case Match_InvalidImm1_8:
4319 return Error(Loc, "immediate must be an integer in range [1, 8].");
4320 case Match_InvalidImm1_16:
4321 return Error(Loc, "immediate must be an integer in range [1, 16].");
4322 case Match_InvalidImm1_32:
4323 return Error(Loc, "immediate must be an integer in range [1, 32].");
4324 case Match_InvalidImm1_64:
4325 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00004326 case Match_InvalidSVEAddSubImm8:
4327 return Error(Loc, "immediate must be an integer in range [0, 255]"
4328 " with a shift amount of 0");
4329 case Match_InvalidSVEAddSubImm16:
4330 case Match_InvalidSVEAddSubImm32:
4331 case Match_InvalidSVEAddSubImm64:
4332 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
4333 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004334 case Match_InvalidSVECpyImm8:
4335 return Error(Loc, "immediate must be an integer in range [-128, 255]"
4336 " with a shift amount of 0");
4337 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00004338 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4339 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004340 case Match_InvalidSVECpyImm32:
4341 case Match_InvalidSVECpyImm64:
4342 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4343 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004344 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004345 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004346 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00004347 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004348 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00004349 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004350 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004351 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004352 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004353 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004354 case Match_InvalidSVEIndexRange0_63:
4355 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4356 case Match_InvalidSVEIndexRange0_31:
4357 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4358 case Match_InvalidSVEIndexRange0_15:
4359 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4360 case Match_InvalidSVEIndexRange0_7:
4361 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4362 case Match_InvalidSVEIndexRange0_3:
4363 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004364 case Match_InvalidLabel:
4365 return Error(Loc, "expected label or encodable integer pc offset");
4366 case Match_MRS:
4367 return Error(Loc, "expected readable system register");
4368 case Match_MSR:
4369 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00004370 case Match_InvalidComplexRotationEven:
4371 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4372 case Match_InvalidComplexRotationOdd:
4373 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004374 case Match_MnemonicFail: {
4375 std::string Suggestion = AArch64MnemonicSpellCheck(
4376 ((AArch64Operand &)*Operands[0]).getToken(),
4377 ComputeAvailableFeatures(STI->getFeatureBits()));
4378 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4379 }
Sander de Smalen367694b2018-04-20 08:54:49 +00004380 case Match_InvalidGPR64shifted8:
4381 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4382 case Match_InvalidGPR64shifted16:
4383 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4384 case Match_InvalidGPR64shifted32:
4385 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4386 case Match_InvalidGPR64shifted64:
4387 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4388 case Match_InvalidGPR64NoXZRshifted8:
4389 return Error(Loc, "register must be x0..x30 without shift");
4390 case Match_InvalidGPR64NoXZRshifted16:
4391 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4392 case Match_InvalidGPR64NoXZRshifted32:
4393 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4394 case Match_InvalidGPR64NoXZRshifted64:
4395 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004396 case Match_InvalidZPR32UXTW8:
4397 case Match_InvalidZPR32SXTW8:
4398 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4399 case Match_InvalidZPR32UXTW16:
4400 case Match_InvalidZPR32SXTW16:
4401 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4402 case Match_InvalidZPR32UXTW32:
4403 case Match_InvalidZPR32SXTW32:
4404 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4405 case Match_InvalidZPR32UXTW64:
4406 case Match_InvalidZPR32SXTW64:
4407 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4408 case Match_InvalidZPR64UXTW8:
4409 case Match_InvalidZPR64SXTW8:
4410 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4411 case Match_InvalidZPR64UXTW16:
4412 case Match_InvalidZPR64SXTW16:
4413 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4414 case Match_InvalidZPR64UXTW32:
4415 case Match_InvalidZPR64SXTW32:
4416 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4417 case Match_InvalidZPR64UXTW64:
4418 case Match_InvalidZPR64SXTW64:
4419 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
Sander de Smalenc69944c2018-07-09 09:58:24 +00004420 case Match_InvalidZPR32LSL8:
4421 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s'");
4422 case Match_InvalidZPR32LSL16:
4423 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #1'");
4424 case Match_InvalidZPR32LSL32:
4425 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #2'");
4426 case Match_InvalidZPR32LSL64:
4427 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004428 case Match_InvalidZPR64LSL8:
4429 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4430 case Match_InvalidZPR64LSL16:
4431 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4432 case Match_InvalidZPR64LSL32:
4433 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4434 case Match_InvalidZPR64LSL64:
4435 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00004436 case Match_InvalidZPR0:
Sander de Smalene1eab422019-03-27 17:23:38 +00004437 return Error(Loc, "expected register without element width suffix");
Sander de Smalen22176a22018-05-16 15:45:17 +00004438 case Match_InvalidZPR8:
4439 case Match_InvalidZPR16:
4440 case Match_InvalidZPR32:
4441 case Match_InvalidZPR64:
4442 case Match_InvalidZPR128:
4443 return Error(Loc, "invalid element width");
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004444 case Match_InvalidZPR_3b8:
4445 return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b");
4446 case Match_InvalidZPR_3b16:
4447 return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h");
4448 case Match_InvalidZPR_3b32:
4449 return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s");
4450 case Match_InvalidZPR_4b16:
4451 return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h");
4452 case Match_InvalidZPR_4b32:
4453 return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s");
4454 case Match_InvalidZPR_4b64:
4455 return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004456 case Match_InvalidSVEPattern:
4457 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004458 case Match_InvalidSVEPredicateAnyReg:
4459 case Match_InvalidSVEPredicateBReg:
4460 case Match_InvalidSVEPredicateHReg:
4461 case Match_InvalidSVEPredicateSReg:
4462 case Match_InvalidSVEPredicateDReg:
4463 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004464 case Match_InvalidSVEPredicate3bAnyReg:
4465 case Match_InvalidSVEPredicate3bBReg:
4466 case Match_InvalidSVEPredicate3bHReg:
4467 case Match_InvalidSVEPredicate3bSReg:
4468 case Match_InvalidSVEPredicate3bDReg:
4469 return Error(Loc, "restricted predicate has range [0, 7].");
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004470 case Match_InvalidSVEExactFPImmOperandHalfOne:
4471 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4472 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4473 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4474 case Match_InvalidSVEExactFPImmOperandZeroOne:
4475 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004476 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004477 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004478 }
4479}
4480
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004481static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004482
4483bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4484 OperandVector &Operands,
4485 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004486 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004487 bool MatchingInlineAsm) {
4488 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004489 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4490 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004491
David Blaikie960ea3f2014-06-08 16:18:35 +00004492 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004493 unsigned NumOperands = Operands.size();
4494
4495 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004496 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4497 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004498 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004499 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004500 if (Op3CE) {
4501 uint64_t Op3Val = Op3CE->getValue();
4502 uint64_t NewOp3Val = 0;
4503 uint64_t NewOp4Val = 0;
4504 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004505 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004506 NewOp3Val = (32 - Op3Val) & 0x1f;
4507 NewOp4Val = 31 - Op3Val;
4508 } else {
4509 NewOp3Val = (64 - Op3Val) & 0x3f;
4510 NewOp4Val = 63 - Op3Val;
4511 }
4512
Jim Grosbach13760bd2015-05-30 01:25:56 +00004513 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4514 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004515
4516 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004517 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004518 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004519 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4520 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4521 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004522 }
4523 }
Tim Northover03b99f62015-04-30 18:28:58 +00004524 } else if (NumOperands == 4 && Tok == "bfc") {
4525 // FIXME: Horrible hack to handle BFC->BFM alias.
4526 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4527 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4528 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4529
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004530 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004531 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4532 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4533
4534 if (LSBCE && WidthCE) {
4535 uint64_t LSB = LSBCE->getValue();
4536 uint64_t Width = WidthCE->getValue();
4537
4538 uint64_t RegWidth = 0;
4539 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4540 Op1.getReg()))
4541 RegWidth = 64;
4542 else
4543 RegWidth = 32;
4544
4545 if (LSB >= RegWidth)
4546 return Error(LSBOp.getStartLoc(),
4547 "expected integer in range [0, 31]");
4548 if (Width < 1 || Width > RegWidth)
4549 return Error(WidthOp.getStartLoc(),
4550 "expected integer in range [1, 32]");
4551
4552 uint64_t ImmR = 0;
4553 if (RegWidth == 32)
4554 ImmR = (32 - LSB) & 0x1f;
4555 else
4556 ImmR = (64 - LSB) & 0x3f;
4557
4558 uint64_t ImmS = Width - 1;
4559
4560 if (ImmR != 0 && ImmS >= ImmR)
4561 return Error(WidthOp.getStartLoc(),
4562 "requested insert overflows register");
4563
Jim Grosbach13760bd2015-05-30 01:25:56 +00004564 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4565 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004566 Operands[0] = AArch64Operand::CreateToken(
4567 "bfm", false, Op.getStartLoc(), getContext());
4568 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004569 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4570 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004571 Operands[3] = AArch64Operand::CreateImm(
4572 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4573 Operands.emplace_back(
4574 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4575 WidthOp.getEndLoc(), getContext()));
4576 }
4577 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004578 } else if (NumOperands == 5) {
4579 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4580 // UBFIZ -> UBFM aliases.
4581 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004582 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4583 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4584 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004585
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004586 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004587 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4588 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004589
4590 if (Op3CE && Op4CE) {
4591 uint64_t Op3Val = Op3CE->getValue();
4592 uint64_t Op4Val = Op4CE->getValue();
4593
4594 uint64_t RegWidth = 0;
4595 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004596 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004597 RegWidth = 64;
4598 else
4599 RegWidth = 32;
4600
4601 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004602 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004603 "expected integer in range [0, 31]");
4604 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004605 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004606 "expected integer in range [1, 32]");
4607
4608 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004609 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004610 NewOp3Val = (32 - Op3Val) & 0x1f;
4611 else
4612 NewOp3Val = (64 - Op3Val) & 0x3f;
4613
4614 uint64_t NewOp4Val = Op4Val - 1;
4615
4616 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004617 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004618 "requested insert overflows register");
4619
4620 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004621 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004622 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004623 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004624 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004625 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004626 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004627 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004628 if (Tok == "bfi")
4629 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004630 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004631 else if (Tok == "sbfiz")
4632 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004633 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004634 else if (Tok == "ubfiz")
4635 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004636 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004637 else
4638 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004639 }
4640 }
4641
4642 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4643 // UBFX -> UBFM aliases.
4644 } else if (NumOperands == 5 &&
4645 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004646 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4647 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4648 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004649
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004650 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004651 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4652 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004653
4654 if (Op3CE && Op4CE) {
4655 uint64_t Op3Val = Op3CE->getValue();
4656 uint64_t Op4Val = Op4CE->getValue();
4657
4658 uint64_t RegWidth = 0;
4659 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004660 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004661 RegWidth = 64;
4662 else
4663 RegWidth = 32;
4664
4665 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004666 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004667 "expected integer in range [0, 31]");
4668 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004669 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004670 "expected integer in range [1, 32]");
4671
4672 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4673
4674 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004675 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004676 "requested extract overflows register");
4677
4678 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004679 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004680 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004681 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004682 if (Tok == "bfxil")
4683 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004684 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004685 else if (Tok == "sbfx")
4686 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004687 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004688 else if (Tok == "ubfx")
4689 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004690 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004691 else
4692 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004693 }
4694 }
4695 }
4696 }
Tim Northover9097a072017-12-18 10:36:00 +00004697
4698 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4699 // instruction for FP registers correctly in some rare circumstances. Convert
4700 // it to a safe instruction and warn (because silently changing someone's
4701 // assembly is rude).
4702 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4703 NumOperands == 4 && Tok == "movi") {
4704 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4705 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4706 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4707 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4708 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4709 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4710 if (Suffix.lower() == ".2d" &&
4711 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4712 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4713 " correctly on this CPU, converting to equivalent movi.16b");
4714 // Switch the suffix to .16b.
4715 unsigned Idx = Op1.isToken() ? 1 : 2;
4716 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4717 getContext());
4718 }
4719 }
4720 }
4721
Tim Northover3b0846e2014-05-24 12:50:23 +00004722 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4723 // InstAlias can't quite handle this since the reg classes aren't
4724 // subclasses.
4725 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4726 // The source register can be Wn here, but the matcher expects a
4727 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004728 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004729 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004730 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004731 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4732 Op.getStartLoc(), Op.getEndLoc(),
4733 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004734 }
4735 }
4736 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4737 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004738 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004739 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004740 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004741 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004742 // The source register can be Wn here, but the matcher expects a
4743 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004744 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004745 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004746 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004747 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4748 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004749 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004750 }
4751 }
4752 }
4753 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4754 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004755 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004756 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004757 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004758 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004759 // The source register can be Wn here, but the matcher expects a
4760 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004761 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004762 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004763 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004764 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4765 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004766 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004767 }
4768 }
4769 }
4770
Tim Northover3b0846e2014-05-24 12:50:23 +00004771 MCInst Inst;
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004772 FeatureBitset MissingFeatures;
Tim Northover3b0846e2014-05-24 12:50:23 +00004773 // First try to match against the secondary set of tables containing the
4774 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4775 unsigned MatchResult =
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004776 MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
4777 MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004778
4779 // If that fails, try against the alternate table containing long-form NEON:
4780 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004781 if (MatchResult != Match_Success) {
4782 // But first, save the short-form match result: we can use it in case the
4783 // long-form match also fails.
4784 auto ShortFormNEONErrorInfo = ErrorInfo;
4785 auto ShortFormNEONMatchResult = MatchResult;
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004786 auto ShortFormNEONMissingFeatures = MissingFeatures;
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004787
Tim Northover3b0846e2014-05-24 12:50:23 +00004788 MatchResult =
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004789 MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
4790 MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004791
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004792 // Now, both matches failed, and the long-form match failed on the mnemonic
4793 // suffix token operand. The short-form match failure is probably more
4794 // relevant: use it instead.
4795 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004796 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004797 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4798 MatchResult = ShortFormNEONMatchResult;
4799 ErrorInfo = ShortFormNEONErrorInfo;
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004800 MissingFeatures = ShortFormNEONMissingFeatures;
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004801 }
4802 }
4803
Tim Northover3b0846e2014-05-24 12:50:23 +00004804 switch (MatchResult) {
4805 case Match_Success: {
4806 // Perform range checking and other semantic validations
4807 SmallVector<SMLoc, 8> OperandLocs;
4808 NumOperands = Operands.size();
4809 for (unsigned i = 1; i < NumOperands; ++i)
4810 OperandLocs.push_back(Operands[i]->getStartLoc());
Sander de Smalen9b333092018-07-30 15:42:46 +00004811 if (validateInstruction(Inst, IDLoc, OperandLocs))
Tim Northover3b0846e2014-05-24 12:50:23 +00004812 return true;
4813
4814 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004815 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004816 return false;
4817 }
4818 case Match_MissingFeature: {
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004819 assert(MissingFeatures.any() && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004820 // Special case the error message for the very common case where only
4821 // a single subtarget feature is missing (neon, e.g.).
4822 std::string Msg = "instruction requires:";
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004823 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
4824 if (MissingFeatures[i]) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004825 Msg += " ";
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00004826 Msg += getSubtargetFeatureName(i);
Tim Northover3b0846e2014-05-24 12:50:23 +00004827 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004828 }
4829 return Error(IDLoc, Msg);
4830 }
4831 case Match_MnemonicFail:
Sander de Smalen0325e302018-07-02 07:34:52 +00004832 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004833 case Match_InvalidOperand: {
4834 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004835
Tim Northover26bb14e2014-08-18 11:49:42 +00004836 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004837 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004838 return Error(IDLoc, "too few operands for instruction",
4839 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004840
David Blaikie960ea3f2014-06-08 16:18:35 +00004841 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004842 if (ErrorLoc == SMLoc())
4843 ErrorLoc = IDLoc;
4844 }
4845 // If the match failed on a suffix token operand, tweak the diagnostic
4846 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004847 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4848 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004849 MatchResult = Match_InvalidSuffix;
4850
Sander de Smalen0325e302018-07-02 07:34:52 +00004851 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004852 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004853 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004854 case Match_InvalidMemoryIndexed1:
4855 case Match_InvalidMemoryIndexed2:
4856 case Match_InvalidMemoryIndexed4:
4857 case Match_InvalidMemoryIndexed8:
4858 case Match_InvalidMemoryIndexed16:
4859 case Match_InvalidCondCode:
4860 case Match_AddSubRegExtendSmall:
4861 case Match_AddSubRegExtendLarge:
4862 case Match_AddSubSecondSource:
4863 case Match_LogicalSecondSource:
4864 case Match_AddSubRegShift32:
4865 case Match_AddSubRegShift64:
4866 case Match_InvalidMovImm32Shift:
4867 case Match_InvalidMovImm64Shift:
4868 case Match_InvalidFPImm:
4869 case Match_InvalidMemoryWExtend8:
4870 case Match_InvalidMemoryWExtend16:
4871 case Match_InvalidMemoryWExtend32:
4872 case Match_InvalidMemoryWExtend64:
4873 case Match_InvalidMemoryWExtend128:
4874 case Match_InvalidMemoryXExtend8:
4875 case Match_InvalidMemoryXExtend16:
4876 case Match_InvalidMemoryXExtend32:
4877 case Match_InvalidMemoryXExtend64:
4878 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004879 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004880 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004881 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004882 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004883 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004884 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004885 case Match_InvalidMemoryIndexed4SImm7:
4886 case Match_InvalidMemoryIndexed8SImm7:
4887 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004888 case Match_InvalidMemoryIndexed8UImm5:
4889 case Match_InvalidMemoryIndexed4UImm5:
4890 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004891 case Match_InvalidMemoryIndexed1UImm6:
4892 case Match_InvalidMemoryIndexed2UImm6:
4893 case Match_InvalidMemoryIndexed4UImm6:
4894 case Match_InvalidMemoryIndexed8UImm6:
Oliver Stannardc4190282018-10-02 10:04:39 +00004895 case Match_InvalidMemoryIndexed16UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004896 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004897 case Match_InvalidMemoryIndexedSImm5:
Sander de Smalen592718f2018-07-05 07:54:10 +00004898 case Match_InvalidMemoryIndexedSImm8:
Tim Northover3b0846e2014-05-24 12:50:23 +00004899 case Match_InvalidMemoryIndexedSImm9:
Oliver Stannardc4190282018-10-02 10:04:39 +00004900 case Match_InvalidMemoryIndexed16SImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004901 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004902 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004903 case Match_InvalidImm0_7:
4904 case Match_InvalidImm0_15:
4905 case Match_InvalidImm0_31:
4906 case Match_InvalidImm0_63:
4907 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004908 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004909 case Match_InvalidImm0_65535:
4910 case Match_InvalidImm1_8:
4911 case Match_InvalidImm1_16:
4912 case Match_InvalidImm1_32:
4913 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004914 case Match_InvalidSVEAddSubImm8:
4915 case Match_InvalidSVEAddSubImm16:
4916 case Match_InvalidSVEAddSubImm32:
4917 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004918 case Match_InvalidSVECpyImm8:
4919 case Match_InvalidSVECpyImm16:
4920 case Match_InvalidSVECpyImm32:
4921 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004922 case Match_InvalidIndexRange1_1:
4923 case Match_InvalidIndexRange0_15:
4924 case Match_InvalidIndexRange0_7:
4925 case Match_InvalidIndexRange0_3:
4926 case Match_InvalidIndexRange0_1:
4927 case Match_InvalidSVEIndexRange0_63:
4928 case Match_InvalidSVEIndexRange0_31:
4929 case Match_InvalidSVEIndexRange0_15:
4930 case Match_InvalidSVEIndexRange0_7:
4931 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004932 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004933 case Match_InvalidComplexRotationEven:
4934 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004935 case Match_InvalidGPR64shifted8:
4936 case Match_InvalidGPR64shifted16:
4937 case Match_InvalidGPR64shifted32:
4938 case Match_InvalidGPR64shifted64:
4939 case Match_InvalidGPR64NoXZRshifted8:
4940 case Match_InvalidGPR64NoXZRshifted16:
4941 case Match_InvalidGPR64NoXZRshifted32:
4942 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004943 case Match_InvalidZPR32UXTW8:
4944 case Match_InvalidZPR32UXTW16:
4945 case Match_InvalidZPR32UXTW32:
4946 case Match_InvalidZPR32UXTW64:
4947 case Match_InvalidZPR32SXTW8:
4948 case Match_InvalidZPR32SXTW16:
4949 case Match_InvalidZPR32SXTW32:
4950 case Match_InvalidZPR32SXTW64:
4951 case Match_InvalidZPR64UXTW8:
4952 case Match_InvalidZPR64SXTW8:
4953 case Match_InvalidZPR64UXTW16:
4954 case Match_InvalidZPR64SXTW16:
4955 case Match_InvalidZPR64UXTW32:
4956 case Match_InvalidZPR64SXTW32:
4957 case Match_InvalidZPR64UXTW64:
4958 case Match_InvalidZPR64SXTW64:
Sander de Smalenc69944c2018-07-09 09:58:24 +00004959 case Match_InvalidZPR32LSL8:
4960 case Match_InvalidZPR32LSL16:
4961 case Match_InvalidZPR32LSL32:
4962 case Match_InvalidZPR32LSL64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004963 case Match_InvalidZPR64LSL8:
4964 case Match_InvalidZPR64LSL16:
4965 case Match_InvalidZPR64LSL32:
4966 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004967 case Match_InvalidZPR0:
4968 case Match_InvalidZPR8:
4969 case Match_InvalidZPR16:
4970 case Match_InvalidZPR32:
4971 case Match_InvalidZPR64:
4972 case Match_InvalidZPR128:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004973 case Match_InvalidZPR_3b8:
4974 case Match_InvalidZPR_3b16:
4975 case Match_InvalidZPR_3b32:
4976 case Match_InvalidZPR_4b16:
4977 case Match_InvalidZPR_4b32:
4978 case Match_InvalidZPR_4b64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004979 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004980 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004981 case Match_InvalidSVEPredicateBReg:
4982 case Match_InvalidSVEPredicateHReg:
4983 case Match_InvalidSVEPredicateSReg:
4984 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004985 case Match_InvalidSVEPredicate3bAnyReg:
4986 case Match_InvalidSVEPredicate3bBReg:
4987 case Match_InvalidSVEPredicate3bHReg:
4988 case Match_InvalidSVEPredicate3bSReg:
4989 case Match_InvalidSVEPredicate3bDReg:
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004990 case Match_InvalidSVEExactFPImmOperandHalfOne:
4991 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4992 case Match_InvalidSVEExactFPImmOperandZeroOne:
Tim Northover3b0846e2014-05-24 12:50:23 +00004993 case Match_MSR:
4994 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004995 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004996 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004997 // Any time we get here, there's nothing fancy to do. Just get the
4998 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004999 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00005000 if (ErrorLoc == SMLoc())
5001 ErrorLoc = IDLoc;
Sander de Smalen0325e302018-07-02 07:34:52 +00005002 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00005003 }
5004 }
5005
5006 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00005007}
5008
5009/// ParseDirective parses the arm specific directives
5010bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00005011 const MCObjectFileInfo::Environment Format =
5012 getContext().getObjectFileInfo()->getObjectFileType();
5013 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005014
Tim Northover3b0846e2014-05-24 12:50:23 +00005015 StringRef IDVal = DirectiveID.getIdentifier();
5016 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005017 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00005018 parseDirectiveArch(Loc);
5019 else if (IDVal == ".cpu")
5020 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00005021 else if (IDVal == ".tlsdesccall")
5022 parseDirectiveTLSDescCall(Loc);
5023 else if (IDVal == ".ltorg" || IDVal == ".pool")
5024 parseDirectiveLtorg(Loc);
5025 else if (IDVal == ".unreq")
5026 parseDirectiveUnreq(Loc);
Martin Storsjo3e3d39d2018-07-31 09:26:52 +00005027 else if (IDVal == ".inst")
5028 parseDirectiveInst(Loc);
Luke Cheesemanf57d7d82018-12-18 10:37:42 +00005029 else if (IDVal == ".cfi_negate_ra_state")
5030 parseDirectiveCFINegateRAState();
Luke Cheeseman41a9e532018-12-21 10:45:08 +00005031 else if (IDVal == ".cfi_b_key_frame")
5032 parseDirectiveCFIBKeyFrame();
Martin Storsjo20187772018-12-30 21:06:32 +00005033 else if (IDVal == ".arch_extension")
5034 parseDirectiveArchExtension(Loc);
Martin Storsjod4590c32018-08-01 06:50:18 +00005035 else if (IsMachO) {
5036 if (IDVal == MCLOHDirectiveName())
5037 parseDirectiveLOH(IDVal, Loc);
5038 else
5039 return true;
5040 } else
Nirav Davee833c6c2016-11-08 18:31:04 +00005041 return true;
5042 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00005043}
5044
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005045static void ExpandCryptoAEK(AArch64::ArchKind ArchKind,
5046 SmallVector<StringRef, 4> &RequestedExtensions) {
5047 const bool NoCrypto =
5048 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
5049 "nocrypto") != std::end(RequestedExtensions));
5050 const bool Crypto =
5051 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
5052 "crypto") != std::end(RequestedExtensions));
5053
5054 if (!NoCrypto && Crypto) {
5055 switch (ArchKind) {
5056 default:
5057 // Map 'generic' (and others) to sha2 and aes, because
5058 // that was the traditional meaning of crypto.
5059 case AArch64::ArchKind::ARMV8_1A:
5060 case AArch64::ArchKind::ARMV8_2A:
5061 case AArch64::ArchKind::ARMV8_3A:
5062 RequestedExtensions.push_back("sha2");
5063 RequestedExtensions.push_back("aes");
5064 break;
5065 case AArch64::ArchKind::ARMV8_4A:
Oliver Stannard7c3c4ba2018-09-26 12:48:21 +00005066 case AArch64::ArchKind::ARMV8_5A:
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005067 RequestedExtensions.push_back("sm4");
5068 RequestedExtensions.push_back("sha3");
5069 RequestedExtensions.push_back("sha2");
5070 RequestedExtensions.push_back("aes");
5071 break;
5072 }
5073 } else if (NoCrypto) {
5074 switch (ArchKind) {
5075 default:
5076 // Map 'generic' (and others) to sha2 and aes, because
5077 // that was the traditional meaning of crypto.
5078 case AArch64::ArchKind::ARMV8_1A:
5079 case AArch64::ArchKind::ARMV8_2A:
5080 case AArch64::ArchKind::ARMV8_3A:
5081 RequestedExtensions.push_back("nosha2");
5082 RequestedExtensions.push_back("noaes");
5083 break;
5084 case AArch64::ArchKind::ARMV8_4A:
Oliver Stannard7c3c4ba2018-09-26 12:48:21 +00005085 case AArch64::ArchKind::ARMV8_5A:
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005086 RequestedExtensions.push_back("nosm4");
5087 RequestedExtensions.push_back("nosha3");
5088 RequestedExtensions.push_back("nosha2");
5089 RequestedExtensions.push_back("noaes");
5090 break;
5091 }
5092 }
5093}
5094
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005095/// parseDirectiveArch
5096/// ::= .arch token
5097bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
5098 SMLoc ArchLoc = getLoc();
5099
5100 StringRef Arch, ExtensionString;
5101 std::tie(Arch, ExtensionString) =
5102 getParser().parseStringToEndOfStatement().trim().split('+');
5103
Florian Hahn67ddd1d2017-07-27 16:27:56 +00005104 AArch64::ArchKind ID = AArch64::parseArch(Arch);
5105 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00005106 return Error(ArchLoc, "unknown arch name");
5107
5108 if (parseToken(AsmToken::EndOfStatement))
5109 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005110
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005111 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00005112 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005113 AArch64::getArchFeatures(ID, AArch64Features);
5114 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
5115 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005116
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005117 MCSubtargetInfo &STI = copySTI();
5118 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
5119 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
5120
5121 SmallVector<StringRef, 4> RequestedExtensions;
5122 if (!ExtensionString.empty())
5123 ExtensionString.split(RequestedExtensions, '+');
5124
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005125 ExpandCryptoAEK(ID, RequestedExtensions);
5126
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005127 FeatureBitset Features = STI.getFeatureBits();
5128 for (auto Name : RequestedExtensions) {
5129 bool EnableFeature = true;
5130
5131 if (Name.startswith_lower("no")) {
5132 EnableFeature = false;
5133 Name = Name.substr(2);
5134 }
5135
5136 for (const auto &Extension : ExtensionMap) {
5137 if (Extension.Name != Name)
5138 continue;
5139
5140 if (Extension.Features.none())
5141 report_fatal_error("unsupported architectural extension: " + Name);
5142
5143 FeatureBitset ToggleFeatures = EnableFeature
5144 ? (~Features & Extension.Features)
5145 : ( Features & Extension.Features);
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00005146 FeatureBitset Features =
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005147 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5148 setAvailableFeatures(Features);
5149 break;
5150 }
5151 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005152 return false;
5153}
5154
Martin Storsjo20187772018-12-30 21:06:32 +00005155/// parseDirectiveArchExtension
5156/// ::= .arch_extension [no]feature
5157bool AArch64AsmParser::parseDirectiveArchExtension(SMLoc L) {
Sander de Smalen772e4732019-04-04 09:11:17 +00005158 SMLoc ExtLoc = getLoc();
Martin Storsjo20187772018-12-30 21:06:32 +00005159
Sander de Smalen772e4732019-04-04 09:11:17 +00005160 StringRef Name = getParser().parseStringToEndOfStatement().trim();
Martin Storsjo20187772018-12-30 21:06:32 +00005161
5162 if (parseToken(AsmToken::EndOfStatement,
5163 "unexpected token in '.arch_extension' directive"))
5164 return true;
5165
5166 bool EnableFeature = true;
5167 if (Name.startswith_lower("no")) {
5168 EnableFeature = false;
5169 Name = Name.substr(2);
5170 }
5171
5172 MCSubtargetInfo &STI = copySTI();
5173 FeatureBitset Features = STI.getFeatureBits();
5174 for (const auto &Extension : ExtensionMap) {
5175 if (Extension.Name != Name)
5176 continue;
5177
5178 if (Extension.Features.none())
5179 return Error(ExtLoc, "unsupported architectural extension: " + Name);
5180
5181 FeatureBitset ToggleFeatures = EnableFeature
5182 ? (~Features & Extension.Features)
5183 : (Features & Extension.Features);
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00005184 FeatureBitset Features =
Martin Storsjo20187772018-12-30 21:06:32 +00005185 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5186 setAvailableFeatures(Features);
5187 return false;
5188 }
5189
5190 return Error(ExtLoc, "unknown architectural extension: " + Name);
5191}
5192
Tim Northover8b96c7e2017-05-15 19:42:15 +00005193static SMLoc incrementLoc(SMLoc L, int Offset) {
5194 return SMLoc::getFromPointer(L.getPointer() + Offset);
5195}
5196
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005197/// parseDirectiveCPU
5198/// ::= .cpu id
5199bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005200 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005201
5202 StringRef CPU, ExtensionString;
5203 std::tie(CPU, ExtensionString) =
5204 getParser().parseStringToEndOfStatement().trim().split('+');
5205
Nirav Davee833c6c2016-11-08 18:31:04 +00005206 if (parseToken(AsmToken::EndOfStatement))
5207 return true;
5208
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005209 SmallVector<StringRef, 4> RequestedExtensions;
5210 if (!ExtensionString.empty())
5211 ExtensionString.split(RequestedExtensions, '+');
5212
5213 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
5214 // once that is tablegen'ed
5215 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005216 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005217 return false;
5218 }
5219
5220 MCSubtargetInfo &STI = copySTI();
5221 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00005222 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005223
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005224 ExpandCryptoAEK(llvm::AArch64::getCPUArchKind(CPU), RequestedExtensions);
5225
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005226 FeatureBitset Features = STI.getFeatureBits();
5227 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005228 // Advance source location past '+'.
5229 CurLoc = incrementLoc(CurLoc, 1);
5230
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005231 bool EnableFeature = true;
5232
5233 if (Name.startswith_lower("no")) {
5234 EnableFeature = false;
5235 Name = Name.substr(2);
5236 }
5237
Tim Northover8b96c7e2017-05-15 19:42:15 +00005238 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005239 for (const auto &Extension : ExtensionMap) {
5240 if (Extension.Name != Name)
5241 continue;
5242
5243 if (Extension.Features.none())
5244 report_fatal_error("unsupported architectural extension: " + Name);
5245
5246 FeatureBitset ToggleFeatures = EnableFeature
5247 ? (~Features & Extension.Features)
5248 : ( Features & Extension.Features);
Stanislav Mekhanoshine98944e2019-03-11 17:04:35 +00005249 FeatureBitset Features =
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005250 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5251 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00005252 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005253
5254 break;
5255 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00005256
5257 if (!FoundExtension)
5258 Error(CurLoc, "unsupported architectural extension");
5259
5260 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005261 }
5262 return false;
5263}
5264
Chad Rosierdcd2a302014-10-22 20:35:57 +00005265/// parseDirectiveInst
5266/// ::= .inst opcode [, ...]
5267bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005268 if (getLexer().is(AsmToken::EndOfStatement))
5269 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005270
Nirav Davee833c6c2016-11-08 18:31:04 +00005271 auto parseOp = [&]() -> bool {
5272 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00005273 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00005274 if (check(getParser().parseExpression(Expr), L, "expected expression"))
5275 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005276 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00005277 if (check(!Value, L, "expected constant expression"))
5278 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005279 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00005280 return false;
5281 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00005282
Nirav Davee833c6c2016-11-08 18:31:04 +00005283 if (parseMany(parseOp))
5284 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005285 return false;
5286}
5287
Tim Northover3b0846e2014-05-24 12:50:23 +00005288// parseDirectiveTLSDescCall:
5289// ::= .tlsdesccall symbol
5290bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
5291 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00005292 if (check(getParser().parseIdentifier(Name), L,
5293 "expected symbol after directive") ||
5294 parseToken(AsmToken::EndOfStatement))
5295 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005296
Jim Grosbach6f482002015-05-18 18:43:14 +00005297 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00005298 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
5299 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00005300
5301 MCInst Inst;
5302 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00005303 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00005304
Akira Hatanakabd9fc282015-11-14 05:20:05 +00005305 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00005306 return false;
5307}
5308
5309/// ::= .loh <lohName | lohId> label1, ..., labelN
5310/// The number of arguments depends on the loh identifier.
5311bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00005312 MCLOHType Kind;
5313 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5314 if (getParser().getTok().isNot(AsmToken::Integer))
5315 return TokError("expected an identifier or a number in directive");
5316 // We successfully get a numeric value for the identifier.
5317 // Check if it is valid.
5318 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00005319 if (Id <= -1U && !isValidMCLOHType(Id))
5320 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00005321 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00005322 } else {
5323 StringRef Name = getTok().getIdentifier();
5324 // We successfully parse an identifier.
5325 // Check if it is a recognized one.
5326 int Id = MCLOHNameToId(Name);
5327
5328 if (Id == -1)
5329 return TokError("invalid identifier in directive");
5330 Kind = (MCLOHType)Id;
5331 }
5332 // Consume the identifier.
5333 Lex();
5334 // Get the number of arguments of this LOH.
5335 int NbArgs = MCLOHIdToNbArgs(Kind);
5336
5337 assert(NbArgs != -1 && "Invalid number of arguments");
5338
5339 SmallVector<MCSymbol *, 3> Args;
5340 for (int Idx = 0; Idx < NbArgs; ++Idx) {
5341 StringRef Name;
5342 if (getParser().parseIdentifier(Name))
5343 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00005344 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00005345
5346 if (Idx + 1 == NbArgs)
5347 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00005348 if (parseToken(AsmToken::Comma,
5349 "unexpected token in '" + Twine(IDVal) + "' directive"))
5350 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005351 }
Nirav Davee833c6c2016-11-08 18:31:04 +00005352 if (parseToken(AsmToken::EndOfStatement,
5353 "unexpected token in '" + Twine(IDVal) + "' directive"))
5354 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005355
5356 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
5357 return false;
5358}
5359
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005360/// parseDirectiveLtorg
5361/// ::= .ltorg | .pool
5362bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005363 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5364 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005365 getTargetStreamer().emitCurrentConstantPool();
5366 return false;
5367}
5368
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005369/// parseDirectiveReq
5370/// ::= name .req registername
5371bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005372 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005373 Parser.Lex(); // Eat the '.req' token.
5374 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00005375 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00005376 unsigned RegNum;
5377 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005378
Sander de Smalen50d87022018-04-19 07:35:08 +00005379 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005380 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00005381 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005382 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00005383
Sander de Smalen50d87022018-04-19 07:35:08 +00005384 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00005385 return true;
5386
Sander de Smalen50d87022018-04-19 07:35:08 +00005387 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00005388 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005389 }
5390
Sander de Smalen50d87022018-04-19 07:35:08 +00005391 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005392 StringRef Kind;
5393 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005394 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00005395 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005396
Sander de Smalen50d87022018-04-19 07:35:08 +00005397 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00005398 return true;
5399
Sander de Smalen50d87022018-04-19 07:35:08 +00005400 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00005401 return Error(SRegLoc,
5402 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00005403 }
5404
Sander de Smalen50d87022018-04-19 07:35:08 +00005405 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00005406 StringRef Kind;
5407 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005408 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00005409
Sander de Smalen50d87022018-04-19 07:35:08 +00005410 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00005411 return true;
5412
Sander de Smalen50d87022018-04-19 07:35:08 +00005413 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00005414 return Error(SRegLoc,
5415 "sve predicate register without type specifier expected");
5416 }
5417
Sander de Smalen50d87022018-04-19 07:35:08 +00005418 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00005419 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005420
5421 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00005422 if (parseToken(AsmToken::EndOfStatement,
5423 "unexpected input in .req directive"))
5424 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005425
Sander de Smalen8e607342017-11-15 15:44:43 +00005426 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00005427 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005428 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
5429
Nirav Dave2364748a2016-09-16 18:30:20 +00005430 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005431}
5432
5433/// parseDirectiveUneq
5434/// ::= .unreq registername
5435bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005436 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00005437 if (getTok().isNot(AsmToken::Identifier))
5438 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005439 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
5440 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00005441 if (parseToken(AsmToken::EndOfStatement))
5442 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005443 return false;
5444}
5445
Luke Cheesemanf57d7d82018-12-18 10:37:42 +00005446bool AArch64AsmParser::parseDirectiveCFINegateRAState() {
5447 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5448 return true;
5449 getStreamer().EmitCFINegateRAState();
5450 return false;
5451}
5452
Luke Cheeseman41a9e532018-12-21 10:45:08 +00005453/// parseDirectiveCFIBKeyFrame
5454/// ::= .cfi_b_key
5455bool AArch64AsmParser::parseDirectiveCFIBKeyFrame() {
5456 if (parseToken(AsmToken::EndOfStatement,
5457 "unexpected token in '.cfi_b_key_frame'"))
5458 return true;
5459 getStreamer().EmitCFIBKeyFrame();
5460 return false;
5461}
5462
Tim Northover3b0846e2014-05-24 12:50:23 +00005463bool
5464AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
5465 AArch64MCExpr::VariantKind &ELFRefKind,
5466 MCSymbolRefExpr::VariantKind &DarwinRefKind,
5467 int64_t &Addend) {
5468 ELFRefKind = AArch64MCExpr::VK_INVALID;
5469 DarwinRefKind = MCSymbolRefExpr::VK_None;
5470 Addend = 0;
5471
5472 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5473 ELFRefKind = AE->getKind();
5474 Expr = AE->getSubExpr();
5475 }
5476
5477 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5478 if (SE) {
5479 // It's a simple symbol reference with no addend.
5480 DarwinRefKind = SE->getKind();
5481 return true;
5482 }
5483
David Green85d6a552018-09-18 09:44:53 +00005484 // Check that it looks like a symbol + an addend
5485 MCValue Res;
5486 bool Relocatable = Expr->evaluateAsRelocatable(Res, nullptr, nullptr);
Eli Friedman48397102018-12-20 19:46:14 +00005487 if (!Relocatable || Res.getSymB())
Tim Northover3b0846e2014-05-24 12:50:23 +00005488 return false;
5489
Eli Friedman48397102018-12-20 19:46:14 +00005490 // Treat expressions with an ELFRefKind (like ":abs_g1:3", or
5491 // ":abs_g1:x" where x is constant) as symbolic even if there is no symbol.
5492 if (!Res.getSymA() && ELFRefKind == AArch64MCExpr::VK_INVALID)
5493 return false;
5494
5495 if (Res.getSymA())
5496 DarwinRefKind = Res.getSymA()->getKind();
David Green85d6a552018-09-18 09:44:53 +00005497 Addend = Res.getConstant();
Tim Northover3b0846e2014-05-24 12:50:23 +00005498
5499 // It's some symbol reference + a constant addend, but really
5500 // shouldn't use both Darwin and ELF syntax.
5501 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5502 DarwinRefKind == MCSymbolRefExpr::VK_None;
5503}
5504
5505/// Force static initialization.
5506extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00005507 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5508 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5509 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00005510}
5511
5512#define GET_REGISTER_MATCHER
5513#define GET_SUBTARGET_FEATURE_NAME
5514#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00005515#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00005516#include "AArch64GenAsmMatcher.inc"
5517
5518// Define this matcher function after the auto-generated include so we
5519// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00005520unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00005521 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005522 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00005523 // If the kind is a token for a literal immediate, check if our asm
5524 // operand matches. This is for InstAliases which have a fixed-value
5525 // immediate in the syntax.
5526 int64_t ExpectedVal;
5527 switch (Kind) {
5528 default:
5529 return Match_InvalidOperand;
5530 case MCK__35_0:
5531 ExpectedVal = 0;
5532 break;
5533 case MCK__35_1:
5534 ExpectedVal = 1;
5535 break;
5536 case MCK__35_12:
5537 ExpectedVal = 12;
5538 break;
5539 case MCK__35_16:
5540 ExpectedVal = 16;
5541 break;
5542 case MCK__35_2:
5543 ExpectedVal = 2;
5544 break;
5545 case MCK__35_24:
5546 ExpectedVal = 24;
5547 break;
5548 case MCK__35_3:
5549 ExpectedVal = 3;
5550 break;
5551 case MCK__35_32:
5552 ExpectedVal = 32;
5553 break;
5554 case MCK__35_4:
5555 ExpectedVal = 4;
5556 break;
5557 case MCK__35_48:
5558 ExpectedVal = 48;
5559 break;
5560 case MCK__35_6:
5561 ExpectedVal = 6;
5562 break;
5563 case MCK__35_64:
5564 ExpectedVal = 64;
5565 break;
5566 case MCK__35_8:
5567 ExpectedVal = 8;
5568 break;
5569 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005570 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005571 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005572 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005573 if (!CE)
5574 return Match_InvalidOperand;
5575 if (CE->getValue() == ExpectedVal)
5576 return Match_Success;
5577 return Match_InvalidOperand;
5578}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005579
Alex Bradbury58eba092016-11-01 16:32:05 +00005580OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005581AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5582
5583 SMLoc S = getLoc();
5584
5585 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5586 Error(S, "expected register");
5587 return MatchOperand_ParseFail;
5588 }
5589
Sander de Smalen50d87022018-04-19 07:35:08 +00005590 unsigned FirstReg;
5591 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5592 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005593 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005594
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005595 const MCRegisterClass &WRegClass =
5596 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5597 const MCRegisterClass &XRegClass =
5598 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5599
5600 bool isXReg = XRegClass.contains(FirstReg),
5601 isWReg = WRegClass.contains(FirstReg);
5602 if (!isXReg && !isWReg) {
5603 Error(S, "expected first even register of a "
5604 "consecutive same-size even/odd register pair");
5605 return MatchOperand_ParseFail;
5606 }
5607
5608 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5609 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5610
5611 if (FirstEncoding & 0x1) {
5612 Error(S, "expected first even register of a "
5613 "consecutive same-size even/odd register pair");
5614 return MatchOperand_ParseFail;
5615 }
5616
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005617 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005618 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005619 return MatchOperand_ParseFail;
5620 }
5621 // Eat the comma
5622 getParser().Lex();
5623
5624 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005625 unsigned SecondReg;
5626 Res = tryParseScalarRegister(SecondReg);
5627 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005628 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005629
Eugene Zelenko049b0172017-01-06 00:30:53 +00005630 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005631 (isXReg && !XRegClass.contains(SecondReg)) ||
5632 (isWReg && !WRegClass.contains(SecondReg))) {
5633 Error(E,"expected second odd register of a "
5634 "consecutive same-size even/odd register pair");
5635 return MatchOperand_ParseFail;
5636 }
Joel Jones504bf332016-10-24 13:37:13 +00005637
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005638 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005639 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005640 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5641 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5642 } else {
5643 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5644 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5645 }
5646
Florian Hahnc4422242017-11-07 13:07:50 +00005647 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5648 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005649
5650 return MatchOperand_Success;
5651}
Florian Hahn91f11e52017-11-07 16:45:48 +00005652
Sander de Smaleneb896b12018-04-25 09:26:47 +00005653template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005654OperandMatchResultTy
5655AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005656 const SMLoc S = getLoc();
5657 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005658 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005659 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005660
Sander de Smalen8e607342017-11-15 15:44:43 +00005661 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005662 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005663
5664 if (Res != MatchOperand_Success)
5665 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005666
5667 if (ParseSuffix && Kind.empty())
5668 return MatchOperand_NoMatch;
5669
Sander de Smalen73937b72018-04-11 07:36:10 +00005670 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5671 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005672 return MatchOperand_NoMatch;
5673
Sander de Smalen73937b72018-04-11 07:36:10 +00005674 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005675
5676 // No shift/extend is the default.
5677 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5678 Operands.push_back(AArch64Operand::CreateVectorReg(
5679 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5680
Sander de Smalenc33d6682018-06-04 06:40:55 +00005681 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5682 if (Res == MatchOperand_ParseFail)
5683 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005684 return MatchOperand_Success;
5685 }
5686
5687 // Eat the comma
5688 getParser().Lex();
5689
5690 // Match the shift
5691 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5692 Res = tryParseOptionalShiftExtend(ExtOpnd);
5693 if (Res != MatchOperand_Success)
5694 return Res;
5695
5696 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005697 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005698 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5699 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5700 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005701
5702 return MatchOperand_Success;
5703}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005704
5705OperandMatchResultTy
5706AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5707 MCAsmParser &Parser = getParser();
5708
5709 SMLoc SS = getLoc();
5710 const AsmToken &TokE = Parser.getTok();
5711 bool IsHash = TokE.is(AsmToken::Hash);
5712
5713 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5714 return MatchOperand_NoMatch;
5715
5716 int64_t Pattern;
5717 if (IsHash) {
5718 Parser.Lex(); // Eat hash
5719
5720 // Parse the immediate operand.
5721 const MCExpr *ImmVal;
5722 SS = getLoc();
5723 if (Parser.parseExpression(ImmVal))
5724 return MatchOperand_ParseFail;
5725
5726 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5727 if (!MCE)
5728 return MatchOperand_ParseFail;
5729
5730 Pattern = MCE->getValue();
5731 } else {
5732 // Parse the pattern
5733 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5734 if (!Pat)
5735 return MatchOperand_NoMatch;
5736
5737 Parser.Lex();
5738 Pattern = Pat->Encoding;
5739 assert(Pattern >= 0 && Pattern < 32);
5740 }
5741
5742 Operands.push_back(
5743 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5744 SS, getLoc(), getContext()));
5745
5746 return MatchOperand_Success;
5747}