blob: eb1cc3a9479c888218a7cc24b22f59bf00b52d4f [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/AArch64AddressingModes.h"
11#include "MCTargetDesc/AArch64MCExpr.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000012#include "MCTargetDesc/AArch64MCTargetDesc.h"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000013#include "MCTargetDesc/AArch64TargetStreamer.h"
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"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000043#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000044#include "llvm/Support/MathExtras.h"
45#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000046#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000047#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000049#include <cassert>
50#include <cctype>
51#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000052#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000053#include <string>
54#include <tuple>
55#include <utility>
56#include <vector>
57
Tim Northover3b0846e2014-05-24 12:50:23 +000058using namespace llvm;
59
60namespace {
61
Sander de Smalencd6be962017-12-20 11:02:42 +000062enum class RegKind {
63 Scalar,
64 NeonVector,
65 SVEDataVector,
66 SVEPredicateVector
67};
Florian Hahnc4422242017-11-07 13:07:50 +000068
Tim Northover3b0846e2014-05-24 12:50:23 +000069class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000070private:
71 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000072
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000073 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000074 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000075
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000076 AArch64TargetStreamer &getTargetStreamer() {
77 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
78 return static_cast<AArch64TargetStreamer &>(TS);
79 }
80
Rafael Espindola961d4692014-11-11 05:18:41 +000081 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000082
83 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +000084 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +000085 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
86 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +000087 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +000088 bool parseRegister(OperandVector &Operands);
89 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
Sander de Smalenc88f9a12018-04-11 14:10:37 +000090 bool parseNeonVectorList(OperandVector &Operands);
Sander de Smalen5c625982018-04-13 12:56:14 +000091 bool parseOptionalMulVl(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000092 bool parseOperand(OperandVector &Operands, bool isCondCode,
93 bool invertCondCode);
94
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +000095 bool showMatchError(SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000096
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000097 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000098 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +000099 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +0000100 bool parseDirectiveInst(SMLoc L);
101
Tim Northover3b0846e2014-05-24 12:50:23 +0000102 bool parseDirectiveTLSDescCall(SMLoc L);
103
104 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000105 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000106
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000107 bool parseDirectiveReq(StringRef Name, SMLoc L);
108 bool parseDirectiveUnreq(SMLoc L);
109
Tim Northover3b0846e2014-05-24 12:50:23 +0000110 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
111 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
112 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000113 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000114 bool MatchingInlineAsm) override;
115/// @name Auto-generated Match Functions
116/// {
117
118#define GET_ASSEMBLER_HEADER
119#include "AArch64GenAsmMatcher.inc"
120
121 /// }
122
Sander de Smalen50d87022018-04-19 07:35:08 +0000123 OperandMatchResultTy tryParseScalarRegister(unsigned &Reg);
124 OperandMatchResultTy tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +0000125 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000126 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
127 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
128 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
129 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
130 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
Sander de Smalen93380372018-05-14 11:54:41 +0000131 template <bool IsSVEPrefetch = false>
Tim Northover3b0846e2014-05-24 12:50:23 +0000132 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000133 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000134 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
135 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
136 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
137 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
138 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000139 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000140 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000141 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Sander de Smalen149916d2018-04-20 07:24:20 +0000142 template <bool ParseShiftExtend>
143 OperandMatchResultTy tryParseGPROperand(OperandVector &Operands);
Sander de Smaleneb896b12018-04-25 09:26:47 +0000144 template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +0000145 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000146 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000147 template <RegKind VectorKind>
148 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
149 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000150 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000151
152public:
153 enum AArch64MatchResultTy {
154 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
155#define GET_OPERAND_DIAGNOSTIC_TYPES
156#include "AArch64GenAsmMatcher.inc"
157 };
Joel Jones504bf332016-10-24 13:37:13 +0000158 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000159
Akira Hatanakab11ef082015-11-14 06:35:56 +0000160 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000161 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000162 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000163 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000164 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000165 MCStreamer &S = getParser().getStreamer();
166 if (S.getTargetStreamer() == nullptr)
167 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000168
169 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000170 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000171 }
172
173 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
174 SMLoc NameLoc, OperandVector &Operands) override;
175 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
176 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000177 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000178 unsigned Kind) override;
179
180 static bool classifySymbolRef(const MCExpr *Expr,
181 AArch64MCExpr::VariantKind &ELFRefKind,
182 MCSymbolRefExpr::VariantKind &DarwinRefKind,
183 int64_t &Addend);
184};
Tim Northover3b0846e2014-05-24 12:50:23 +0000185
186/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
187/// instruction.
188class AArch64Operand : public MCParsedAsmOperand {
189private:
190 enum KindTy {
191 k_Immediate,
192 k_ShiftedImm,
193 k_CondCode,
194 k_Register,
195 k_VectorList,
196 k_VectorIndex,
197 k_Token,
198 k_SysReg,
199 k_SysCR,
200 k_Prefetch,
201 k_ShiftExtend,
202 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000203 k_Barrier,
204 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000205 } Kind;
206
207 SMLoc StartLoc, EndLoc;
208
209 struct TokOp {
210 const char *Data;
211 unsigned Length;
212 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
213 };
214
Sander de Smalen149916d2018-04-20 07:24:20 +0000215 // Separate shift/extend operand.
216 struct ShiftExtendOp {
217 AArch64_AM::ShiftExtendType Type;
218 unsigned Amount;
219 bool HasExplicitAmount;
220 };
221
Tim Northover3b0846e2014-05-24 12:50:23 +0000222 struct RegOp {
223 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000224 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000225 int ElementWidth;
Sander de Smalen149916d2018-04-20 07:24:20 +0000226
227 // In some cases the shift/extend needs to be explicitly parsed together
228 // with the register, rather than as a separate operand. This is needed
229 // for addressing modes where the instruction as a whole dictates the
230 // scaling/extend, rather than specific bits in the instruction.
231 // By parsing them as a single operand, we avoid the need to pass an
232 // extra operand in all CodeGen patterns (because all operands need to
233 // have an associated value), and we avoid the need to update TableGen to
234 // accept operands that have no associated bits in the instruction.
235 //
236 // An added benefit of parsing them together is that the assembler
237 // can give a sensible diagnostic if the scaling is not correct.
238 //
239 // The default is 'lsl #0' (HasExplicitAmount = false) if no
240 // ShiftExtend is specified.
241 ShiftExtendOp ShiftExtend;
Tim Northover3b0846e2014-05-24 12:50:23 +0000242 };
243
244 struct VectorListOp {
245 unsigned RegNum;
246 unsigned Count;
247 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000248 unsigned ElementWidth;
249 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000250 };
251
252 struct VectorIndexOp {
253 unsigned Val;
254 };
255
256 struct ImmOp {
257 const MCExpr *Val;
258 };
259
260 struct ShiftedImmOp {
261 const MCExpr *Val;
262 unsigned ShiftAmount;
263 };
264
265 struct CondCodeOp {
266 AArch64CC::CondCode Code;
267 };
268
269 struct FPImmOp {
270 unsigned Val; // Encoded 8-bit representation.
271 };
272
273 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000274 const char *Data;
275 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000276 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000277 };
278
279 struct SysRegOp {
280 const char *Data;
281 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000282 uint32_t MRSReg;
283 uint32_t MSRReg;
284 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000285 };
286
287 struct SysCRImmOp {
288 unsigned Val;
289 };
290
291 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000292 const char *Data;
293 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000294 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000295 };
296
Oliver Stannarda34e4702015-12-01 10:48:51 +0000297 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000298 const char *Data;
299 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000300 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000301 };
302
Tim Northover3b0846e2014-05-24 12:50:23 +0000303 struct ExtendOp {
304 unsigned Val;
305 };
306
307 union {
308 struct TokOp Tok;
309 struct RegOp Reg;
310 struct VectorListOp VectorList;
311 struct VectorIndexOp VectorIndex;
312 struct ImmOp Imm;
313 struct ShiftedImmOp ShiftedImm;
314 struct CondCodeOp CondCode;
315 struct FPImmOp FPImm;
316 struct BarrierOp Barrier;
317 struct SysRegOp SysReg;
318 struct SysCRImmOp SysCRImm;
319 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000320 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000321 struct ShiftExtendOp ShiftExtend;
322 };
323
324 // Keep the MCContext around as the MCExprs may need manipulated during
325 // the add<>Operands() calls.
326 MCContext &Ctx;
327
David Blaikie960ea3f2014-06-08 16:18:35 +0000328public:
David Blaikie9f380a32015-03-16 18:06:57 +0000329 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000330
Tim Northover3b0846e2014-05-24 12:50:23 +0000331 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
332 Kind = o.Kind;
333 StartLoc = o.StartLoc;
334 EndLoc = o.EndLoc;
335 switch (Kind) {
336 case k_Token:
337 Tok = o.Tok;
338 break;
339 case k_Immediate:
340 Imm = o.Imm;
341 break;
342 case k_ShiftedImm:
343 ShiftedImm = o.ShiftedImm;
344 break;
345 case k_CondCode:
346 CondCode = o.CondCode;
347 break;
348 case k_FPImm:
349 FPImm = o.FPImm;
350 break;
351 case k_Barrier:
352 Barrier = o.Barrier;
353 break;
354 case k_Register:
355 Reg = o.Reg;
356 break;
357 case k_VectorList:
358 VectorList = o.VectorList;
359 break;
360 case k_VectorIndex:
361 VectorIndex = o.VectorIndex;
362 break;
363 case k_SysReg:
364 SysReg = o.SysReg;
365 break;
366 case k_SysCR:
367 SysCRImm = o.SysCRImm;
368 break;
369 case k_Prefetch:
370 Prefetch = o.Prefetch;
371 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000372 case k_PSBHint:
373 PSBHint = o.PSBHint;
374 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000375 case k_ShiftExtend:
376 ShiftExtend = o.ShiftExtend;
377 break;
378 }
379 }
380
381 /// getStartLoc - Get the location of the first token of this operand.
382 SMLoc getStartLoc() const override { return StartLoc; }
383 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000384 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000385
386 StringRef getToken() const {
387 assert(Kind == k_Token && "Invalid access!");
388 return StringRef(Tok.Data, Tok.Length);
389 }
390
391 bool isTokenSuffix() const {
392 assert(Kind == k_Token && "Invalid access!");
393 return Tok.IsSuffix;
394 }
395
396 const MCExpr *getImm() const {
397 assert(Kind == k_Immediate && "Invalid access!");
398 return Imm.Val;
399 }
400
401 const MCExpr *getShiftedImmVal() const {
402 assert(Kind == k_ShiftedImm && "Invalid access!");
403 return ShiftedImm.Val;
404 }
405
406 unsigned getShiftedImmShift() const {
407 assert(Kind == k_ShiftedImm && "Invalid access!");
408 return ShiftedImm.ShiftAmount;
409 }
410
411 AArch64CC::CondCode getCondCode() const {
412 assert(Kind == k_CondCode && "Invalid access!");
413 return CondCode.Code;
414 }
415
416 unsigned getFPImm() const {
417 assert(Kind == k_FPImm && "Invalid access!");
418 return FPImm.Val;
419 }
420
421 unsigned getBarrier() const {
422 assert(Kind == k_Barrier && "Invalid access!");
423 return Barrier.Val;
424 }
425
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000426 StringRef getBarrierName() const {
427 assert(Kind == k_Barrier && "Invalid access!");
428 return StringRef(Barrier.Data, Barrier.Length);
429 }
430
Tim Northover3b0846e2014-05-24 12:50:23 +0000431 unsigned getReg() const override {
432 assert(Kind == k_Register && "Invalid access!");
433 return Reg.RegNum;
434 }
435
436 unsigned getVectorListStart() const {
437 assert(Kind == k_VectorList && "Invalid access!");
438 return VectorList.RegNum;
439 }
440
441 unsigned getVectorListCount() const {
442 assert(Kind == k_VectorList && "Invalid access!");
443 return VectorList.Count;
444 }
445
446 unsigned getVectorIndex() const {
447 assert(Kind == k_VectorIndex && "Invalid access!");
448 return VectorIndex.Val;
449 }
450
451 StringRef getSysReg() const {
452 assert(Kind == k_SysReg && "Invalid access!");
453 return StringRef(SysReg.Data, SysReg.Length);
454 }
455
Tim Northover3b0846e2014-05-24 12:50:23 +0000456 unsigned getSysCR() const {
457 assert(Kind == k_SysCR && "Invalid access!");
458 return SysCRImm.Val;
459 }
460
461 unsigned getPrefetch() const {
462 assert(Kind == k_Prefetch && "Invalid access!");
463 return Prefetch.Val;
464 }
465
Oliver Stannarda34e4702015-12-01 10:48:51 +0000466 unsigned getPSBHint() const {
467 assert(Kind == k_PSBHint && "Invalid access!");
468 return PSBHint.Val;
469 }
470
471 StringRef getPSBHintName() const {
472 assert(Kind == k_PSBHint && "Invalid access!");
473 return StringRef(PSBHint.Data, PSBHint.Length);
474 }
475
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000476 StringRef getPrefetchName() const {
477 assert(Kind == k_Prefetch && "Invalid access!");
478 return StringRef(Prefetch.Data, Prefetch.Length);
479 }
480
Tim Northover3b0846e2014-05-24 12:50:23 +0000481 AArch64_AM::ShiftExtendType getShiftExtendType() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000482 if (Kind == k_ShiftExtend)
483 return ShiftExtend.Type;
484 if (Kind == k_Register)
485 return Reg.ShiftExtend.Type;
486 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000487 }
488
489 unsigned getShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000490 if (Kind == k_ShiftExtend)
491 return ShiftExtend.Amount;
492 if (Kind == k_Register)
493 return Reg.ShiftExtend.Amount;
494 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000495 }
496
497 bool hasShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000498 if (Kind == k_ShiftExtend)
499 return ShiftExtend.HasExplicitAmount;
500 if (Kind == k_Register)
501 return Reg.ShiftExtend.HasExplicitAmount;
502 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000503 }
504
505 bool isImm() const override { return Kind == k_Immediate; }
506 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000507
508 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
509
Sander de Smalen50ded902018-04-29 17:33:38 +0000510 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
511 return isImmScaled<Bits, Scale>(true);
512 }
513
514 template <int Bits, int Scale> DiagnosticPredicate isUImmScaled() const {
515 return isImmScaled<Bits, Scale>(false);
516 }
517
Sander de Smalenfe17a782018-04-26 12:54:42 +0000518 template <int Bits, int Scale>
Sander de Smalen50ded902018-04-29 17:33:38 +0000519 DiagnosticPredicate isImmScaled(bool Signed) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000520 if (!isImm())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000521 return DiagnosticPredicateTy::NoMatch;
522
Tim Northover3b0846e2014-05-24 12:50:23 +0000523 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
524 if (!MCE)
Sander de Smalenfe17a782018-04-26 12:54:42 +0000525 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000526
Sander de Smalen50ded902018-04-29 17:33:38 +0000527 int64_t MinVal, MaxVal;
528 if (Signed) {
529 int64_t Shift = Bits - 1;
530 MinVal = (int64_t(1) << Shift) * -Scale;
531 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
532 } else {
533 MinVal = 0;
534 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
535 }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000536
Tim Northover3b0846e2014-05-24 12:50:23 +0000537 int64_t Val = MCE->getValue();
Sander de Smalenfe17a782018-04-26 12:54:42 +0000538 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
539 return DiagnosticPredicateTy::Match;
540
541 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +0000542 }
543
Sander de Smalen245e0e62018-01-22 10:46:00 +0000544 bool isSVEPattern() const {
545 if (!isImm())
546 return false;
547 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
548 if (!MCE)
549 return false;
550 int64_t Val = MCE->getValue();
551 return Val >= 0 && Val < 32;
552 }
553
Tim Northover3b0846e2014-05-24 12:50:23 +0000554 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
555 AArch64MCExpr::VariantKind ELFRefKind;
556 MCSymbolRefExpr::VariantKind DarwinRefKind;
557 int64_t Addend;
558 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
559 Addend)) {
560 // If we don't understand the expression, assume the best and
561 // let the fixup and relocation code deal with it.
562 return true;
563 }
564
565 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
566 ELFRefKind == AArch64MCExpr::VK_LO12 ||
567 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
568 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
569 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
570 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
571 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
572 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000573 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
574 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
575 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000576 // Note that we don't range-check the addend. It's adjusted modulo page
577 // size when converted, so there is no "out of range" condition when using
578 // @pageoff.
579 return Addend >= 0 && (Addend % Scale) == 0;
580 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
581 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
582 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
583 return Addend == 0;
584 }
585
586 return false;
587 }
588
589 template <int Scale> bool isUImm12Offset() const {
590 if (!isImm())
591 return false;
592
593 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
594 if (!MCE)
595 return isSymbolicUImm12Offset(getImm(), Scale);
596
597 int64_t Val = MCE->getValue();
598 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
599 }
600
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000601 template <int N, int M>
602 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000603 if (!isImm())
604 return false;
605 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
606 if (!MCE)
607 return false;
608 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000609 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000610 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000611
Sander de Smalena1c259c2018-01-29 13:05:38 +0000612 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
613 // a logical immediate can always be represented when inverted.
614 template <typename T>
615 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000616 if (!isImm())
617 return false;
618 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
619 if (!MCE)
620 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000621
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000622 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000623 int64_t SVal = typename std::make_signed<T>::type(Val);
624 int64_t UVal = typename std::make_unsigned<T>::type(Val);
625 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000626 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000627
Sander de Smalena1c259c2018-01-29 13:05:38 +0000628 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000629 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000630
Tim Northover3b0846e2014-05-24 12:50:23 +0000631 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000632
Tim Northover3b0846e2014-05-24 12:50:23 +0000633 bool isAddSubImm() const {
634 if (!isShiftedImm() && !isImm())
635 return false;
636
637 const MCExpr *Expr;
638
639 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
640 if (isShiftedImm()) {
641 unsigned Shift = ShiftedImm.ShiftAmount;
642 Expr = ShiftedImm.Val;
643 if (Shift != 0 && Shift != 12)
644 return false;
645 } else {
646 Expr = getImm();
647 }
648
649 AArch64MCExpr::VariantKind ELFRefKind;
650 MCSymbolRefExpr::VariantKind DarwinRefKind;
651 int64_t Addend;
652 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
653 DarwinRefKind, Addend)) {
654 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
655 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
656 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
657 || ELFRefKind == AArch64MCExpr::VK_LO12
658 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
659 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
660 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
661 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
662 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
663 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000664 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
665 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
666 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000667 }
668
Diana Picusc93518d2016-10-11 09:17:47 +0000669 // If it's a constant, it should be a real immediate in range:
670 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
671 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
672
673 // If it's an expression, we hope for the best and let the fixup/relocation
674 // code deal with it.
675 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000676 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000677
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000678 bool isAddSubImmNeg() const {
679 if (!isShiftedImm() && !isImm())
680 return false;
681
682 const MCExpr *Expr;
683
684 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
685 if (isShiftedImm()) {
686 unsigned Shift = ShiftedImm.ShiftAmount;
687 Expr = ShiftedImm.Val;
688 if (Shift != 0 && Shift != 12)
689 return false;
690 } else
691 Expr = getImm();
692
693 // Otherwise it should be a real negative immediate in range:
694 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
695 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
696 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000697
Tim Northover3b0846e2014-05-24 12:50:23 +0000698 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000699
Tim Northover3b0846e2014-05-24 12:50:23 +0000700 bool isSIMDImmType10() const {
701 if (!isImm())
702 return false;
703 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
704 if (!MCE)
705 return false;
706 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
707 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000708
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000709 template<int N>
710 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000711 if (!isImm())
712 return false;
713 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
714 if (!MCE)
715 return true;
716 int64_t Val = MCE->getValue();
717 if (Val & 0x3)
718 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000719 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
720 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000721 }
722
723 bool
724 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
725 if (!isImm())
726 return false;
727
728 AArch64MCExpr::VariantKind ELFRefKind;
729 MCSymbolRefExpr::VariantKind DarwinRefKind;
730 int64_t Addend;
731 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
732 DarwinRefKind, Addend)) {
733 return false;
734 }
735 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
736 return false;
737
738 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
739 if (ELFRefKind == AllowedModifiers[i])
740 return Addend == 0;
741 }
742
743 return false;
744 }
745
746 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000747 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000748 }
749
750 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000751 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
752 AArch64MCExpr::VK_TPREL_G2,
753 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000754 }
755
756 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000757 return isMovWSymbol({
758 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000759 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
760 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000761 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000762 }
763
764 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000765 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
766 AArch64MCExpr::VK_TPREL_G0,
767 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000768 }
769
770 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000771 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000772 }
773
774 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000775 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000776 }
777
778 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000779 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
780 AArch64MCExpr::VK_TPREL_G1_NC,
781 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000782 }
783
784 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000785 return isMovWSymbol(
786 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
787 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000788 }
789
790 template<int RegWidth, int Shift>
791 bool isMOVZMovAlias() const {
792 if (!isImm()) return false;
793
794 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
795 if (!CE) return false;
796 uint64_t Value = CE->getValue();
797
Tim Northoverdaa1c012016-06-16 01:42:25 +0000798 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000799 }
800
801 template<int RegWidth, int Shift>
802 bool isMOVNMovAlias() const {
803 if (!isImm()) return false;
804
805 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
806 if (!CE) return false;
807 uint64_t Value = CE->getValue();
808
Tim Northoverdaa1c012016-06-16 01:42:25 +0000809 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000810 }
811
812 bool isFPImm() const { return Kind == k_FPImm; }
813 bool isBarrier() const { return Kind == k_Barrier; }
814 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000815
Tim Northover3b0846e2014-05-24 12:50:23 +0000816 bool isMRSSystemRegister() const {
817 if (!isSysReg()) return false;
818
Tim Northover7cd58932015-01-22 17:23:04 +0000819 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000820 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000821
Tim Northover3b0846e2014-05-24 12:50:23 +0000822 bool isMSRSystemRegister() const {
823 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000824 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000825 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000826
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000827 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000828 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000829 return (SysReg.PStateField == AArch64PState::PAN ||
830 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000831 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000832
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000833 bool isSystemPStateFieldWithImm0_15() const {
834 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000835 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000836 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000837
Florian Hahnc4422242017-11-07 13:07:50 +0000838 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000839 return Kind == k_Register;
840 }
841
842 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000843 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
844 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000845
Florian Hahnc4422242017-11-07 13:07:50 +0000846 bool isNeonVectorReg() const {
847 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
848 }
849
850 bool isNeonVectorRegLo() const {
851 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000852 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
853 Reg.RegNum);
854 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000855
Sander de Smalencd6be962017-12-20 11:02:42 +0000856 template <unsigned Class> bool isSVEVectorReg() const {
857 RegKind RK;
858 switch (Class) {
859 case AArch64::ZPRRegClassID:
860 RK = RegKind::SVEDataVector;
861 break;
862 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000863 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000864 RK = RegKind::SVEPredicateVector;
865 break;
866 default:
867 llvm_unreachable("Unsupport register class");
868 }
869
870 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000871 AArch64MCRegisterClasses[Class].contains(getReg());
872 }
873
Sander de Smalencd6be962017-12-20 11:02:42 +0000874 template <int ElementWidth, unsigned Class>
875 bool isSVEVectorRegOfWidth() const {
876 return isSVEVectorReg<Class>() &&
Sander de Smalen73937b72018-04-11 07:36:10 +0000877 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth);
Florian Hahn91f11e52017-11-07 16:45:48 +0000878 }
879
Sander de Smaleneb896b12018-04-25 09:26:47 +0000880 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +0000881 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
882 bool ShiftWidthAlwaysSame>
Sander de Smalenfe17a782018-04-26 12:54:42 +0000883 DiagnosticPredicate isSVEVectorRegWithShiftExtend() const {
884 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
885 return DiagnosticPredicateTy::NoMatch;
886
Sander de Smalen5861c262018-04-30 07:24:38 +0000887 if (!isSVEVectorRegOfWidth<ElementWidth, Class>())
888 return DiagnosticPredicateTy::NearMatch;
889
890 // Give a more specific diagnostic when the user has explicitly typed in
891 // a shift-amount that does not match what is expected, but for which
892 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
893 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
894 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
895 ShiftExtendTy == AArch64_AM::SXTW) &&
896 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
897 return DiagnosticPredicateTy::NoMatch;
898
899 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000900 return DiagnosticPredicateTy::Match;
901
902 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +0000903 }
904
Tim Northover3b0846e2014-05-24 12:50:23 +0000905 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000906 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000907 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
908 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000909
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000910 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000911 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000912 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
913 Reg.RegNum);
914 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000915
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000916 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000917 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000918 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
919 Reg.RegNum);
920 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000921
Sam Parker5f934642017-08-31 09:27:04 +0000922 template<int64_t Angle, int64_t Remainder>
923 bool isComplexRotation() const {
924 if (!isImm()) return false;
925
926 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
927 if (!CE) return false;
928 uint64_t Value = CE->getValue();
929
930 return (Value % Angle == Remainder && Value <= 270);
931 }
932
Sander de Smalen149916d2018-04-20 07:24:20 +0000933 template <unsigned RegClassID> bool isGPR64() const {
934 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
935 AArch64MCRegisterClasses[RegClassID].contains(getReg());
936 }
937
938 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +0000939 DiagnosticPredicate isGPR64WithShiftExtend() const {
940 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
941 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +0000942
Sander de Smalenfe17a782018-04-26 12:54:42 +0000943 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
944 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
945 return DiagnosticPredicateTy::Match;
946 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +0000947 }
948
Tim Northover3b0846e2014-05-24 12:50:23 +0000949 /// Is this a vector list with the type implicit (presumably attached to the
950 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +0000951 template <RegKind VectorKind, unsigned NumRegs>
952 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000953 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +0000954 VectorList.NumElements == 0 &&
955 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000956 }
957
Sander de Smalen650234b2018-04-12 11:40:52 +0000958 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
959 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +0000960 bool isTypedVectorList() const {
961 if (Kind != k_VectorList)
962 return false;
963 if (VectorList.Count != NumRegs)
964 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +0000965 if (VectorList.RegisterKind != VectorKind)
966 return false;
967 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +0000968 return false;
969 return VectorList.NumElements == NumElements;
970 }
971
972 bool isVectorIndex1() const {
973 return Kind == k_VectorIndex && VectorIndex.Val == 1;
974 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000975
Tim Northover3b0846e2014-05-24 12:50:23 +0000976 bool isVectorIndexB() const {
977 return Kind == k_VectorIndex && VectorIndex.Val < 16;
978 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000979
Tim Northover3b0846e2014-05-24 12:50:23 +0000980 bool isVectorIndexH() const {
981 return Kind == k_VectorIndex && VectorIndex.Val < 8;
982 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000983
Tim Northover3b0846e2014-05-24 12:50:23 +0000984 bool isVectorIndexS() const {
985 return Kind == k_VectorIndex && VectorIndex.Val < 4;
986 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000987
Tim Northover3b0846e2014-05-24 12:50:23 +0000988 bool isVectorIndexD() const {
989 return Kind == k_VectorIndex && VectorIndex.Val < 2;
990 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000991
Tim Northover3b0846e2014-05-24 12:50:23 +0000992 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000993
Tim Northover3b0846e2014-05-24 12:50:23 +0000994 bool isTokenEqual(StringRef Str) const {
995 return Kind == k_Token && getToken() == Str;
996 }
997 bool isSysCR() const { return Kind == k_SysCR; }
998 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000999 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001000 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1001 bool isShifter() const {
1002 if (!isShiftExtend())
1003 return false;
1004
1005 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1006 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1007 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1008 ST == AArch64_AM::MSL);
1009 }
1010 bool isExtend() const {
1011 if (!isShiftExtend())
1012 return false;
1013
1014 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1015 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1016 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1017 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1018 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1019 ET == AArch64_AM::LSL) &&
1020 getShiftExtendAmount() <= 4;
1021 }
1022
1023 bool isExtend64() const {
1024 if (!isExtend())
1025 return false;
1026 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1027 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1028 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1029 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001030
Tim Northover3b0846e2014-05-24 12:50:23 +00001031 bool isExtendLSL64() const {
1032 if (!isExtend())
1033 return false;
1034 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1035 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1036 ET == AArch64_AM::LSL) &&
1037 getShiftExtendAmount() <= 4;
1038 }
1039
1040 template<int Width> bool isMemXExtend() const {
1041 if (!isExtend())
1042 return false;
1043 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1044 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1045 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1046 getShiftExtendAmount() == 0);
1047 }
1048
1049 template<int Width> bool isMemWExtend() const {
1050 if (!isExtend())
1051 return false;
1052 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1053 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1054 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1055 getShiftExtendAmount() == 0);
1056 }
1057
1058 template <unsigned width>
1059 bool isArithmeticShifter() const {
1060 if (!isShifter())
1061 return false;
1062
1063 // An arithmetic shifter is LSL, LSR, or ASR.
1064 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1065 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1066 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1067 }
1068
1069 template <unsigned width>
1070 bool isLogicalShifter() const {
1071 if (!isShifter())
1072 return false;
1073
1074 // A logical shifter is LSL, LSR, ASR or ROR.
1075 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1076 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1077 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1078 getShiftExtendAmount() < width;
1079 }
1080
1081 bool isMovImm32Shifter() const {
1082 if (!isShifter())
1083 return false;
1084
1085 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1086 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1087 if (ST != AArch64_AM::LSL)
1088 return false;
1089 uint64_t Val = getShiftExtendAmount();
1090 return (Val == 0 || Val == 16);
1091 }
1092
1093 bool isMovImm64Shifter() const {
1094 if (!isShifter())
1095 return false;
1096
1097 // A MOVi shifter is LSL of 0 or 16.
1098 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1099 if (ST != AArch64_AM::LSL)
1100 return false;
1101 uint64_t Val = getShiftExtendAmount();
1102 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1103 }
1104
1105 bool isLogicalVecShifter() const {
1106 if (!isShifter())
1107 return false;
1108
1109 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1110 unsigned Shift = getShiftExtendAmount();
1111 return getShiftExtendType() == AArch64_AM::LSL &&
1112 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1113 }
1114
1115 bool isLogicalVecHalfWordShifter() const {
1116 if (!isLogicalVecShifter())
1117 return false;
1118
1119 // A logical vector shifter is a left shift by 0 or 8.
1120 unsigned Shift = getShiftExtendAmount();
1121 return getShiftExtendType() == AArch64_AM::LSL &&
1122 (Shift == 0 || Shift == 8);
1123 }
1124
1125 bool isMoveVecShifter() const {
1126 if (!isShiftExtend())
1127 return false;
1128
1129 // A logical vector shifter is a left shift by 8 or 16.
1130 unsigned Shift = getShiftExtendAmount();
1131 return getShiftExtendType() == AArch64_AM::MSL &&
1132 (Shift == 8 || Shift == 16);
1133 }
1134
1135 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1136 // to LDUR/STUR when the offset is not legal for the former but is for
1137 // the latter. As such, in addition to checking for being a legal unscaled
1138 // address, also check that it is not a legal scaled address. This avoids
1139 // ambiguity in the matcher.
1140 template<int Width>
1141 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001142 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001143 }
1144
1145 bool isAdrpLabel() const {
1146 // Validation was handled during parsing, so we just sanity check that
1147 // something didn't go haywire.
1148 if (!isImm())
1149 return false;
1150
1151 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1152 int64_t Val = CE->getValue();
1153 int64_t Min = - (4096 * (1LL << (21 - 1)));
1154 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1155 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1156 }
1157
1158 return true;
1159 }
1160
1161 bool isAdrLabel() const {
1162 // Validation was handled during parsing, so we just sanity check that
1163 // something didn't go haywire.
1164 if (!isImm())
1165 return false;
1166
1167 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1168 int64_t Val = CE->getValue();
1169 int64_t Min = - (1LL << (21 - 1));
1170 int64_t Max = ((1LL << (21 - 1)) - 1);
1171 return Val >= Min && Val <= Max;
1172 }
1173
1174 return true;
1175 }
1176
1177 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1178 // Add as immediates when possible. Null MCExpr = 0.
1179 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001180 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001181 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001182 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001183 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001184 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001185 }
1186
1187 void addRegOperands(MCInst &Inst, unsigned N) const {
1188 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001189 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001190 }
1191
1192 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1193 assert(N == 1 && "Invalid number of operands!");
1194 assert(
1195 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1196
1197 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1198 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1199 RI->getEncodingValue(getReg()));
1200
Jim Grosbache9119e42015-05-13 18:37:00 +00001201 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001202 }
1203
1204 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1205 assert(N == 1 && "Invalid number of operands!");
1206 assert(
1207 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001208 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001209 }
1210
1211 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1212 assert(N == 1 && "Invalid number of operands!");
1213 assert(
1214 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001215 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001216 }
1217
1218 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1219 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001220 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001221 }
1222
Sander de Smalen525e3222018-04-12 13:19:32 +00001223 enum VecListIndexType {
1224 VecListIdx_DReg = 0,
1225 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001226 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001227 };
1228
1229 template <VecListIndexType RegTy, unsigned NumRegs>
1230 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001231 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001232 static const unsigned FirstRegs[][5] = {
1233 /* DReg */ { AArch64::Q0,
1234 AArch64::D0, AArch64::D0_D1,
1235 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1236 /* QReg */ { AArch64::Q0,
1237 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001238 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1239 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001240 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001241 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001242 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001243
Sander de Smalen7a210db2018-04-16 10:46:18 +00001244 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1245 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001246
Sander de Smalen525e3222018-04-12 13:19:32 +00001247 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1248 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1249 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001250 }
1251
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001252 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001253 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001254 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001255 }
1256
1257 void addImmOperands(MCInst &Inst, unsigned N) const {
1258 assert(N == 1 && "Invalid number of operands!");
1259 // If this is a pageoff symrefexpr with an addend, adjust the addend
1260 // to be only the page-offset portion. Otherwise, just add the expr
1261 // as-is.
1262 addExpr(Inst, getImm());
1263 }
1264
1265 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1266 assert(N == 2 && "Invalid number of operands!");
1267 if (isShiftedImm()) {
1268 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001269 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001270 } else {
1271 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001272 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001273 }
1274 }
1275
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001276 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1277 assert(N == 2 && "Invalid number of operands!");
1278
1279 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1280 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1281 int64_t Val = -CE->getValue();
1282 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1283
1284 Inst.addOperand(MCOperand::createImm(Val));
1285 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1286 }
1287
Tim Northover3b0846e2014-05-24 12:50:23 +00001288 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1289 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001290 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001291 }
1292
1293 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1294 assert(N == 1 && "Invalid number of operands!");
1295 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1296 if (!MCE)
1297 addExpr(Inst, getImm());
1298 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001299 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001300 }
1301
1302 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1303 addImmOperands(Inst, N);
1304 }
1305
1306 template<int Scale>
1307 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1308 assert(N == 1 && "Invalid number of operands!");
1309 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1310
1311 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001312 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001313 return;
1314 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001315 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001316 }
1317
Sander de Smalen5c625982018-04-13 12:56:14 +00001318 template <int Scale>
1319 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1320 assert(N == 1 && "Invalid number of operands!");
1321 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1322 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1323 }
1324
Sander de Smalena1c259c2018-01-29 13:05:38 +00001325 template <typename T>
1326 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001327 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001328 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001329 typename std::make_unsigned<T>::type Val = MCE->getValue();
1330 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001331 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001332 }
1333
Sander de Smalena1c259c2018-01-29 13:05:38 +00001334 template <typename T>
1335 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001336 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001337 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001338 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1339 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001340 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001341 }
1342
Tim Northover3b0846e2014-05-24 12:50:23 +00001343 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1344 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001345 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001346 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001347 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001348 }
1349
1350 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1351 // Branch operands don't encode the low bits, so shift them off
1352 // here. If it's a label, however, just put it on directly as there's
1353 // not enough information now to do anything.
1354 assert(N == 1 && "Invalid number of operands!");
1355 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1356 if (!MCE) {
1357 addExpr(Inst, getImm());
1358 return;
1359 }
1360 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001361 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001362 }
1363
1364 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1365 // Branch operands don't encode the low bits, so shift them off
1366 // here. If it's a label, however, just put it on directly as there's
1367 // not enough information now to do anything.
1368 assert(N == 1 && "Invalid number of operands!");
1369 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1370 if (!MCE) {
1371 addExpr(Inst, getImm());
1372 return;
1373 }
1374 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001375 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001376 }
1377
1378 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1379 // Branch operands don't encode the low bits, so shift them off
1380 // here. If it's a label, however, just put it on directly as there's
1381 // not enough information now to do anything.
1382 assert(N == 1 && "Invalid number of operands!");
1383 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1384 if (!MCE) {
1385 addExpr(Inst, getImm());
1386 return;
1387 }
1388 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001389 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001390 }
1391
1392 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1393 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001394 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001395 }
1396
1397 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1398 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001399 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001400 }
1401
1402 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1403 assert(N == 1 && "Invalid number of operands!");
1404
Jim Grosbache9119e42015-05-13 18:37:00 +00001405 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001406 }
1407
1408 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1409 assert(N == 1 && "Invalid number of operands!");
1410
Jim Grosbache9119e42015-05-13 18:37:00 +00001411 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001412 }
1413
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001414 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1415 assert(N == 1 && "Invalid number of operands!");
1416
1417 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1418 }
1419
1420 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001421 assert(N == 1 && "Invalid number of operands!");
1422
Jim Grosbache9119e42015-05-13 18:37:00 +00001423 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001424 }
1425
1426 void addSysCROperands(MCInst &Inst, unsigned N) const {
1427 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001428 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001429 }
1430
1431 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1432 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001433 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 }
1435
Oliver Stannarda34e4702015-12-01 10:48:51 +00001436 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1437 assert(N == 1 && "Invalid number of operands!");
1438 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1439 }
1440
Tim Northover3b0846e2014-05-24 12:50:23 +00001441 void addShifterOperands(MCInst &Inst, unsigned N) const {
1442 assert(N == 1 && "Invalid number of operands!");
1443 unsigned Imm =
1444 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001445 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001446 }
1447
1448 void addExtendOperands(MCInst &Inst, unsigned N) const {
1449 assert(N == 1 && "Invalid number of operands!");
1450 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1451 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1452 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001453 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001454 }
1455
1456 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1457 assert(N == 1 && "Invalid number of operands!");
1458 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1459 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1460 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001461 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001462 }
1463
1464 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1465 assert(N == 2 && "Invalid number of operands!");
1466 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1467 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001468 Inst.addOperand(MCOperand::createImm(IsSigned));
1469 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001470 }
1471
1472 // For 8-bit load/store instructions with a register offset, both the
1473 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1474 // they're disambiguated by whether the shift was explicit or implicit rather
1475 // than its size.
1476 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1477 assert(N == 2 && "Invalid number of operands!");
1478 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1479 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001480 Inst.addOperand(MCOperand::createImm(IsSigned));
1481 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001482 }
1483
1484 template<int Shift>
1485 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1486 assert(N == 1 && "Invalid number of operands!");
1487
1488 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1489 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001490 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001491 }
1492
1493 template<int Shift>
1494 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1495 assert(N == 1 && "Invalid number of operands!");
1496
1497 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1498 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001499 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001500 }
1501
Sam Parker5f934642017-08-31 09:27:04 +00001502 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1503 assert(N == 1 && "Invalid number of operands!");
1504 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1505 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1506 }
1507
1508 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1509 assert(N == 1 && "Invalid number of operands!");
1510 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1511 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1512 }
1513
Tim Northover3b0846e2014-05-24 12:50:23 +00001514 void print(raw_ostream &OS) const override;
1515
David Blaikie960ea3f2014-06-08 16:18:35 +00001516 static std::unique_ptr<AArch64Operand>
1517 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1518 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001519 Op->Tok.Data = Str.data();
1520 Op->Tok.Length = Str.size();
1521 Op->Tok.IsSuffix = IsSuffix;
1522 Op->StartLoc = S;
1523 Op->EndLoc = S;
1524 return Op;
1525 }
1526
David Blaikie960ea3f2014-06-08 16:18:35 +00001527 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001528 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
1529 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1530 unsigned ShiftAmount = 0,
1531 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001532 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001533 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001534 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001535 Op->Reg.ElementWidth = 0;
1536 Op->Reg.ShiftExtend.Type = ExtTy;
1537 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1538 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001539 Op->StartLoc = S;
1540 Op->EndLoc = E;
1541 return Op;
1542 }
1543
David Blaikie960ea3f2014-06-08 16:18:35 +00001544 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001545 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001546 SMLoc S, SMLoc E, MCContext &Ctx,
1547 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1548 unsigned ShiftAmount = 0,
1549 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001550 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1551 Kind == RegKind::SVEPredicateVector) &&
1552 "Invalid vector kind");
Sander de Smalen149916d2018-04-20 07:24:20 +00001553 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, ExtTy, ShiftAmount,
1554 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001555 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001556 return Op;
1557 }
1558
1559 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001560 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001561 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1562 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001563 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001564 Op->VectorList.RegNum = RegNum;
1565 Op->VectorList.Count = Count;
1566 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001567 Op->VectorList.ElementWidth = ElementWidth;
1568 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001569 Op->StartLoc = S;
1570 Op->EndLoc = E;
1571 return Op;
1572 }
1573
David Blaikie960ea3f2014-06-08 16:18:35 +00001574 static std::unique_ptr<AArch64Operand>
1575 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1576 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001577 Op->VectorIndex.Val = Idx;
1578 Op->StartLoc = S;
1579 Op->EndLoc = E;
1580 return Op;
1581 }
1582
David Blaikie960ea3f2014-06-08 16:18:35 +00001583 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1584 SMLoc E, MCContext &Ctx) {
1585 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001586 Op->Imm.Val = Val;
1587 Op->StartLoc = S;
1588 Op->EndLoc = E;
1589 return Op;
1590 }
1591
David Blaikie960ea3f2014-06-08 16:18:35 +00001592 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1593 unsigned ShiftAmount,
1594 SMLoc S, SMLoc E,
1595 MCContext &Ctx) {
1596 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001597 Op->ShiftedImm .Val = Val;
1598 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1599 Op->StartLoc = S;
1600 Op->EndLoc = E;
1601 return Op;
1602 }
1603
David Blaikie960ea3f2014-06-08 16:18:35 +00001604 static std::unique_ptr<AArch64Operand>
1605 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1606 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001607 Op->CondCode.Code = Code;
1608 Op->StartLoc = S;
1609 Op->EndLoc = E;
1610 return Op;
1611 }
1612
David Blaikie960ea3f2014-06-08 16:18:35 +00001613 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1614 MCContext &Ctx) {
1615 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001616 Op->FPImm.Val = Val;
1617 Op->StartLoc = S;
1618 Op->EndLoc = S;
1619 return Op;
1620 }
1621
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001622 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1623 StringRef Str,
1624 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001625 MCContext &Ctx) {
1626 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001627 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001628 Op->Barrier.Data = Str.data();
1629 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001630 Op->StartLoc = S;
1631 Op->EndLoc = S;
1632 return Op;
1633 }
1634
Tim Northover7cd58932015-01-22 17:23:04 +00001635 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1636 uint32_t MRSReg,
1637 uint32_t MSRReg,
1638 uint32_t PStateField,
1639 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001640 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001641 Op->SysReg.Data = Str.data();
1642 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001643 Op->SysReg.MRSReg = MRSReg;
1644 Op->SysReg.MSRReg = MSRReg;
1645 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001646 Op->StartLoc = S;
1647 Op->EndLoc = S;
1648 return Op;
1649 }
1650
David Blaikie960ea3f2014-06-08 16:18:35 +00001651 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1652 SMLoc E, MCContext &Ctx) {
1653 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001654 Op->SysCRImm.Val = Val;
1655 Op->StartLoc = S;
1656 Op->EndLoc = E;
1657 return Op;
1658 }
1659
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001660 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1661 StringRef Str,
1662 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001663 MCContext &Ctx) {
1664 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001665 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001666 Op->Barrier.Data = Str.data();
1667 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001668 Op->StartLoc = S;
1669 Op->EndLoc = S;
1670 return Op;
1671 }
1672
Oliver Stannarda34e4702015-12-01 10:48:51 +00001673 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1674 StringRef Str,
1675 SMLoc S,
1676 MCContext &Ctx) {
1677 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1678 Op->PSBHint.Val = Val;
1679 Op->PSBHint.Data = Str.data();
1680 Op->PSBHint.Length = Str.size();
1681 Op->StartLoc = S;
1682 Op->EndLoc = S;
1683 return Op;
1684 }
1685
David Blaikie960ea3f2014-06-08 16:18:35 +00001686 static std::unique_ptr<AArch64Operand>
1687 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1688 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1689 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001690 Op->ShiftExtend.Type = ShOp;
1691 Op->ShiftExtend.Amount = Val;
1692 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1693 Op->StartLoc = S;
1694 Op->EndLoc = E;
1695 return Op;
1696 }
1697};
1698
1699} // end anonymous namespace.
1700
1701void AArch64Operand::print(raw_ostream &OS) const {
1702 switch (Kind) {
1703 case k_FPImm:
1704 OS << "<fpimm " << getFPImm() << "("
1705 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1706 break;
1707 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001708 StringRef Name = getBarrierName();
1709 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001710 OS << "<barrier " << Name << ">";
1711 else
1712 OS << "<barrier invalid #" << getBarrier() << ">";
1713 break;
1714 }
1715 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001716 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001717 break;
1718 case k_ShiftedImm: {
1719 unsigned Shift = getShiftedImmShift();
1720 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001721 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001722 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1723 break;
1724 }
1725 case k_CondCode:
1726 OS << "<condcode " << getCondCode() << ">";
1727 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001728 case k_VectorList: {
1729 OS << "<vectorlist ";
1730 unsigned Reg = getVectorListStart();
1731 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1732 OS << Reg + i << " ";
1733 OS << ">";
1734 break;
1735 }
1736 case k_VectorIndex:
1737 OS << "<vectorindex " << getVectorIndex() << ">";
1738 break;
1739 case k_SysReg:
1740 OS << "<sysreg: " << getSysReg() << '>';
1741 break;
1742 case k_Token:
1743 OS << "'" << getToken() << "'";
1744 break;
1745 case k_SysCR:
1746 OS << "c" << getSysCR();
1747 break;
1748 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001749 StringRef Name = getPrefetchName();
1750 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001751 OS << "<prfop " << Name << ">";
1752 else
1753 OS << "<prfop invalid #" << getPrefetch() << ">";
1754 break;
1755 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001756 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001757 OS << getPSBHintName();
1758 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00001759 case k_Register:
1760 OS << "<register " << getReg() << ">";
1761 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
1762 break;
1763 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001764 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001765 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1766 << getShiftExtendAmount();
1767 if (!hasShiftExtendAmount())
1768 OS << "<imp>";
1769 OS << '>';
1770 break;
1771 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001772}
1773
1774/// @name Auto-generated Match Functions
1775/// {
1776
1777static unsigned MatchRegisterName(StringRef Name);
1778
1779/// }
1780
Florian Hahnc4422242017-11-07 13:07:50 +00001781static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001782 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001783 .Case("v0", AArch64::Q0)
1784 .Case("v1", AArch64::Q1)
1785 .Case("v2", AArch64::Q2)
1786 .Case("v3", AArch64::Q3)
1787 .Case("v4", AArch64::Q4)
1788 .Case("v5", AArch64::Q5)
1789 .Case("v6", AArch64::Q6)
1790 .Case("v7", AArch64::Q7)
1791 .Case("v8", AArch64::Q8)
1792 .Case("v9", AArch64::Q9)
1793 .Case("v10", AArch64::Q10)
1794 .Case("v11", AArch64::Q11)
1795 .Case("v12", AArch64::Q12)
1796 .Case("v13", AArch64::Q13)
1797 .Case("v14", AArch64::Q14)
1798 .Case("v15", AArch64::Q15)
1799 .Case("v16", AArch64::Q16)
1800 .Case("v17", AArch64::Q17)
1801 .Case("v18", AArch64::Q18)
1802 .Case("v19", AArch64::Q19)
1803 .Case("v20", AArch64::Q20)
1804 .Case("v21", AArch64::Q21)
1805 .Case("v22", AArch64::Q22)
1806 .Case("v23", AArch64::Q23)
1807 .Case("v24", AArch64::Q24)
1808 .Case("v25", AArch64::Q25)
1809 .Case("v26", AArch64::Q26)
1810 .Case("v27", AArch64::Q27)
1811 .Case("v28", AArch64::Q28)
1812 .Case("v29", AArch64::Q29)
1813 .Case("v30", AArch64::Q30)
1814 .Case("v31", AArch64::Q31)
1815 .Default(0);
1816}
1817
Sander de Smalen73937b72018-04-11 07:36:10 +00001818/// Returns an optional pair of (#elements, element-width) if Suffix
1819/// is a valid vector kind. Where the number of elements in a vector
1820/// or the vector width is implicit or explicitly unknown (but still a
1821/// valid suffix kind), 0 is used.
1822static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1823 RegKind VectorKind) {
1824 std::pair<int, int> Res = {-1, -1};
1825
1826 switch (VectorKind) {
1827 case RegKind::NeonVector:
1828 Res =
1829 StringSwitch<std::pair<int, int>>(Suffix.lower())
1830 .Case("", {0, 0})
1831 .Case(".1d", {1, 64})
1832 .Case(".1q", {1, 128})
1833 // '.2h' needed for fp16 scalar pairwise reductions
1834 .Case(".2h", {2, 16})
1835 .Case(".2s", {2, 32})
1836 .Case(".2d", {2, 64})
1837 // '.4b' is another special case for the ARMv8.2a dot product
1838 // operand
1839 .Case(".4b", {4, 8})
1840 .Case(".4h", {4, 16})
1841 .Case(".4s", {4, 32})
1842 .Case(".8b", {8, 8})
1843 .Case(".8h", {8, 16})
1844 .Case(".16b", {16, 8})
1845 // Accept the width neutral ones, too, for verbose syntax. If those
1846 // aren't used in the right places, the token operand won't match so
1847 // all will work out.
1848 .Case(".b", {0, 8})
1849 .Case(".h", {0, 16})
1850 .Case(".s", {0, 32})
1851 .Case(".d", {0, 64})
1852 .Default({-1, -1});
1853 break;
1854 case RegKind::SVEPredicateVector:
1855 case RegKind::SVEDataVector:
1856 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1857 .Case("", {0, 0})
1858 .Case(".b", {0, 8})
1859 .Case(".h", {0, 16})
1860 .Case(".s", {0, 32})
1861 .Case(".d", {0, 64})
1862 .Case(".q", {0, 128})
1863 .Default({-1, -1});
1864 break;
1865 default:
1866 llvm_unreachable("Unsupported RegKind");
1867 }
1868
1869 if (Res == std::make_pair(-1, -1))
1870 return Optional<std::pair<int, int>>();
1871
1872 return Optional<std::pair<int, int>>(Res);
1873}
1874
1875static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1876 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001877}
1878
Florian Hahn91f11e52017-11-07 16:45:48 +00001879static unsigned matchSVEDataVectorRegName(StringRef Name) {
1880 return StringSwitch<unsigned>(Name.lower())
1881 .Case("z0", AArch64::Z0)
1882 .Case("z1", AArch64::Z1)
1883 .Case("z2", AArch64::Z2)
1884 .Case("z3", AArch64::Z3)
1885 .Case("z4", AArch64::Z4)
1886 .Case("z5", AArch64::Z5)
1887 .Case("z6", AArch64::Z6)
1888 .Case("z7", AArch64::Z7)
1889 .Case("z8", AArch64::Z8)
1890 .Case("z9", AArch64::Z9)
1891 .Case("z10", AArch64::Z10)
1892 .Case("z11", AArch64::Z11)
1893 .Case("z12", AArch64::Z12)
1894 .Case("z13", AArch64::Z13)
1895 .Case("z14", AArch64::Z14)
1896 .Case("z15", AArch64::Z15)
1897 .Case("z16", AArch64::Z16)
1898 .Case("z17", AArch64::Z17)
1899 .Case("z18", AArch64::Z18)
1900 .Case("z19", AArch64::Z19)
1901 .Case("z20", AArch64::Z20)
1902 .Case("z21", AArch64::Z21)
1903 .Case("z22", AArch64::Z22)
1904 .Case("z23", AArch64::Z23)
1905 .Case("z24", AArch64::Z24)
1906 .Case("z25", AArch64::Z25)
1907 .Case("z26", AArch64::Z26)
1908 .Case("z27", AArch64::Z27)
1909 .Case("z28", AArch64::Z28)
1910 .Case("z29", AArch64::Z29)
1911 .Case("z30", AArch64::Z30)
1912 .Case("z31", AArch64::Z31)
1913 .Default(0);
1914}
1915
Sander de Smalencd6be962017-12-20 11:02:42 +00001916static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1917 return StringSwitch<unsigned>(Name.lower())
1918 .Case("p0", AArch64::P0)
1919 .Case("p1", AArch64::P1)
1920 .Case("p2", AArch64::P2)
1921 .Case("p3", AArch64::P3)
1922 .Case("p4", AArch64::P4)
1923 .Case("p5", AArch64::P5)
1924 .Case("p6", AArch64::P6)
1925 .Case("p7", AArch64::P7)
1926 .Case("p8", AArch64::P8)
1927 .Case("p9", AArch64::P9)
1928 .Case("p10", AArch64::P10)
1929 .Case("p11", AArch64::P11)
1930 .Case("p12", AArch64::P12)
1931 .Case("p13", AArch64::P13)
1932 .Case("p14", AArch64::P14)
1933 .Case("p15", AArch64::P15)
1934 .Default(0);
1935}
1936
Tim Northover3b0846e2014-05-24 12:50:23 +00001937bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1938 SMLoc &EndLoc) {
1939 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00001940 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00001941 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00001942 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00001943}
1944
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001945// Matches a register name or register alias previously defined by '.req'
1946unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001947 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001948 unsigned RegNum = 0;
1949 if ((RegNum = matchSVEDataVectorRegName(Name)))
1950 return Kind == RegKind::SVEDataVector ? RegNum : 0;
1951
Sander de Smalencd6be962017-12-20 11:02:42 +00001952 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
1953 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
1954
Sander de Smalenc067c302017-12-20 09:45:45 +00001955 if ((RegNum = MatchNeonVectorRegName(Name)))
1956 return Kind == RegKind::NeonVector ? RegNum : 0;
1957
1958 // The parsed register must be of RegKind Scalar
1959 if ((RegNum = MatchRegisterName(Name)))
1960 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001961
Florian Hahnc4422242017-11-07 13:07:50 +00001962 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00001963 // Handle a few common aliases of registers.
1964 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
1965 .Case("fp", AArch64::FP)
1966 .Case("lr", AArch64::LR)
1967 .Case("x31", AArch64::XZR)
1968 .Case("w31", AArch64::WZR)
1969 .Default(0))
1970 return Kind == RegKind::Scalar ? RegNum : 0;
1971
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001972 // Check for aliases registered via .req. Canonicalize to lower case.
1973 // That's more consistent since register names are case insensitive, and
1974 // it's how the original entry was passed in from MC/MCParser/AsmParser.
1975 auto Entry = RegisterReqs.find(Name.lower());
1976 if (Entry == RegisterReqs.end())
1977 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00001978
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001979 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00001980 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001981 RegNum = Entry->getValue().second;
1982 }
1983 return RegNum;
1984}
1985
Sander de Smalen50d87022018-04-19 07:35:08 +00001986/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00001987/// Identifier when called, and if it is a register name the token is eaten and
1988/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00001989OperandMatchResultTy
1990AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001991 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001992 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00001993 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00001994 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001995
1996 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00001997 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
1998 if (Reg == 0)
1999 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002000
Sander de Smalen50d87022018-04-19 07:35:08 +00002001 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002002 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002003 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002004}
2005
Tim Northover3b0846e2014-05-24 12:50:23 +00002006/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002007OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002008AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002009 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002010 SMLoc S = getLoc();
2011
2012 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2013 Error(S, "Expected cN operand where 0 <= N <= 15");
2014 return MatchOperand_ParseFail;
2015 }
2016
2017 StringRef Tok = Parser.getTok().getIdentifier();
2018 if (Tok[0] != 'c' && Tok[0] != 'C') {
2019 Error(S, "Expected cN operand where 0 <= N <= 15");
2020 return MatchOperand_ParseFail;
2021 }
2022
2023 uint32_t CRNum;
2024 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2025 if (BadNum || CRNum > 15) {
2026 Error(S, "Expected cN operand where 0 <= N <= 15");
2027 return MatchOperand_ParseFail;
2028 }
2029
2030 Parser.Lex(); // Eat identifier token.
2031 Operands.push_back(
2032 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2033 return MatchOperand_Success;
2034}
2035
2036/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002037template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002038OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002039AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002040 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002041 SMLoc S = getLoc();
2042 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002043
2044 auto LookupByName = [](StringRef N) {
2045 if (IsSVEPrefetch) {
2046 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2047 return Optional<unsigned>(Res->Encoding);
2048 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2049 return Optional<unsigned>(Res->Encoding);
2050 return Optional<unsigned>();
2051 };
2052
2053 auto LookupByEncoding = [](unsigned E) {
2054 if (IsSVEPrefetch) {
2055 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2056 return Optional<StringRef>(Res->Name);
2057 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2058 return Optional<StringRef>(Res->Name);
2059 return Optional<StringRef>();
2060 };
2061 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2062
Tim Northover3b0846e2014-05-24 12:50:23 +00002063 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002064 // Eat optional hash.
2065 if (parseOptionalToken(AsmToken::Hash) ||
2066 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002067 const MCExpr *ImmVal;
2068 if (getParser().parseExpression(ImmVal))
2069 return MatchOperand_ParseFail;
2070
2071 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2072 if (!MCE) {
2073 TokError("immediate value expected for prefetch operand");
2074 return MatchOperand_ParseFail;
2075 }
2076 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002077 if (prfop > MaxVal) {
2078 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2079 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002080 return MatchOperand_ParseFail;
2081 }
2082
Sander de Smalen93380372018-05-14 11:54:41 +00002083 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002084 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002085 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002086 return MatchOperand_Success;
2087 }
2088
2089 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002090 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002091 return MatchOperand_ParseFail;
2092 }
2093
Sander de Smalen93380372018-05-14 11:54:41 +00002094 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002095 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002096 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002097 return MatchOperand_ParseFail;
2098 }
2099
2100 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002101 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002102 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002103 return MatchOperand_Success;
2104}
2105
Oliver Stannarda34e4702015-12-01 10:48:51 +00002106/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002107OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002108AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2109 MCAsmParser &Parser = getParser();
2110 SMLoc S = getLoc();
2111 const AsmToken &Tok = Parser.getTok();
2112 if (Tok.isNot(AsmToken::Identifier)) {
2113 TokError("invalid operand for instruction");
2114 return MatchOperand_ParseFail;
2115 }
2116
Tim Northovere6ae6762016-07-05 21:23:04 +00002117 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2118 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002119 TokError("invalid operand for instruction");
2120 return MatchOperand_ParseFail;
2121 }
2122
2123 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002124 Operands.push_back(AArch64Operand::CreatePSBHint(
2125 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002126 return MatchOperand_Success;
2127}
2128
Tim Northover3b0846e2014-05-24 12:50:23 +00002129/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2130/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002131OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002132AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002133 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002134 SMLoc S = getLoc();
2135 const MCExpr *Expr;
2136
2137 if (Parser.getTok().is(AsmToken::Hash)) {
2138 Parser.Lex(); // Eat hash token.
2139 }
2140
2141 if (parseSymbolicImmVal(Expr))
2142 return MatchOperand_ParseFail;
2143
2144 AArch64MCExpr::VariantKind ELFRefKind;
2145 MCSymbolRefExpr::VariantKind DarwinRefKind;
2146 int64_t Addend;
2147 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2148 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2149 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2150 // No modifier was specified at all; this is the syntax for an ELF basic
2151 // ADRP relocation (unfortunately).
2152 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002153 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002154 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2155 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2156 Addend != 0) {
2157 Error(S, "gotpage label reference not allowed an addend");
2158 return MatchOperand_ParseFail;
2159 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2160 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2161 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2162 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2163 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2164 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2165 // The operand must be an @page or @gotpage qualified symbolref.
2166 Error(S, "page or gotpage label reference expected");
2167 return MatchOperand_ParseFail;
2168 }
2169 }
2170
2171 // We have either a label reference possibly with addend or an immediate. The
2172 // addend is a raw value here. The linker will adjust it to only reference the
2173 // page.
2174 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2175 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2176
2177 return MatchOperand_Success;
2178}
2179
2180/// tryParseAdrLabel - Parse and validate a source label for the ADR
2181/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002182OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002183AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2184 SMLoc S = getLoc();
2185 const MCExpr *Expr;
2186
Nirav Davee833c6c2016-11-08 18:31:04 +00002187 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002188 if (getParser().parseExpression(Expr))
2189 return MatchOperand_ParseFail;
2190
2191 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2192 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2193
2194 return MatchOperand_Success;
2195}
2196
2197/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002198OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002199AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002200 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002201 SMLoc S = getLoc();
2202
Nirav Davee833c6c2016-11-08 18:31:04 +00002203 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002204
2205 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002206 bool isNegative = parseOptionalToken(AsmToken::Minus);
2207
Tim Northover3b0846e2014-05-24 12:50:23 +00002208 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002209 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002210 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002211 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002212 Val = Tok.getIntVal();
2213 if (Val > 255 || Val < 0) {
2214 TokError("encoded floating point value out of range");
2215 return MatchOperand_ParseFail;
2216 }
2217 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002218 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002219 if (isNegative)
2220 RealVal.changeSign();
2221
Tim Northover3b0846e2014-05-24 12:50:23 +00002222 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002223 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002224
John Brawn5ca5daa2017-04-20 10:13:54 +00002225 // Check for out of range values. As an exception we let Zero through,
2226 // but as tokens instead of an FPImm so that it can be matched by the
2227 // appropriate alias if one exists.
2228 if (RealVal.isPosZero()) {
2229 Parser.Lex(); // Eat the token.
2230 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2231 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2232 return MatchOperand_Success;
2233 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002234 TokError("expected compatible register or floating-point constant");
2235 return MatchOperand_ParseFail;
2236 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002237 }
2238 Parser.Lex(); // Eat the token.
2239 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2240 return MatchOperand_Success;
2241 }
2242
2243 if (!Hash)
2244 return MatchOperand_NoMatch;
2245
2246 TokError("invalid floating point immediate");
2247 return MatchOperand_ParseFail;
2248}
2249
2250/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002251OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002252AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002253 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002254 SMLoc S = getLoc();
2255
2256 if (Parser.getTok().is(AsmToken::Hash))
2257 Parser.Lex(); // Eat '#'
2258 else if (Parser.getTok().isNot(AsmToken::Integer))
2259 // Operand should start from # or should be integer, emit error otherwise.
2260 return MatchOperand_NoMatch;
2261
2262 const MCExpr *Imm;
2263 if (parseSymbolicImmVal(Imm))
2264 return MatchOperand_ParseFail;
2265 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2266 uint64_t ShiftAmount = 0;
2267 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2268 if (MCE) {
2269 int64_t Val = MCE->getValue();
2270 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002271 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002272 ShiftAmount = 12;
2273 }
2274 }
2275 SMLoc E = Parser.getTok().getLoc();
2276 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2277 getContext()));
2278 return MatchOperand_Success;
2279 }
2280
2281 // Eat ','
2282 Parser.Lex();
2283
2284 // The optional operand must be "lsl #N" where N is non-negative.
2285 if (!Parser.getTok().is(AsmToken::Identifier) ||
2286 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2287 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2288 return MatchOperand_ParseFail;
2289 }
2290
2291 // Eat 'lsl'
2292 Parser.Lex();
2293
Nirav Davee833c6c2016-11-08 18:31:04 +00002294 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002295
2296 if (Parser.getTok().isNot(AsmToken::Integer)) {
2297 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2298 return MatchOperand_ParseFail;
2299 }
2300
2301 int64_t ShiftAmount = Parser.getTok().getIntVal();
2302
2303 if (ShiftAmount < 0) {
2304 Error(Parser.getTok().getLoc(), "positive shift amount required");
2305 return MatchOperand_ParseFail;
2306 }
2307 Parser.Lex(); // Eat the number
2308
2309 SMLoc E = Parser.getTok().getLoc();
2310 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2311 S, E, getContext()));
2312 return MatchOperand_Success;
2313}
2314
2315/// parseCondCodeString - Parse a Condition Code string.
2316AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2317 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2318 .Case("eq", AArch64CC::EQ)
2319 .Case("ne", AArch64CC::NE)
2320 .Case("cs", AArch64CC::HS)
2321 .Case("hs", AArch64CC::HS)
2322 .Case("cc", AArch64CC::LO)
2323 .Case("lo", AArch64CC::LO)
2324 .Case("mi", AArch64CC::MI)
2325 .Case("pl", AArch64CC::PL)
2326 .Case("vs", AArch64CC::VS)
2327 .Case("vc", AArch64CC::VC)
2328 .Case("hi", AArch64CC::HI)
2329 .Case("ls", AArch64CC::LS)
2330 .Case("ge", AArch64CC::GE)
2331 .Case("lt", AArch64CC::LT)
2332 .Case("gt", AArch64CC::GT)
2333 .Case("le", AArch64CC::LE)
2334 .Case("al", AArch64CC::AL)
2335 .Case("nv", AArch64CC::NV)
2336 .Default(AArch64CC::Invalid);
2337 return CC;
2338}
2339
2340/// parseCondCode - Parse a Condition Code operand.
2341bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2342 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002343 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002344 SMLoc S = getLoc();
2345 const AsmToken &Tok = Parser.getTok();
2346 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2347
2348 StringRef Cond = Tok.getString();
2349 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2350 if (CC == AArch64CC::Invalid)
2351 return TokError("invalid condition code");
2352 Parser.Lex(); // Eat identifier token.
2353
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002354 if (invertCondCode) {
2355 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2356 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002357 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002358 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002359
2360 Operands.push_back(
2361 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2362 return false;
2363}
2364
2365/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2366/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002367OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002368AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002369 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002370 const AsmToken &Tok = Parser.getTok();
2371 std::string LowerID = Tok.getString().lower();
2372 AArch64_AM::ShiftExtendType ShOp =
2373 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2374 .Case("lsl", AArch64_AM::LSL)
2375 .Case("lsr", AArch64_AM::LSR)
2376 .Case("asr", AArch64_AM::ASR)
2377 .Case("ror", AArch64_AM::ROR)
2378 .Case("msl", AArch64_AM::MSL)
2379 .Case("uxtb", AArch64_AM::UXTB)
2380 .Case("uxth", AArch64_AM::UXTH)
2381 .Case("uxtw", AArch64_AM::UXTW)
2382 .Case("uxtx", AArch64_AM::UXTX)
2383 .Case("sxtb", AArch64_AM::SXTB)
2384 .Case("sxth", AArch64_AM::SXTH)
2385 .Case("sxtw", AArch64_AM::SXTW)
2386 .Case("sxtx", AArch64_AM::SXTX)
2387 .Default(AArch64_AM::InvalidShiftExtend);
2388
2389 if (ShOp == AArch64_AM::InvalidShiftExtend)
2390 return MatchOperand_NoMatch;
2391
2392 SMLoc S = Tok.getLoc();
2393 Parser.Lex();
2394
Nirav Davee833c6c2016-11-08 18:31:04 +00002395 bool Hash = parseOptionalToken(AsmToken::Hash);
2396
Tim Northover3b0846e2014-05-24 12:50:23 +00002397 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2398 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2399 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2400 ShOp == AArch64_AM::MSL) {
2401 // We expect a number here.
2402 TokError("expected #imm after shift specifier");
2403 return MatchOperand_ParseFail;
2404 }
2405
Chad Rosier2ff37b82016-12-27 16:58:09 +00002406 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002407 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2408 Operands.push_back(
2409 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2410 return MatchOperand_Success;
2411 }
2412
Chad Rosier2ff37b82016-12-27 16:58:09 +00002413 // Make sure we do actually have a number, identifier or a parenthesized
2414 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002415 SMLoc E = Parser.getTok().getLoc();
2416 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002417 !Parser.getTok().is(AsmToken::LParen) &&
2418 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002419 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002420 return MatchOperand_ParseFail;
2421 }
2422
2423 const MCExpr *ImmVal;
2424 if (getParser().parseExpression(ImmVal))
2425 return MatchOperand_ParseFail;
2426
2427 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2428 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002429 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002430 return MatchOperand_ParseFail;
2431 }
2432
Jim Grosbach57fd2622014-09-23 22:16:02 +00002433 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002434 Operands.push_back(AArch64Operand::CreateShiftExtend(
2435 ShOp, MCE->getValue(), true, S, E, getContext()));
2436 return MatchOperand_Success;
2437}
2438
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002439static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2440 if (FBS[AArch64::HasV8_1aOps])
2441 Str += "ARMv8.1a";
2442 else if (FBS[AArch64::HasV8_2aOps])
2443 Str += "ARMv8.2a";
2444 else
2445 Str += "(unknown)";
2446}
2447
2448void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2449 SMLoc S) {
2450 const uint16_t Op2 = Encoding & 7;
2451 const uint16_t Cm = (Encoding & 0x78) >> 3;
2452 const uint16_t Cn = (Encoding & 0x780) >> 7;
2453 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2454
2455 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2456
2457 Operands.push_back(
2458 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2459 Operands.push_back(
2460 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2461 Operands.push_back(
2462 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2463 Expr = MCConstantExpr::create(Op2, getContext());
2464 Operands.push_back(
2465 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2466}
2467
Tim Northover3b0846e2014-05-24 12:50:23 +00002468/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2469/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2470bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2471 OperandVector &Operands) {
2472 if (Name.find('.') != StringRef::npos)
2473 return TokError("invalid operand");
2474
2475 Mnemonic = Name;
2476 Operands.push_back(
2477 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2478
Rafael Espindola961d4692014-11-11 05:18:41 +00002479 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002480 const AsmToken &Tok = Parser.getTok();
2481 StringRef Op = Tok.getString();
2482 SMLoc S = Tok.getLoc();
2483
Tim Northover3b0846e2014-05-24 12:50:23 +00002484 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002485 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2486 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002487 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002488 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2489 std::string Str("IC " + std::string(IC->Name) + " requires ");
2490 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2491 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002492 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002493 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002494 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002495 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2496 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002497 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002498 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2499 std::string Str("DC " + std::string(DC->Name) + " requires ");
2500 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2501 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002502 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002503 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002504 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002505 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2506 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002507 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002508 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2509 std::string Str("AT " + std::string(AT->Name) + " requires ");
2510 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2511 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002512 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002513 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002514 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002515 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2516 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002517 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002518 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2519 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2520 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2521 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002522 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002523 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002524 }
2525
Tim Northover3b0846e2014-05-24 12:50:23 +00002526 Parser.Lex(); // Eat operand.
2527
2528 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2529 bool HasRegister = false;
2530
2531 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002532 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002533 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2534 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002535 HasRegister = true;
2536 }
2537
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002538 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002539 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002540 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002541 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002542
Nirav Davee833c6c2016-11-08 18:31:04 +00002543 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2544 return true;
2545
Tim Northover3b0846e2014-05-24 12:50:23 +00002546 return false;
2547}
2548
Alex Bradbury58eba092016-11-01 16:32:05 +00002549OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002550AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002551 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002552 const AsmToken &Tok = Parser.getTok();
2553
2554 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002555 if (parseOptionalToken(AsmToken::Hash) ||
2556 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002557 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002558 const MCExpr *ImmVal;
2559 SMLoc ExprLoc = getLoc();
2560 if (getParser().parseExpression(ImmVal))
2561 return MatchOperand_ParseFail;
2562 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2563 if (!MCE) {
2564 Error(ExprLoc, "immediate value expected for barrier operand");
2565 return MatchOperand_ParseFail;
2566 }
2567 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2568 Error(ExprLoc, "barrier operand out of range");
2569 return MatchOperand_ParseFail;
2570 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002571 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2572 Operands.push_back(AArch64Operand::CreateBarrier(
2573 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002574 return MatchOperand_Success;
2575 }
2576
2577 if (Tok.isNot(AsmToken::Identifier)) {
2578 TokError("invalid operand for instruction");
2579 return MatchOperand_ParseFail;
2580 }
2581
Tim Northover3b0846e2014-05-24 12:50:23 +00002582 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002583 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2584 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002585 TokError("'sy' or #imm operand expected");
2586 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002587 } else if (!DB) {
2588 TokError("invalid barrier option name");
2589 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002590 }
2591
Tim Northovere6ae6762016-07-05 21:23:04 +00002592 Operands.push_back(AArch64Operand::CreateBarrier(
2593 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002594 Parser.Lex(); // Consume the option
2595
2596 return MatchOperand_Success;
2597}
2598
Alex Bradbury58eba092016-11-01 16:32:05 +00002599OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002600AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002601 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002602 const AsmToken &Tok = Parser.getTok();
2603
2604 if (Tok.isNot(AsmToken::Identifier))
2605 return MatchOperand_NoMatch;
2606
Tim Northovere6ae6762016-07-05 21:23:04 +00002607 int MRSReg, MSRReg;
2608 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2609 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2610 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2611 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2612 } else
2613 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002614
Tim Northovere6ae6762016-07-05 21:23:04 +00002615 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2616 unsigned PStateImm = -1;
2617 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2618 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002619
Tim Northovere6ae6762016-07-05 21:23:04 +00002620 Operands.push_back(
2621 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2622 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002623 Parser.Lex(); // Eat identifier
2624
2625 return MatchOperand_Success;
2626}
2627
Florian Hahnc4422242017-11-07 13:07:50 +00002628/// tryParseNeonVectorRegister - Parse a vector register operand.
2629bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002630 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002631 if (Parser.getTok().isNot(AsmToken::Identifier))
2632 return true;
2633
2634 SMLoc S = getLoc();
2635 // Check for a vector register specifier first.
2636 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002637 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002638 OperandMatchResultTy Res =
2639 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2640 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002641 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002642
2643 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2644 if (!KindRes)
2645 return true;
2646
2647 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002648 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002649 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2650 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002651
Tim Northover3b0846e2014-05-24 12:50:23 +00002652 // If there was an explicit qualifier, that goes on as a literal text
2653 // operand.
2654 if (!Kind.empty())
2655 Operands.push_back(
2656 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2657
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002658 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2659}
2660
2661OperandMatchResultTy
2662AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002663 SMLoc SIdx = getLoc();
2664 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002665 const MCExpr *ImmVal;
2666 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002667 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002668 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2669 if (!MCE) {
2670 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002671 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002672 }
2673
2674 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002675
Nirav Davee833c6c2016-11-08 18:31:04 +00002676 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002677 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002678
2679 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2680 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002681 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002682 }
2683
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002684 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002685}
2686
Sander de Smalen73937b72018-04-11 07:36:10 +00002687// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002688// optional kind specifier. If it is a register specifier, eat the token
2689// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002690OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002691AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002692 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002693 MCAsmParser &Parser = getParser();
2694 const AsmToken &Tok = Parser.getTok();
2695
Florian Hahn91f11e52017-11-07 16:45:48 +00002696 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002697 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002698
2699 StringRef Name = Tok.getString();
2700 // If there is a kind specifier, it's separated from the register name by
2701 // a '.'.
2702 size_t Start = 0, Next = Name.find('.');
2703 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002704 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002705
2706 if (RegNum) {
2707 if (Next != StringRef::npos) {
2708 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002709 if (!isValidVectorKind(Kind, MatchKind)) {
2710 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002711 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002712 }
2713 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002714 Parser.Lex(); // Eat the register token.
2715
2716 Reg = RegNum;
2717 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002718 }
2719
Sander de Smalen8e607342017-11-15 15:44:43 +00002720 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002721}
2722
Sander de Smalencd6be962017-12-20 11:02:42 +00002723/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2724OperandMatchResultTy
2725AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2726 // Check for a SVE predicate register specifier first.
2727 const SMLoc S = getLoc();
2728 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002729 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002730 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002731 if (Res != MatchOperand_Success)
2732 return Res;
2733
Sander de Smalen73937b72018-04-11 07:36:10 +00002734 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2735 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002736 return MatchOperand_NoMatch;
2737
Sander de Smalen73937b72018-04-11 07:36:10 +00002738 unsigned ElementWidth = KindRes->second;
2739 Operands.push_back(AArch64Operand::CreateVectorReg(
2740 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2741 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002742
Sander de Smalen7868e742018-01-09 11:17:06 +00002743 // Not all predicates are followed by a '/m' or '/z'.
2744 MCAsmParser &Parser = getParser();
2745 if (Parser.getTok().isNot(AsmToken::Slash))
2746 return MatchOperand_Success;
2747
2748 // But when they do they shouldn't have an element type suffix.
2749 if (!Kind.empty()) {
2750 Error(S, "not expecting size suffix");
2751 return MatchOperand_ParseFail;
2752 }
2753
2754 // Add a literal slash as operand
2755 Operands.push_back(
2756 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2757
2758 Parser.Lex(); // Eat the slash.
2759
2760 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002761 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002762 if (Pred != "z" && Pred != "m") {
2763 Error(getLoc(), "expecting 'm' or 'z' predication");
2764 return MatchOperand_ParseFail;
2765 }
2766
2767 // Add zero/merge token.
2768 const char *ZM = Pred == "z" ? "z" : "m";
2769 Operands.push_back(
2770 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2771
2772 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002773 return MatchOperand_Success;
2774}
2775
Sander de Smalen50d87022018-04-19 07:35:08 +00002776/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002777bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002778 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002779 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002780 return false;
2781
Sander de Smalen149916d2018-04-20 07:24:20 +00002782 // Otherwise try for a scalar register.
2783 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
2784 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002785
Sander de Smalen149916d2018-04-20 07:24:20 +00002786 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002787}
2788
2789bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002790 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002791 bool HasELFModifier = false;
2792 AArch64MCExpr::VariantKind RefKind;
2793
Nirav Davee833c6c2016-11-08 18:31:04 +00002794 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002795 HasELFModifier = true;
2796
Nirav Davee833c6c2016-11-08 18:31:04 +00002797 if (Parser.getTok().isNot(AsmToken::Identifier))
2798 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002799
2800 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2801 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2802 .Case("lo12", AArch64MCExpr::VK_LO12)
2803 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2804 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2805 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2806 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2807 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2808 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2809 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2810 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2811 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2812 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2813 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2814 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2815 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2816 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2817 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2818 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2819 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2820 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2821 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2822 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2823 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2824 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2825 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2826 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2827 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2828 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2829 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2830 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2831 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2832 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2833 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2834 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2835 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2836 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002837 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2838 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002839 .Default(AArch64MCExpr::VK_INVALID);
2840
Nirav Davee833c6c2016-11-08 18:31:04 +00002841 if (RefKind == AArch64MCExpr::VK_INVALID)
2842 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002843
2844 Parser.Lex(); // Eat identifier
2845
Nirav Davee833c6c2016-11-08 18:31:04 +00002846 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002847 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002848 }
2849
2850 if (getParser().parseExpression(ImmVal))
2851 return true;
2852
2853 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002854 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002855
2856 return false;
2857}
2858
Sander de Smalen650234b2018-04-12 11:40:52 +00002859template <RegKind VectorKind>
2860OperandMatchResultTy
2861AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
2862 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002863 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00002864 if (!Parser.getTok().is(AsmToken::LCurly))
2865 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002866
2867 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00002868 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00002869 bool NoMatchIsError) {
2870 auto RegTok = Parser.getTok();
2871 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
2872 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002873 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00002874 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002875 llvm_unreachable("Expected a valid vector kind");
2876 }
2877
Sander de Smalen650234b2018-04-12 11:40:52 +00002878 if (RegTok.isNot(AsmToken::Identifier) ||
2879 ParseRes == MatchOperand_ParseFail ||
2880 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
2881 Error(Loc, "vector register expected");
2882 return MatchOperand_ParseFail;
2883 }
2884
2885 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002886 };
2887
Tim Northover3b0846e2014-05-24 12:50:23 +00002888 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00002889 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00002890 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00002891
Tim Northover3b0846e2014-05-24 12:50:23 +00002892 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002893 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002894 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
2895
2896 // Put back the original left bracket if there was no match, so that
2897 // different types of list-operands can be matched (e.g. SVE, Neon).
2898 if (ParseRes == MatchOperand_NoMatch)
2899 Parser.getLexer().UnLex(LCurly);
2900
2901 if (ParseRes != MatchOperand_Success)
2902 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002903
Tim Northover3b0846e2014-05-24 12:50:23 +00002904 int64_t PrevReg = FirstReg;
2905 unsigned Count = 1;
2906
Nirav Davee833c6c2016-11-08 18:31:04 +00002907 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002908 SMLoc Loc = getLoc();
2909 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002910
Sander de Smalen50d87022018-04-19 07:35:08 +00002911 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002912 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2913 if (ParseRes != MatchOperand_Success)
2914 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002915
Tim Northover3b0846e2014-05-24 12:50:23 +00002916 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002917 if (Kind != NextKind) {
2918 Error(Loc, "mismatched register size suffix");
2919 return MatchOperand_ParseFail;
2920 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002921
2922 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2923
2924 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002925 Error(Loc, "invalid number of vectors");
2926 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002927 }
2928
2929 Count += Space;
2930 }
2931 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002932 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002933 SMLoc Loc = getLoc();
2934 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002935 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002936 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2937 if (ParseRes != MatchOperand_Success)
2938 return ParseRes;
2939
Tim Northover3b0846e2014-05-24 12:50:23 +00002940 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002941 if (Kind != NextKind) {
2942 Error(Loc, "mismatched register size suffix");
2943 return MatchOperand_ParseFail;
2944 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002945
2946 // Registers must be incremental (with wraparound at 31)
2947 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00002948 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
2949 Error(Loc, "registers must be sequential");
2950 return MatchOperand_ParseFail;
2951 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002952
2953 PrevReg = Reg;
2954 ++Count;
2955 }
2956 }
2957
Nirav Davee833c6c2016-11-08 18:31:04 +00002958 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00002959 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002960
Sander de Smalen650234b2018-04-12 11:40:52 +00002961 if (Count > 4) {
2962 Error(S, "invalid number of vectors");
2963 return MatchOperand_ParseFail;
2964 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002965
2966 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00002967 unsigned ElementWidth = 0;
2968 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002969 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00002970 std::tie(NumElements, ElementWidth) = *VK;
2971 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002972
2973 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00002974 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
2975 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002976
Sander de Smalen650234b2018-04-12 11:40:52 +00002977 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002978}
2979
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002980/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
2981bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002982 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
2983 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002984 return true;
2985
2986 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2987}
2988
Alex Bradbury58eba092016-11-01 16:32:05 +00002989OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002990AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002991 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002992
Sander de Smalen50d87022018-04-19 07:35:08 +00002993 unsigned RegNum;
2994 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
2995 if (Res != MatchOperand_Success)
2996 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00002997
Nirav Davee833c6c2016-11-08 18:31:04 +00002998 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002999 Operands.push_back(AArch64Operand::CreateReg(
3000 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003001 return MatchOperand_Success;
3002 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003003
Nirav Davee833c6c2016-11-08 18:31:04 +00003004 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003005
Sander de Smalen50d87022018-04-19 07:35:08 +00003006 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003007 Error(getLoc(), "index must be absent or #0");
3008 return MatchOperand_ParseFail;
3009 }
3010
3011 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003012 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003013 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3014 Error(getLoc(), "index must be absent or #0");
3015 return MatchOperand_ParseFail;
3016 }
3017
Sander de Smalen50d87022018-04-19 07:35:08 +00003018 Operands.push_back(AArch64Operand::CreateReg(
3019 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003020 return MatchOperand_Success;
3021}
3022
Sander de Smalen149916d2018-04-20 07:24:20 +00003023template <bool ParseShiftExtend>
3024OperandMatchResultTy
3025AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3026 SMLoc StartLoc = getLoc();
3027
3028 unsigned RegNum;
3029 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3030 if (Res != MatchOperand_Success)
3031 return Res;
3032
3033 // No shift/extend is the default.
3034 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3035 Operands.push_back(AArch64Operand::CreateReg(
3036 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
3037 return MatchOperand_Success;
3038 }
3039
3040 // Eat the comma
3041 getParser().Lex();
3042
3043 // Match the shift
3044 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3045 Res = tryParseOptionalShiftExtend(ExtOpnd);
3046 if (Res != MatchOperand_Success)
3047 return Res;
3048
3049 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
3050 Operands.push_back(AArch64Operand::CreateReg(RegNum, RegKind::Scalar,
3051 StartLoc, Ext->getEndLoc(), getContext(),
3052 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3053 Ext->hasShiftExtendAmount()));
3054
3055 return MatchOperand_Success;
3056}
3057
Sander de Smalen5c625982018-04-13 12:56:14 +00003058bool AArch64AsmParser::parseOptionalMulVl(OperandVector &Operands) {
3059 MCAsmParser &Parser = getParser();
3060
3061 // Some SVE instructions have a decoration after the immediate, i.e.
3062 // "mul vl". We parse them here and add tokens, which must be present in the
3063 // asm string in the tablegen instruction.
3064 if (!Parser.getTok().getString().equals_lower("mul") ||
3065 !Parser.getLexer().peekTok().getString().equals_lower("vl"))
3066 return true;
3067
3068 SMLoc S = getLoc();
3069 Operands.push_back(
3070 AArch64Operand::CreateToken("mul", false, S, getContext()));
3071 Parser.Lex(); // Eat the "mul"
3072
3073 S = getLoc();
3074 Operands.push_back(
3075 AArch64Operand::CreateToken("vl", false, S, getContext()));
3076 Parser.Lex(); // Eat the "vl"
3077
3078 return false;
3079}
3080
Tim Northover3b0846e2014-05-24 12:50:23 +00003081/// parseOperand - Parse a arm instruction operand. For now this parses the
3082/// operand regardless of the mnemonic.
3083bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3084 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003085 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003086
3087 OperandMatchResultTy ResTy =
3088 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3089
Tim Northover3b0846e2014-05-24 12:50:23 +00003090 // Check if the current operand has a custom associated parser, if so, try to
3091 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003092 if (ResTy == MatchOperand_Success)
3093 return false;
3094 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3095 // there was a match, but an error occurred, in which case, just return that
3096 // the operand parsing failed.
3097 if (ResTy == MatchOperand_ParseFail)
3098 return true;
3099
3100 // Nothing custom, so do general case parsing.
3101 SMLoc S, E;
3102 switch (getLexer().getKind()) {
3103 default: {
3104 SMLoc S = getLoc();
3105 const MCExpr *Expr;
3106 if (parseSymbolicImmVal(Expr))
3107 return Error(S, "invalid operand");
3108
3109 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3110 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3111 return false;
3112 }
3113 case AsmToken::LBrac: {
3114 SMLoc Loc = Parser.getTok().getLoc();
3115 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3116 getContext()));
3117 Parser.Lex(); // Eat '['
3118
3119 // There's no comma after a '[', so we can parse the next operand
3120 // immediately.
3121 return parseOperand(Operands, false, false);
3122 }
3123 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003124 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003125 case AsmToken::Identifier: {
3126 // If we're expecting a Condition Code operand, then just parse that.
3127 if (isCondCode)
3128 return parseCondCode(Operands, invertCondCode);
3129
3130 // If it's a register name, parse it.
3131 if (!parseRegister(Operands))
3132 return false;
3133
Sander de Smalen5c625982018-04-13 12:56:14 +00003134 // See if this is a "mul vl" decoration used by SVE instructions.
3135 if (!parseOptionalMulVl(Operands))
3136 return false;
3137
Tim Northover3b0846e2014-05-24 12:50:23 +00003138 // This could be an optional "shift" or "extend" operand.
3139 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3140 // We can only continue if no tokens were eaten.
3141 if (GotShift != MatchOperand_NoMatch)
3142 return GotShift;
3143
3144 // This was not a register so parse other operands that start with an
3145 // identifier (like labels) as expressions and create them as immediates.
3146 const MCExpr *IdVal;
3147 S = getLoc();
3148 if (getParser().parseExpression(IdVal))
3149 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003150 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3151 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3152 return false;
3153 }
3154 case AsmToken::Integer:
3155 case AsmToken::Real:
3156 case AsmToken::Hash: {
3157 // #42 -> immediate.
3158 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003159
3160 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003161
3162 // Parse a negative sign
3163 bool isNegative = false;
3164 if (Parser.getTok().is(AsmToken::Minus)) {
3165 isNegative = true;
3166 // We need to consume this token only when we have a Real, otherwise
3167 // we let parseSymbolicImmVal take care of it
3168 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3169 Parser.Lex();
3170 }
3171
3172 // The only Real that should come through here is a literal #0.0 for
3173 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3174 // so convert the value.
3175 const AsmToken &Tok = Parser.getTok();
3176 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003177 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003178 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3179 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3180 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3181 Mnemonic != "fcmlt")
3182 return TokError("unexpected floating point literal");
3183 else if (IntVal != 0 || isNegative)
3184 return TokError("expected floating-point constant #0.0");
3185 Parser.Lex(); // Eat the token.
3186
3187 Operands.push_back(
3188 AArch64Operand::CreateToken("#0", false, S, getContext()));
3189 Operands.push_back(
3190 AArch64Operand::CreateToken(".0", false, S, getContext()));
3191 return false;
3192 }
3193
3194 const MCExpr *ImmVal;
3195 if (parseSymbolicImmVal(ImmVal))
3196 return true;
3197
3198 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3199 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3200 return false;
3201 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003202 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003203 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003204 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003205 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003206 Parser.Lex(); // Eat '='
3207 const MCExpr *SubExprVal;
3208 if (getParser().parseExpression(SubExprVal))
3209 return true;
3210
David Peixottoae5ba762014-07-18 16:05:14 +00003211 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003212 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003213 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003214
3215 bool IsXReg =
3216 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3217 Operands[1]->getReg());
3218
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003219 MCContext& Ctx = getContext();
3220 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3221 // 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 +00003222 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003223 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3224 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3225 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3226 ShiftAmt += 16;
3227 Imm >>= 16;
3228 }
3229 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3230 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3231 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003232 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003233 if (ShiftAmt)
3234 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3235 ShiftAmt, true, S, E, Ctx));
3236 return false;
3237 }
David Peixottoae5ba762014-07-18 16:05:14 +00003238 APInt Simm = APInt(64, Imm << ShiftAmt);
3239 // check if the immediate is an unsigned or signed 32-bit int for W regs
3240 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3241 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003242 }
3243 // 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 +00003244 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003245 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003246 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3247 return false;
3248 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003249 }
3250}
3251
3252/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3253/// operands.
3254bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3255 StringRef Name, SMLoc NameLoc,
3256 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003257 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003258 Name = StringSwitch<StringRef>(Name.lower())
3259 .Case("beq", "b.eq")
3260 .Case("bne", "b.ne")
3261 .Case("bhs", "b.hs")
3262 .Case("bcs", "b.cs")
3263 .Case("blo", "b.lo")
3264 .Case("bcc", "b.cc")
3265 .Case("bmi", "b.mi")
3266 .Case("bpl", "b.pl")
3267 .Case("bvs", "b.vs")
3268 .Case("bvc", "b.vc")
3269 .Case("bhi", "b.hi")
3270 .Case("bls", "b.ls")
3271 .Case("bge", "b.ge")
3272 .Case("blt", "b.lt")
3273 .Case("bgt", "b.gt")
3274 .Case("ble", "b.le")
3275 .Case("bal", "b.al")
3276 .Case("bnv", "b.nv")
3277 .Default(Name);
3278
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003279 // First check for the AArch64-specific .req directive.
3280 if (Parser.getTok().is(AsmToken::Identifier) &&
3281 Parser.getTok().getIdentifier() == ".req") {
3282 parseDirectiveReq(Name, NameLoc);
3283 // We always return 'error' for this, as we're done with this
3284 // statement and don't need to match the 'instruction."
3285 return true;
3286 }
3287
Tim Northover3b0846e2014-05-24 12:50:23 +00003288 // Create the leading tokens for the mnemonic, split by '.' characters.
3289 size_t Start = 0, Next = Name.find('.');
3290 StringRef Head = Name.slice(Start, Next);
3291
3292 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003293 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3294 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003295
3296 Operands.push_back(
3297 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3298 Mnemonic = Head;
3299
3300 // Handle condition codes for a branch mnemonic
3301 if (Head == "b" && Next != StringRef::npos) {
3302 Start = Next;
3303 Next = Name.find('.', Start + 1);
3304 Head = Name.slice(Start + 1, Next);
3305
3306 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3307 (Head.data() - Name.data()));
3308 AArch64CC::CondCode CC = parseCondCodeString(Head);
3309 if (CC == AArch64CC::Invalid)
3310 return Error(SuffixLoc, "invalid condition code");
3311 Operands.push_back(
3312 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3313 Operands.push_back(
3314 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3315 }
3316
3317 // Add the remaining tokens in the mnemonic.
3318 while (Next != StringRef::npos) {
3319 Start = Next;
3320 Next = Name.find('.', Start + 1);
3321 Head = Name.slice(Start, Next);
3322 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3323 (Head.data() - Name.data()) + 1);
3324 Operands.push_back(
3325 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3326 }
3327
3328 // Conditional compare instructions have a Condition Code operand, which needs
3329 // to be parsed and an immediate operand created.
3330 bool condCodeFourthOperand =
3331 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3332 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3333 Head == "csinc" || Head == "csinv" || Head == "csneg");
3334
3335 // These instructions are aliases to some of the conditional select
3336 // instructions. However, the condition code is inverted in the aliased
3337 // instruction.
3338 //
3339 // FIXME: Is this the correct way to handle these? Or should the parser
3340 // generate the aliased instructions directly?
3341 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3342 bool condCodeThirdOperand =
3343 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3344
3345 // Read the remaining operands.
3346 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3347 // Read the first operand.
3348 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003349 return true;
3350 }
3351
3352 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003353 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003354 // Parse and remember the operand.
3355 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3356 (N == 3 && condCodeThirdOperand) ||
3357 (N == 2 && condCodeSecondOperand),
3358 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003359 return true;
3360 }
3361
3362 // After successfully parsing some operands there are two special cases to
3363 // consider (i.e. notional operands not separated by commas). Both are due
3364 // to memory specifiers:
3365 // + An RBrac will end an address for load/store/prefetch
3366 // + An '!' will indicate a pre-indexed operation.
3367 //
3368 // It's someone else's responsibility to make sure these tokens are sane
3369 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003370
Nirav Davee833c6c2016-11-08 18:31:04 +00003371 SMLoc RLoc = Parser.getTok().getLoc();
3372 if (parseOptionalToken(AsmToken::RBrac))
3373 Operands.push_back(
3374 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3375 SMLoc ELoc = Parser.getTok().getLoc();
3376 if (parseOptionalToken(AsmToken::Exclaim))
3377 Operands.push_back(
3378 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003379
3380 ++N;
3381 }
3382 }
3383
Nirav Davee833c6c2016-11-08 18:31:04 +00003384 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3385 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003386
Tim Northover3b0846e2014-05-24 12:50:23 +00003387 return false;
3388}
3389
3390// FIXME: This entire function is a giant hack to provide us with decent
3391// operand range validation/diagnostics until TableGen/MC can be extended
3392// to support autogeneration of this kind of validation.
3393bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3394 SmallVectorImpl<SMLoc> &Loc) {
3395 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3396 // Check for indexed addressing modes w/ the base register being the
3397 // same as a destination/source register or pair load where
3398 // the Rt == Rt2. All of those are undefined behaviour.
3399 switch (Inst.getOpcode()) {
3400 case AArch64::LDPSWpre:
3401 case AArch64::LDPWpost:
3402 case AArch64::LDPWpre:
3403 case AArch64::LDPXpost:
3404 case AArch64::LDPXpre: {
3405 unsigned Rt = Inst.getOperand(1).getReg();
3406 unsigned Rt2 = Inst.getOperand(2).getReg();
3407 unsigned Rn = Inst.getOperand(3).getReg();
3408 if (RI->isSubRegisterEq(Rn, Rt))
3409 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3410 "is also a destination");
3411 if (RI->isSubRegisterEq(Rn, Rt2))
3412 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3413 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003414 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003415 }
3416 case AArch64::LDPDi:
3417 case AArch64::LDPQi:
3418 case AArch64::LDPSi:
3419 case AArch64::LDPSWi:
3420 case AArch64::LDPWi:
3421 case AArch64::LDPXi: {
3422 unsigned Rt = Inst.getOperand(0).getReg();
3423 unsigned Rt2 = Inst.getOperand(1).getReg();
3424 if (Rt == Rt2)
3425 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3426 break;
3427 }
3428 case AArch64::LDPDpost:
3429 case AArch64::LDPDpre:
3430 case AArch64::LDPQpost:
3431 case AArch64::LDPQpre:
3432 case AArch64::LDPSpost:
3433 case AArch64::LDPSpre:
3434 case AArch64::LDPSWpost: {
3435 unsigned Rt = Inst.getOperand(1).getReg();
3436 unsigned Rt2 = Inst.getOperand(2).getReg();
3437 if (Rt == Rt2)
3438 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3439 break;
3440 }
3441 case AArch64::STPDpost:
3442 case AArch64::STPDpre:
3443 case AArch64::STPQpost:
3444 case AArch64::STPQpre:
3445 case AArch64::STPSpost:
3446 case AArch64::STPSpre:
3447 case AArch64::STPWpost:
3448 case AArch64::STPWpre:
3449 case AArch64::STPXpost:
3450 case AArch64::STPXpre: {
3451 unsigned Rt = Inst.getOperand(1).getReg();
3452 unsigned Rt2 = Inst.getOperand(2).getReg();
3453 unsigned Rn = Inst.getOperand(3).getReg();
3454 if (RI->isSubRegisterEq(Rn, Rt))
3455 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3456 "is also a source");
3457 if (RI->isSubRegisterEq(Rn, Rt2))
3458 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3459 "is also a source");
3460 break;
3461 }
3462 case AArch64::LDRBBpre:
3463 case AArch64::LDRBpre:
3464 case AArch64::LDRHHpre:
3465 case AArch64::LDRHpre:
3466 case AArch64::LDRSBWpre:
3467 case AArch64::LDRSBXpre:
3468 case AArch64::LDRSHWpre:
3469 case AArch64::LDRSHXpre:
3470 case AArch64::LDRSWpre:
3471 case AArch64::LDRWpre:
3472 case AArch64::LDRXpre:
3473 case AArch64::LDRBBpost:
3474 case AArch64::LDRBpost:
3475 case AArch64::LDRHHpost:
3476 case AArch64::LDRHpost:
3477 case AArch64::LDRSBWpost:
3478 case AArch64::LDRSBXpost:
3479 case AArch64::LDRSHWpost:
3480 case AArch64::LDRSHXpost:
3481 case AArch64::LDRSWpost:
3482 case AArch64::LDRWpost:
3483 case AArch64::LDRXpost: {
3484 unsigned Rt = Inst.getOperand(1).getReg();
3485 unsigned Rn = Inst.getOperand(2).getReg();
3486 if (RI->isSubRegisterEq(Rn, Rt))
3487 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3488 "is also a source");
3489 break;
3490 }
3491 case AArch64::STRBBpost:
3492 case AArch64::STRBpost:
3493 case AArch64::STRHHpost:
3494 case AArch64::STRHpost:
3495 case AArch64::STRWpost:
3496 case AArch64::STRXpost:
3497 case AArch64::STRBBpre:
3498 case AArch64::STRBpre:
3499 case AArch64::STRHHpre:
3500 case AArch64::STRHpre:
3501 case AArch64::STRWpre:
3502 case AArch64::STRXpre: {
3503 unsigned Rt = Inst.getOperand(1).getReg();
3504 unsigned Rn = Inst.getOperand(2).getReg();
3505 if (RI->isSubRegisterEq(Rn, Rt))
3506 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3507 "is also a source");
3508 break;
3509 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003510 case AArch64::STXRB:
3511 case AArch64::STXRH:
3512 case AArch64::STXRW:
3513 case AArch64::STXRX:
3514 case AArch64::STLXRB:
3515 case AArch64::STLXRH:
3516 case AArch64::STLXRW:
3517 case AArch64::STLXRX: {
3518 unsigned Rs = Inst.getOperand(0).getReg();
3519 unsigned Rt = Inst.getOperand(1).getReg();
3520 unsigned Rn = Inst.getOperand(2).getReg();
3521 if (RI->isSubRegisterEq(Rt, Rs) ||
3522 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3523 return Error(Loc[0],
3524 "unpredictable STXR instruction, status is also a source");
3525 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003526 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003527 case AArch64::STXPW:
3528 case AArch64::STXPX:
3529 case AArch64::STLXPW:
3530 case AArch64::STLXPX: {
3531 unsigned Rs = Inst.getOperand(0).getReg();
3532 unsigned Rt1 = Inst.getOperand(1).getReg();
3533 unsigned Rt2 = Inst.getOperand(2).getReg();
3534 unsigned Rn = Inst.getOperand(3).getReg();
3535 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3536 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3537 return Error(Loc[0],
3538 "unpredictable STXP instruction, status is also a source");
3539 break;
3540 }
3541 }
3542
Tim Northover3b0846e2014-05-24 12:50:23 +00003543
3544 // Now check immediate ranges. Separate from the above as there is overlap
3545 // in the instructions being checked and this keeps the nested conditionals
3546 // to a minimum.
3547 switch (Inst.getOpcode()) {
3548 case AArch64::ADDSWri:
3549 case AArch64::ADDSXri:
3550 case AArch64::ADDWri:
3551 case AArch64::ADDXri:
3552 case AArch64::SUBSWri:
3553 case AArch64::SUBSXri:
3554 case AArch64::SUBWri:
3555 case AArch64::SUBXri: {
3556 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3557 // some slight duplication here.
3558 if (Inst.getOperand(2).isExpr()) {
3559 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3560 AArch64MCExpr::VariantKind ELFRefKind;
3561 MCSymbolRefExpr::VariantKind DarwinRefKind;
3562 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003563 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3564
3565 // Only allow these with ADDXri.
3566 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3567 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3568 Inst.getOpcode() == AArch64::ADDXri)
3569 return false;
3570
3571 // Only allow these with ADDXri/ADDWri
3572 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3573 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3574 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3575 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3576 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3577 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3578 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003579 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3580 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3581 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003582 (Inst.getOpcode() == AArch64::ADDXri ||
3583 Inst.getOpcode() == AArch64::ADDWri))
3584 return false;
3585
3586 // Don't allow symbol refs in the immediate field otherwise
3587 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3588 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3589 // 'cmp w0, 'borked')
3590 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003591 }
Diana Picusc93518d2016-10-11 09:17:47 +00003592 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003593 }
3594 return false;
3595 }
3596 default:
3597 return false;
3598 }
3599}
3600
Craig Topper05515562017-10-26 06:46:41 +00003601static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3602 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003603
3604bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3605 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003606 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003607 case Match_InvalidTiedOperand:
3608 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003609 case Match_MissingFeature:
3610 return Error(Loc,
3611 "instruction requires a CPU feature not currently enabled");
3612 case Match_InvalidOperand:
3613 return Error(Loc, "invalid operand for instruction");
3614 case Match_InvalidSuffix:
3615 return Error(Loc, "invalid type suffix for instruction");
3616 case Match_InvalidCondCode:
3617 return Error(Loc, "expected AArch64 condition code");
3618 case Match_AddSubRegExtendSmall:
3619 return Error(Loc,
3620 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3621 case Match_AddSubRegExtendLarge:
3622 return Error(Loc,
3623 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3624 case Match_AddSubSecondSource:
3625 return Error(Loc,
3626 "expected compatible register, symbol or integer in range [0, 4095]");
3627 case Match_LogicalSecondSource:
3628 return Error(Loc, "expected compatible register or logical immediate");
3629 case Match_InvalidMovImm32Shift:
3630 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3631 case Match_InvalidMovImm64Shift:
3632 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3633 case Match_AddSubRegShift32:
3634 return Error(Loc,
3635 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3636 case Match_AddSubRegShift64:
3637 return Error(Loc,
3638 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3639 case Match_InvalidFPImm:
3640 return Error(Loc,
3641 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003642 case Match_InvalidMemoryIndexedSImm6:
3643 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003644 case Match_InvalidMemoryIndexedSImm5:
3645 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003646 case Match_InvalidMemoryIndexed1SImm4:
3647 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003648 case Match_InvalidMemoryIndexed2SImm4:
3649 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003650 case Match_InvalidMemoryIndexed3SImm4:
3651 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003652 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00003653 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00003654 case Match_InvalidMemoryIndexed16SImm4:
3655 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00003656 case Match_InvalidMemoryIndexed1SImm6:
3657 return Error(Loc, "index must be an integer in range [-32, 31].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003658 case Match_InvalidMemoryIndexedSImm9:
3659 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00003660 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00003661 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003662 case Match_InvalidMemoryIndexed4SImm7:
3663 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3664 case Match_InvalidMemoryIndexed8SImm7:
3665 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3666 case Match_InvalidMemoryIndexed16SImm7:
3667 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00003668 case Match_InvalidMemoryIndexed8UImm5:
3669 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
3670 case Match_InvalidMemoryIndexed4UImm5:
3671 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
3672 case Match_InvalidMemoryIndexed2UImm5:
3673 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00003674 case Match_InvalidMemoryIndexed8UImm6:
3675 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
3676 case Match_InvalidMemoryIndexed4UImm6:
3677 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
3678 case Match_InvalidMemoryIndexed2UImm6:
3679 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
3680 case Match_InvalidMemoryIndexed1UImm6:
3681 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003682 case Match_InvalidMemoryWExtend8:
3683 return Error(Loc,
3684 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3685 case Match_InvalidMemoryWExtend16:
3686 return Error(Loc,
3687 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3688 case Match_InvalidMemoryWExtend32:
3689 return Error(Loc,
3690 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3691 case Match_InvalidMemoryWExtend64:
3692 return Error(Loc,
3693 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3694 case Match_InvalidMemoryWExtend128:
3695 return Error(Loc,
3696 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3697 case Match_InvalidMemoryXExtend8:
3698 return Error(Loc,
3699 "expected 'lsl' or 'sxtx' with optional shift of #0");
3700 case Match_InvalidMemoryXExtend16:
3701 return Error(Loc,
3702 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3703 case Match_InvalidMemoryXExtend32:
3704 return Error(Loc,
3705 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3706 case Match_InvalidMemoryXExtend64:
3707 return Error(Loc,
3708 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3709 case Match_InvalidMemoryXExtend128:
3710 return Error(Loc,
3711 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3712 case Match_InvalidMemoryIndexed1:
3713 return Error(Loc, "index must be an integer in range [0, 4095].");
3714 case Match_InvalidMemoryIndexed2:
3715 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3716 case Match_InvalidMemoryIndexed4:
3717 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3718 case Match_InvalidMemoryIndexed8:
3719 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3720 case Match_InvalidMemoryIndexed16:
3721 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003722 case Match_InvalidImm0_1:
3723 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003724 case Match_InvalidImm0_7:
3725 return Error(Loc, "immediate must be an integer in range [0, 7].");
3726 case Match_InvalidImm0_15:
3727 return Error(Loc, "immediate must be an integer in range [0, 15].");
3728 case Match_InvalidImm0_31:
3729 return Error(Loc, "immediate must be an integer in range [0, 31].");
3730 case Match_InvalidImm0_63:
3731 return Error(Loc, "immediate must be an integer in range [0, 63].");
3732 case Match_InvalidImm0_127:
3733 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003734 case Match_InvalidImm0_255:
3735 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003736 case Match_InvalidImm0_65535:
3737 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3738 case Match_InvalidImm1_8:
3739 return Error(Loc, "immediate must be an integer in range [1, 8].");
3740 case Match_InvalidImm1_16:
3741 return Error(Loc, "immediate must be an integer in range [1, 16].");
3742 case Match_InvalidImm1_32:
3743 return Error(Loc, "immediate must be an integer in range [1, 32].");
3744 case Match_InvalidImm1_64:
3745 return Error(Loc, "immediate must be an integer in range [1, 64].");
3746 case Match_InvalidIndex1:
3747 return Error(Loc, "expected lane specifier '[1]'");
3748 case Match_InvalidIndexB:
3749 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3750 case Match_InvalidIndexH:
3751 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3752 case Match_InvalidIndexS:
3753 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3754 case Match_InvalidIndexD:
3755 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3756 case Match_InvalidLabel:
3757 return Error(Loc, "expected label or encodable integer pc offset");
3758 case Match_MRS:
3759 return Error(Loc, "expected readable system register");
3760 case Match_MSR:
3761 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003762 case Match_InvalidComplexRotationEven:
3763 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3764 case Match_InvalidComplexRotationOdd:
3765 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003766 case Match_MnemonicFail: {
3767 std::string Suggestion = AArch64MnemonicSpellCheck(
3768 ((AArch64Operand &)*Operands[0]).getToken(),
3769 ComputeAvailableFeatures(STI->getFeatureBits()));
3770 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3771 }
Sander de Smalen367694b2018-04-20 08:54:49 +00003772 case Match_InvalidGPR64shifted8:
3773 return Error(Loc, "register must be x0..x30 or xzr, without shift");
3774 case Match_InvalidGPR64shifted16:
3775 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
3776 case Match_InvalidGPR64shifted32:
3777 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
3778 case Match_InvalidGPR64shifted64:
3779 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
3780 case Match_InvalidGPR64NoXZRshifted8:
3781 return Error(Loc, "register must be x0..x30 without shift");
3782 case Match_InvalidGPR64NoXZRshifted16:
3783 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
3784 case Match_InvalidGPR64NoXZRshifted32:
3785 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
3786 case Match_InvalidGPR64NoXZRshifted64:
3787 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00003788 case Match_InvalidZPR32UXTW8:
3789 case Match_InvalidZPR32SXTW8:
3790 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
3791 case Match_InvalidZPR32UXTW16:
3792 case Match_InvalidZPR32SXTW16:
3793 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
3794 case Match_InvalidZPR32UXTW32:
3795 case Match_InvalidZPR32SXTW32:
3796 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
3797 case Match_InvalidZPR32UXTW64:
3798 case Match_InvalidZPR32SXTW64:
3799 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
3800 case Match_InvalidZPR64UXTW8:
3801 case Match_InvalidZPR64SXTW8:
3802 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
3803 case Match_InvalidZPR64UXTW16:
3804 case Match_InvalidZPR64SXTW16:
3805 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
3806 case Match_InvalidZPR64UXTW32:
3807 case Match_InvalidZPR64SXTW32:
3808 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
3809 case Match_InvalidZPR64UXTW64:
3810 case Match_InvalidZPR64SXTW64:
3811 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
3812 case Match_InvalidZPR64LSL8:
3813 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
3814 case Match_InvalidZPR64LSL16:
3815 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
3816 case Match_InvalidZPR64LSL32:
3817 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
3818 case Match_InvalidZPR64LSL64:
3819 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003820 case Match_InvalidSVEPattern:
3821 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003822 case Match_InvalidSVEPredicateAnyReg:
3823 case Match_InvalidSVEPredicateBReg:
3824 case Match_InvalidSVEPredicateHReg:
3825 case Match_InvalidSVEPredicateSReg:
3826 case Match_InvalidSVEPredicateDReg:
3827 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003828 case Match_InvalidSVEPredicate3bAnyReg:
3829 case Match_InvalidSVEPredicate3bBReg:
3830 case Match_InvalidSVEPredicate3bHReg:
3831 case Match_InvalidSVEPredicate3bSReg:
3832 case Match_InvalidSVEPredicate3bDReg:
3833 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003834 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003835 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003836 }
3837}
3838
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003839static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003840
3841bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3842 OperandVector &Operands,
3843 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003844 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003845 bool MatchingInlineAsm) {
3846 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003847 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3848 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003849
David Blaikie960ea3f2014-06-08 16:18:35 +00003850 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003851 unsigned NumOperands = Operands.size();
3852
3853 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003854 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3855 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003856 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003857 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003858 if (Op3CE) {
3859 uint64_t Op3Val = Op3CE->getValue();
3860 uint64_t NewOp3Val = 0;
3861 uint64_t NewOp4Val = 0;
3862 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003863 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003864 NewOp3Val = (32 - Op3Val) & 0x1f;
3865 NewOp4Val = 31 - Op3Val;
3866 } else {
3867 NewOp3Val = (64 - Op3Val) & 0x3f;
3868 NewOp4Val = 63 - Op3Val;
3869 }
3870
Jim Grosbach13760bd2015-05-30 01:25:56 +00003871 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3872 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003873
3874 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003875 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003876 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003877 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3878 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3879 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003880 }
3881 }
Tim Northover03b99f62015-04-30 18:28:58 +00003882 } else if (NumOperands == 4 && Tok == "bfc") {
3883 // FIXME: Horrible hack to handle BFC->BFM alias.
3884 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3885 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3886 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3887
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003888 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003889 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3890 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3891
3892 if (LSBCE && WidthCE) {
3893 uint64_t LSB = LSBCE->getValue();
3894 uint64_t Width = WidthCE->getValue();
3895
3896 uint64_t RegWidth = 0;
3897 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3898 Op1.getReg()))
3899 RegWidth = 64;
3900 else
3901 RegWidth = 32;
3902
3903 if (LSB >= RegWidth)
3904 return Error(LSBOp.getStartLoc(),
3905 "expected integer in range [0, 31]");
3906 if (Width < 1 || Width > RegWidth)
3907 return Error(WidthOp.getStartLoc(),
3908 "expected integer in range [1, 32]");
3909
3910 uint64_t ImmR = 0;
3911 if (RegWidth == 32)
3912 ImmR = (32 - LSB) & 0x1f;
3913 else
3914 ImmR = (64 - LSB) & 0x3f;
3915
3916 uint64_t ImmS = Width - 1;
3917
3918 if (ImmR != 0 && ImmS >= ImmR)
3919 return Error(WidthOp.getStartLoc(),
3920 "requested insert overflows register");
3921
Jim Grosbach13760bd2015-05-30 01:25:56 +00003922 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3923 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003924 Operands[0] = AArch64Operand::CreateToken(
3925 "bfm", false, Op.getStartLoc(), getContext());
3926 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003927 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3928 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003929 Operands[3] = AArch64Operand::CreateImm(
3930 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3931 Operands.emplace_back(
3932 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3933 WidthOp.getEndLoc(), getContext()));
3934 }
3935 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003936 } else if (NumOperands == 5) {
3937 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3938 // UBFIZ -> UBFM aliases.
3939 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003940 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3941 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3942 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003943
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003944 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003945 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3946 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003947
3948 if (Op3CE && Op4CE) {
3949 uint64_t Op3Val = Op3CE->getValue();
3950 uint64_t Op4Val = Op4CE->getValue();
3951
3952 uint64_t RegWidth = 0;
3953 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003954 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003955 RegWidth = 64;
3956 else
3957 RegWidth = 32;
3958
3959 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003960 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003961 "expected integer in range [0, 31]");
3962 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003963 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003964 "expected integer in range [1, 32]");
3965
3966 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003967 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003968 NewOp3Val = (32 - Op3Val) & 0x1f;
3969 else
3970 NewOp3Val = (64 - Op3Val) & 0x3f;
3971
3972 uint64_t NewOp4Val = Op4Val - 1;
3973
3974 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003975 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003976 "requested insert overflows register");
3977
3978 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003979 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003980 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003981 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003982 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003983 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003984 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003985 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003986 if (Tok == "bfi")
3987 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003988 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003989 else if (Tok == "sbfiz")
3990 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003991 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003992 else if (Tok == "ubfiz")
3993 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003994 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003995 else
3996 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003997 }
3998 }
3999
4000 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4001 // UBFX -> UBFM aliases.
4002 } else if (NumOperands == 5 &&
4003 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004004 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4005 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4006 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004007
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004008 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004009 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4010 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004011
4012 if (Op3CE && Op4CE) {
4013 uint64_t Op3Val = Op3CE->getValue();
4014 uint64_t Op4Val = Op4CE->getValue();
4015
4016 uint64_t RegWidth = 0;
4017 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004018 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004019 RegWidth = 64;
4020 else
4021 RegWidth = 32;
4022
4023 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004024 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004025 "expected integer in range [0, 31]");
4026 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004027 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004028 "expected integer in range [1, 32]");
4029
4030 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4031
4032 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004033 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004034 "requested extract overflows register");
4035
4036 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004037 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004038 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004039 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004040 if (Tok == "bfxil")
4041 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004042 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004043 else if (Tok == "sbfx")
4044 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004045 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004046 else if (Tok == "ubfx")
4047 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004048 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004049 else
4050 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004051 }
4052 }
4053 }
4054 }
Tim Northover9097a072017-12-18 10:36:00 +00004055
4056 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4057 // instruction for FP registers correctly in some rare circumstances. Convert
4058 // it to a safe instruction and warn (because silently changing someone's
4059 // assembly is rude).
4060 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4061 NumOperands == 4 && Tok == "movi") {
4062 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4063 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4064 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4065 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4066 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4067 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4068 if (Suffix.lower() == ".2d" &&
4069 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4070 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4071 " correctly on this CPU, converting to equivalent movi.16b");
4072 // Switch the suffix to .16b.
4073 unsigned Idx = Op1.isToken() ? 1 : 2;
4074 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4075 getContext());
4076 }
4077 }
4078 }
4079
Tim Northover3b0846e2014-05-24 12:50:23 +00004080 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4081 // InstAlias can't quite handle this since the reg classes aren't
4082 // subclasses.
4083 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4084 // The source register can be Wn here, but the matcher expects a
4085 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004086 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004087 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004088 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004089 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4090 Op.getStartLoc(), Op.getEndLoc(),
4091 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004092 }
4093 }
4094 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4095 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004096 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004097 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004098 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004099 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004100 // The source register can be Wn here, but the matcher expects a
4101 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004102 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004103 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004104 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004105 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4106 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004107 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004108 }
4109 }
4110 }
4111 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4112 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004113 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004114 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004115 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004116 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004117 // The source register can be Wn here, but the matcher expects a
4118 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004119 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004120 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004121 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004122 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4123 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004124 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004125 }
4126 }
4127 }
4128
Tim Northover3b0846e2014-05-24 12:50:23 +00004129 MCInst Inst;
4130 // First try to match against the secondary set of tables containing the
4131 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4132 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004133 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004134
4135 // If that fails, try against the alternate table containing long-form NEON:
4136 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004137 if (MatchResult != Match_Success) {
4138 // But first, save the short-form match result: we can use it in case the
4139 // long-form match also fails.
4140 auto ShortFormNEONErrorInfo = ErrorInfo;
4141 auto ShortFormNEONMatchResult = MatchResult;
4142
Tim Northover3b0846e2014-05-24 12:50:23 +00004143 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004144 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004145
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004146 // Now, both matches failed, and the long-form match failed on the mnemonic
4147 // suffix token operand. The short-form match failure is probably more
4148 // relevant: use it instead.
4149 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004150 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004151 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4152 MatchResult = ShortFormNEONMatchResult;
4153 ErrorInfo = ShortFormNEONErrorInfo;
4154 }
4155 }
4156
Tim Northover3b0846e2014-05-24 12:50:23 +00004157 switch (MatchResult) {
4158 case Match_Success: {
4159 // Perform range checking and other semantic validations
4160 SmallVector<SMLoc, 8> OperandLocs;
4161 NumOperands = Operands.size();
4162 for (unsigned i = 1; i < NumOperands; ++i)
4163 OperandLocs.push_back(Operands[i]->getStartLoc());
4164 if (validateInstruction(Inst, OperandLocs))
4165 return true;
4166
4167 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004168 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004169 return false;
4170 }
4171 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004172 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004173 // Special case the error message for the very common case where only
4174 // a single subtarget feature is missing (neon, e.g.).
4175 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004176 uint64_t Mask = 1;
4177 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4178 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004179 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004180 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004181 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004182 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004183 }
4184 return Error(IDLoc, Msg);
4185 }
4186 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004187 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004188 case Match_InvalidOperand: {
4189 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004190
Tim Northover26bb14e2014-08-18 11:49:42 +00004191 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004192 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004193 return Error(IDLoc, "too few operands for instruction",
4194 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004195
David Blaikie960ea3f2014-06-08 16:18:35 +00004196 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004197 if (ErrorLoc == SMLoc())
4198 ErrorLoc = IDLoc;
4199 }
4200 // If the match failed on a suffix token operand, tweak the diagnostic
4201 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004202 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4203 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004204 MatchResult = Match_InvalidSuffix;
4205
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004206 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004207 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004208 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004209 case Match_InvalidMemoryIndexed1:
4210 case Match_InvalidMemoryIndexed2:
4211 case Match_InvalidMemoryIndexed4:
4212 case Match_InvalidMemoryIndexed8:
4213 case Match_InvalidMemoryIndexed16:
4214 case Match_InvalidCondCode:
4215 case Match_AddSubRegExtendSmall:
4216 case Match_AddSubRegExtendLarge:
4217 case Match_AddSubSecondSource:
4218 case Match_LogicalSecondSource:
4219 case Match_AddSubRegShift32:
4220 case Match_AddSubRegShift64:
4221 case Match_InvalidMovImm32Shift:
4222 case Match_InvalidMovImm64Shift:
4223 case Match_InvalidFPImm:
4224 case Match_InvalidMemoryWExtend8:
4225 case Match_InvalidMemoryWExtend16:
4226 case Match_InvalidMemoryWExtend32:
4227 case Match_InvalidMemoryWExtend64:
4228 case Match_InvalidMemoryWExtend128:
4229 case Match_InvalidMemoryXExtend8:
4230 case Match_InvalidMemoryXExtend16:
4231 case Match_InvalidMemoryXExtend32:
4232 case Match_InvalidMemoryXExtend64:
4233 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004234 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004235 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004236 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004237 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004238 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004239 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004240 case Match_InvalidMemoryIndexed4SImm7:
4241 case Match_InvalidMemoryIndexed8SImm7:
4242 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004243 case Match_InvalidMemoryIndexed8UImm5:
4244 case Match_InvalidMemoryIndexed4UImm5:
4245 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004246 case Match_InvalidMemoryIndexed1UImm6:
4247 case Match_InvalidMemoryIndexed2UImm6:
4248 case Match_InvalidMemoryIndexed4UImm6:
4249 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004250 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004251 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004252 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004253 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004254 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004255 case Match_InvalidImm0_7:
4256 case Match_InvalidImm0_15:
4257 case Match_InvalidImm0_31:
4258 case Match_InvalidImm0_63:
4259 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004260 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004261 case Match_InvalidImm0_65535:
4262 case Match_InvalidImm1_8:
4263 case Match_InvalidImm1_16:
4264 case Match_InvalidImm1_32:
4265 case Match_InvalidImm1_64:
4266 case Match_InvalidIndex1:
4267 case Match_InvalidIndexB:
4268 case Match_InvalidIndexH:
4269 case Match_InvalidIndexS:
4270 case Match_InvalidIndexD:
4271 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004272 case Match_InvalidComplexRotationEven:
4273 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004274 case Match_InvalidGPR64shifted8:
4275 case Match_InvalidGPR64shifted16:
4276 case Match_InvalidGPR64shifted32:
4277 case Match_InvalidGPR64shifted64:
4278 case Match_InvalidGPR64NoXZRshifted8:
4279 case Match_InvalidGPR64NoXZRshifted16:
4280 case Match_InvalidGPR64NoXZRshifted32:
4281 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004282 case Match_InvalidZPR32UXTW8:
4283 case Match_InvalidZPR32UXTW16:
4284 case Match_InvalidZPR32UXTW32:
4285 case Match_InvalidZPR32UXTW64:
4286 case Match_InvalidZPR32SXTW8:
4287 case Match_InvalidZPR32SXTW16:
4288 case Match_InvalidZPR32SXTW32:
4289 case Match_InvalidZPR32SXTW64:
4290 case Match_InvalidZPR64UXTW8:
4291 case Match_InvalidZPR64SXTW8:
4292 case Match_InvalidZPR64UXTW16:
4293 case Match_InvalidZPR64SXTW16:
4294 case Match_InvalidZPR64UXTW32:
4295 case Match_InvalidZPR64SXTW32:
4296 case Match_InvalidZPR64UXTW64:
4297 case Match_InvalidZPR64SXTW64:
4298 case Match_InvalidZPR64LSL8:
4299 case Match_InvalidZPR64LSL16:
4300 case Match_InvalidZPR64LSL32:
4301 case Match_InvalidZPR64LSL64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004302 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004303 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004304 case Match_InvalidSVEPredicateBReg:
4305 case Match_InvalidSVEPredicateHReg:
4306 case Match_InvalidSVEPredicateSReg:
4307 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004308 case Match_InvalidSVEPredicate3bAnyReg:
4309 case Match_InvalidSVEPredicate3bBReg:
4310 case Match_InvalidSVEPredicate3bHReg:
4311 case Match_InvalidSVEPredicate3bSReg:
4312 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004313 case Match_MSR:
4314 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004315 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004316 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004317 // Any time we get here, there's nothing fancy to do. Just get the
4318 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004319 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004320 if (ErrorLoc == SMLoc())
4321 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004322 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004323 }
4324 }
4325
4326 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004327}
4328
4329/// ParseDirective parses the arm specific directives
4330bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004331 const MCObjectFileInfo::Environment Format =
4332 getContext().getObjectFileInfo()->getObjectFileType();
4333 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4334 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004335
Tim Northover3b0846e2014-05-24 12:50:23 +00004336 StringRef IDVal = DirectiveID.getIdentifier();
4337 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004338 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004339 parseDirectiveArch(Loc);
4340 else if (IDVal == ".cpu")
4341 parseDirectiveCPU(Loc);
4342 else if (IDVal == ".hword")
4343 parseDirectiveWord(2, Loc);
4344 else if (IDVal == ".word")
4345 parseDirectiveWord(4, Loc);
4346 else if (IDVal == ".xword")
4347 parseDirectiveWord(8, Loc);
4348 else if (IDVal == ".tlsdesccall")
4349 parseDirectiveTLSDescCall(Loc);
4350 else if (IDVal == ".ltorg" || IDVal == ".pool")
4351 parseDirectiveLtorg(Loc);
4352 else if (IDVal == ".unreq")
4353 parseDirectiveUnreq(Loc);
4354 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004355 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004356 parseDirectiveInst(Loc);
4357 else
4358 return true;
4359 } else if (IDVal == MCLOHDirectiveName())
4360 parseDirectiveLOH(IDVal, Loc);
4361 else
4362 return true;
4363 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004364}
4365
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004366static const struct {
4367 const char *Name;
4368 const FeatureBitset Features;
4369} ExtensionMap[] = {
4370 { "crc", {AArch64::FeatureCRC} },
4371 { "crypto", {AArch64::FeatureCrypto} },
4372 { "fp", {AArch64::FeatureFPARMv8} },
4373 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004374 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004375 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004376
4377 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004378 { "pan", {} },
4379 { "lor", {} },
4380 { "rdma", {} },
4381 { "profile", {} },
4382};
4383
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004384/// parseDirectiveArch
4385/// ::= .arch token
4386bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4387 SMLoc ArchLoc = getLoc();
4388
4389 StringRef Arch, ExtensionString;
4390 std::tie(Arch, ExtensionString) =
4391 getParser().parseStringToEndOfStatement().trim().split('+');
4392
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004393 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4394 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004395 return Error(ArchLoc, "unknown arch name");
4396
4397 if (parseToken(AsmToken::EndOfStatement))
4398 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004399
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004400 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004401 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004402 AArch64::getArchFeatures(ID, AArch64Features);
4403 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4404 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004405
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004406 MCSubtargetInfo &STI = copySTI();
4407 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4408 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4409
4410 SmallVector<StringRef, 4> RequestedExtensions;
4411 if (!ExtensionString.empty())
4412 ExtensionString.split(RequestedExtensions, '+');
4413
4414 FeatureBitset Features = STI.getFeatureBits();
4415 for (auto Name : RequestedExtensions) {
4416 bool EnableFeature = true;
4417
4418 if (Name.startswith_lower("no")) {
4419 EnableFeature = false;
4420 Name = Name.substr(2);
4421 }
4422
4423 for (const auto &Extension : ExtensionMap) {
4424 if (Extension.Name != Name)
4425 continue;
4426
4427 if (Extension.Features.none())
4428 report_fatal_error("unsupported architectural extension: " + Name);
4429
4430 FeatureBitset ToggleFeatures = EnableFeature
4431 ? (~Features & Extension.Features)
4432 : ( Features & Extension.Features);
4433 uint64_t Features =
4434 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4435 setAvailableFeatures(Features);
4436 break;
4437 }
4438 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004439 return false;
4440}
4441
Tim Northover8b96c7e2017-05-15 19:42:15 +00004442static SMLoc incrementLoc(SMLoc L, int Offset) {
4443 return SMLoc::getFromPointer(L.getPointer() + Offset);
4444}
4445
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004446/// parseDirectiveCPU
4447/// ::= .cpu id
4448bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004449 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004450
4451 StringRef CPU, ExtensionString;
4452 std::tie(CPU, ExtensionString) =
4453 getParser().parseStringToEndOfStatement().trim().split('+');
4454
Nirav Davee833c6c2016-11-08 18:31:04 +00004455 if (parseToken(AsmToken::EndOfStatement))
4456 return true;
4457
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004458 SmallVector<StringRef, 4> RequestedExtensions;
4459 if (!ExtensionString.empty())
4460 ExtensionString.split(RequestedExtensions, '+');
4461
4462 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4463 // once that is tablegen'ed
4464 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004465 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004466 return false;
4467 }
4468
4469 MCSubtargetInfo &STI = copySTI();
4470 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004471 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004472
4473 FeatureBitset Features = STI.getFeatureBits();
4474 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004475 // Advance source location past '+'.
4476 CurLoc = incrementLoc(CurLoc, 1);
4477
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004478 bool EnableFeature = true;
4479
4480 if (Name.startswith_lower("no")) {
4481 EnableFeature = false;
4482 Name = Name.substr(2);
4483 }
4484
Tim Northover8b96c7e2017-05-15 19:42:15 +00004485 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004486 for (const auto &Extension : ExtensionMap) {
4487 if (Extension.Name != Name)
4488 continue;
4489
4490 if (Extension.Features.none())
4491 report_fatal_error("unsupported architectural extension: " + Name);
4492
4493 FeatureBitset ToggleFeatures = EnableFeature
4494 ? (~Features & Extension.Features)
4495 : ( Features & Extension.Features);
4496 uint64_t Features =
4497 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4498 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004499 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004500
4501 break;
4502 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004503
4504 if (!FoundExtension)
4505 Error(CurLoc, "unsupported architectural extension");
4506
4507 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004508 }
4509 return false;
4510}
4511
Tim Northover3b0846e2014-05-24 12:50:23 +00004512/// parseDirectiveWord
4513/// ::= .word [ expression (, expression)* ]
4514bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004515 auto parseOp = [&]() -> bool {
4516 const MCExpr *Value;
4517 if (getParser().parseExpression(Value))
4518 return true;
4519 getParser().getStreamer().EmitValue(Value, Size, L);
4520 return false;
4521 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004522
Nirav Davee833c6c2016-11-08 18:31:04 +00004523 if (parseMany(parseOp))
4524 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004525 return false;
4526}
4527
Chad Rosierdcd2a302014-10-22 20:35:57 +00004528/// parseDirectiveInst
4529/// ::= .inst opcode [, ...]
4530bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004531 if (getLexer().is(AsmToken::EndOfStatement))
4532 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004533
Nirav Davee833c6c2016-11-08 18:31:04 +00004534 auto parseOp = [&]() -> bool {
4535 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004536 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004537 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4538 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004539 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004540 if (check(!Value, L, "expected constant expression"))
4541 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004542 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004543 return false;
4544 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004545
Nirav Davee833c6c2016-11-08 18:31:04 +00004546 if (parseMany(parseOp))
4547 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004548 return false;
4549}
4550
Tim Northover3b0846e2014-05-24 12:50:23 +00004551// parseDirectiveTLSDescCall:
4552// ::= .tlsdesccall symbol
4553bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4554 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004555 if (check(getParser().parseIdentifier(Name), L,
4556 "expected symbol after directive") ||
4557 parseToken(AsmToken::EndOfStatement))
4558 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004559
Jim Grosbach6f482002015-05-18 18:43:14 +00004560 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004561 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4562 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004563
4564 MCInst Inst;
4565 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004566 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004567
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004568 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004569 return false;
4570}
4571
4572/// ::= .loh <lohName | lohId> label1, ..., labelN
4573/// The number of arguments depends on the loh identifier.
4574bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004575 MCLOHType Kind;
4576 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4577 if (getParser().getTok().isNot(AsmToken::Integer))
4578 return TokError("expected an identifier or a number in directive");
4579 // We successfully get a numeric value for the identifier.
4580 // Check if it is valid.
4581 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004582 if (Id <= -1U && !isValidMCLOHType(Id))
4583 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004584 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004585 } else {
4586 StringRef Name = getTok().getIdentifier();
4587 // We successfully parse an identifier.
4588 // Check if it is a recognized one.
4589 int Id = MCLOHNameToId(Name);
4590
4591 if (Id == -1)
4592 return TokError("invalid identifier in directive");
4593 Kind = (MCLOHType)Id;
4594 }
4595 // Consume the identifier.
4596 Lex();
4597 // Get the number of arguments of this LOH.
4598 int NbArgs = MCLOHIdToNbArgs(Kind);
4599
4600 assert(NbArgs != -1 && "Invalid number of arguments");
4601
4602 SmallVector<MCSymbol *, 3> Args;
4603 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4604 StringRef Name;
4605 if (getParser().parseIdentifier(Name))
4606 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004607 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004608
4609 if (Idx + 1 == NbArgs)
4610 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004611 if (parseToken(AsmToken::Comma,
4612 "unexpected token in '" + Twine(IDVal) + "' directive"))
4613 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004614 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004615 if (parseToken(AsmToken::EndOfStatement,
4616 "unexpected token in '" + Twine(IDVal) + "' directive"))
4617 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004618
4619 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4620 return false;
4621}
4622
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004623/// parseDirectiveLtorg
4624/// ::= .ltorg | .pool
4625bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004626 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4627 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004628 getTargetStreamer().emitCurrentConstantPool();
4629 return false;
4630}
4631
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004632/// parseDirectiveReq
4633/// ::= name .req registername
4634bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004635 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004636 Parser.Lex(); // Eat the '.req' token.
4637 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004638 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004639 unsigned RegNum;
4640 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004641
Sander de Smalen50d87022018-04-19 07:35:08 +00004642 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004643 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004644 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004645 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004646
Sander de Smalen50d87022018-04-19 07:35:08 +00004647 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004648 return true;
4649
Sander de Smalen50d87022018-04-19 07:35:08 +00004650 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004651 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004652 }
4653
Sander de Smalen50d87022018-04-19 07:35:08 +00004654 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004655 StringRef Kind;
4656 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004657 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004658 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004659
Sander de Smalen50d87022018-04-19 07:35:08 +00004660 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004661 return true;
4662
Sander de Smalen50d87022018-04-19 07:35:08 +00004663 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004664 return Error(SRegLoc,
4665 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004666 }
4667
Sander de Smalen50d87022018-04-19 07:35:08 +00004668 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00004669 StringRef Kind;
4670 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004671 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004672
Sander de Smalen50d87022018-04-19 07:35:08 +00004673 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00004674 return true;
4675
Sander de Smalen50d87022018-04-19 07:35:08 +00004676 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00004677 return Error(SRegLoc,
4678 "sve predicate register without type specifier expected");
4679 }
4680
Sander de Smalen50d87022018-04-19 07:35:08 +00004681 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00004682 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004683
4684 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004685 if (parseToken(AsmToken::EndOfStatement,
4686 "unexpected input in .req directive"))
4687 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004688
Sander de Smalen8e607342017-11-15 15:44:43 +00004689 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004690 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004691 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4692
Nirav Dave2364748a2016-09-16 18:30:20 +00004693 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004694}
4695
4696/// parseDirectiveUneq
4697/// ::= .unreq registername
4698bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004699 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004700 if (getTok().isNot(AsmToken::Identifier))
4701 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004702 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4703 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004704 if (parseToken(AsmToken::EndOfStatement))
4705 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004706 return false;
4707}
4708
Tim Northover3b0846e2014-05-24 12:50:23 +00004709bool
4710AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4711 AArch64MCExpr::VariantKind &ELFRefKind,
4712 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4713 int64_t &Addend) {
4714 ELFRefKind = AArch64MCExpr::VK_INVALID;
4715 DarwinRefKind = MCSymbolRefExpr::VK_None;
4716 Addend = 0;
4717
4718 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4719 ELFRefKind = AE->getKind();
4720 Expr = AE->getSubExpr();
4721 }
4722
4723 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4724 if (SE) {
4725 // It's a simple symbol reference with no addend.
4726 DarwinRefKind = SE->getKind();
4727 return true;
4728 }
4729
4730 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4731 if (!BE)
4732 return false;
4733
4734 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4735 if (!SE)
4736 return false;
4737 DarwinRefKind = SE->getKind();
4738
4739 if (BE->getOpcode() != MCBinaryExpr::Add &&
4740 BE->getOpcode() != MCBinaryExpr::Sub)
4741 return false;
4742
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004743 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004744 // on here than we can deal with.
4745 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4746 if (!AddendExpr)
4747 return false;
4748
4749 Addend = AddendExpr->getValue();
4750 if (BE->getOpcode() == MCBinaryExpr::Sub)
4751 Addend = -Addend;
4752
4753 // It's some symbol reference + a constant addend, but really
4754 // shouldn't use both Darwin and ELF syntax.
4755 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4756 DarwinRefKind == MCSymbolRefExpr::VK_None;
4757}
4758
4759/// Force static initialization.
4760extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004761 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4762 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4763 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004764}
4765
4766#define GET_REGISTER_MATCHER
4767#define GET_SUBTARGET_FEATURE_NAME
4768#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004769#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004770#include "AArch64GenAsmMatcher.inc"
4771
4772// Define this matcher function after the auto-generated include so we
4773// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004774unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004775 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004776 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004777 // If the kind is a token for a literal immediate, check if our asm
4778 // operand matches. This is for InstAliases which have a fixed-value
4779 // immediate in the syntax.
4780 int64_t ExpectedVal;
4781 switch (Kind) {
4782 default:
4783 return Match_InvalidOperand;
4784 case MCK__35_0:
4785 ExpectedVal = 0;
4786 break;
4787 case MCK__35_1:
4788 ExpectedVal = 1;
4789 break;
4790 case MCK__35_12:
4791 ExpectedVal = 12;
4792 break;
4793 case MCK__35_16:
4794 ExpectedVal = 16;
4795 break;
4796 case MCK__35_2:
4797 ExpectedVal = 2;
4798 break;
4799 case MCK__35_24:
4800 ExpectedVal = 24;
4801 break;
4802 case MCK__35_3:
4803 ExpectedVal = 3;
4804 break;
4805 case MCK__35_32:
4806 ExpectedVal = 32;
4807 break;
4808 case MCK__35_4:
4809 ExpectedVal = 4;
4810 break;
4811 case MCK__35_48:
4812 ExpectedVal = 48;
4813 break;
4814 case MCK__35_6:
4815 ExpectedVal = 6;
4816 break;
4817 case MCK__35_64:
4818 ExpectedVal = 64;
4819 break;
4820 case MCK__35_8:
4821 ExpectedVal = 8;
4822 break;
4823 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004824 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004825 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004826 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004827 if (!CE)
4828 return Match_InvalidOperand;
4829 if (CE->getValue() == ExpectedVal)
4830 return Match_Success;
4831 return Match_InvalidOperand;
4832}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004833
Alex Bradbury58eba092016-11-01 16:32:05 +00004834OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004835AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4836
4837 SMLoc S = getLoc();
4838
4839 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4840 Error(S, "expected register");
4841 return MatchOperand_ParseFail;
4842 }
4843
Sander de Smalen50d87022018-04-19 07:35:08 +00004844 unsigned FirstReg;
4845 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
4846 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004847 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00004848
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004849 const MCRegisterClass &WRegClass =
4850 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4851 const MCRegisterClass &XRegClass =
4852 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4853
4854 bool isXReg = XRegClass.contains(FirstReg),
4855 isWReg = WRegClass.contains(FirstReg);
4856 if (!isXReg && !isWReg) {
4857 Error(S, "expected first even register of a "
4858 "consecutive same-size even/odd register pair");
4859 return MatchOperand_ParseFail;
4860 }
4861
4862 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4863 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4864
4865 if (FirstEncoding & 0x1) {
4866 Error(S, "expected first even register of a "
4867 "consecutive same-size even/odd register pair");
4868 return MatchOperand_ParseFail;
4869 }
4870
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004871 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00004872 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004873 return MatchOperand_ParseFail;
4874 }
4875 // Eat the comma
4876 getParser().Lex();
4877
4878 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00004879 unsigned SecondReg;
4880 Res = tryParseScalarRegister(SecondReg);
4881 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004882 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004883
Eugene Zelenko049b0172017-01-06 00:30:53 +00004884 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004885 (isXReg && !XRegClass.contains(SecondReg)) ||
4886 (isWReg && !WRegClass.contains(SecondReg))) {
4887 Error(E,"expected second odd register of a "
4888 "consecutive same-size even/odd register pair");
4889 return MatchOperand_ParseFail;
4890 }
Joel Jones504bf332016-10-24 13:37:13 +00004891
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004892 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004893 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004894 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4895 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4896 } else {
4897 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4898 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4899 }
4900
Florian Hahnc4422242017-11-07 13:07:50 +00004901 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4902 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004903
4904 return MatchOperand_Success;
4905}
Florian Hahn91f11e52017-11-07 16:45:48 +00004906
Sander de Smaleneb896b12018-04-25 09:26:47 +00004907template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00004908OperandMatchResultTy
4909AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004910 const SMLoc S = getLoc();
4911 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00004912 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00004913 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004914
Sander de Smalen8e607342017-11-15 15:44:43 +00004915 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004916 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004917
4918 if (Res != MatchOperand_Success)
4919 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004920
4921 if (ParseSuffix && Kind.empty())
4922 return MatchOperand_NoMatch;
4923
Sander de Smalen73937b72018-04-11 07:36:10 +00004924 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
4925 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00004926 return MatchOperand_NoMatch;
4927
Sander de Smalen73937b72018-04-11 07:36:10 +00004928 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00004929
4930 // No shift/extend is the default.
4931 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
4932 Operands.push_back(AArch64Operand::CreateVectorReg(
4933 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
4934
4935 return MatchOperand_Success;
4936 }
4937
4938 // Eat the comma
4939 getParser().Lex();
4940
4941 // Match the shift
4942 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
4943 Res = tryParseOptionalShiftExtend(ExtOpnd);
4944 if (Res != MatchOperand_Success)
4945 return Res;
4946
4947 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00004948 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00004949 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
4950 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
4951 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00004952
4953 return MatchOperand_Success;
4954}
Sander de Smalen245e0e62018-01-22 10:46:00 +00004955
4956OperandMatchResultTy
4957AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
4958 MCAsmParser &Parser = getParser();
4959
4960 SMLoc SS = getLoc();
4961 const AsmToken &TokE = Parser.getTok();
4962 bool IsHash = TokE.is(AsmToken::Hash);
4963
4964 if (!IsHash && TokE.isNot(AsmToken::Identifier))
4965 return MatchOperand_NoMatch;
4966
4967 int64_t Pattern;
4968 if (IsHash) {
4969 Parser.Lex(); // Eat hash
4970
4971 // Parse the immediate operand.
4972 const MCExpr *ImmVal;
4973 SS = getLoc();
4974 if (Parser.parseExpression(ImmVal))
4975 return MatchOperand_ParseFail;
4976
4977 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4978 if (!MCE)
4979 return MatchOperand_ParseFail;
4980
4981 Pattern = MCE->getValue();
4982 } else {
4983 // Parse the pattern
4984 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
4985 if (!Pat)
4986 return MatchOperand_NoMatch;
4987
4988 Parser.Lex();
4989 Pattern = Pat->Encoding;
4990 assert(Pattern >= 0 && Pattern < 32);
4991 }
4992
4993 Operands.push_back(
4994 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
4995 SS, getLoc(), getContext()));
4996
4997 return MatchOperand_Success;
4998}