blob: 1a8d1726a63a6f9f66b54d8d89df63ee63392830 [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);
131 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000132 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000133 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
134 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
135 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
136 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
137 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000138 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000139 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000140 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Florian Hahn91f11e52017-11-07 16:45:48 +0000141 template <bool ParseSuffix>
142 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000143 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000144 template <RegKind VectorKind>
145 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
146 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000147 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000148
149public:
150 enum AArch64MatchResultTy {
151 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
152#define GET_OPERAND_DIAGNOSTIC_TYPES
153#include "AArch64GenAsmMatcher.inc"
154 };
Joel Jones504bf332016-10-24 13:37:13 +0000155 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000156
Akira Hatanakab11ef082015-11-14 06:35:56 +0000157 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000158 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000159 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000160 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000161 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000162 MCStreamer &S = getParser().getStreamer();
163 if (S.getTargetStreamer() == nullptr)
164 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000165
166 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000167 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000168 }
169
170 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
171 SMLoc NameLoc, OperandVector &Operands) override;
172 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
173 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000174 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000175 unsigned Kind) override;
176
177 static bool classifySymbolRef(const MCExpr *Expr,
178 AArch64MCExpr::VariantKind &ELFRefKind,
179 MCSymbolRefExpr::VariantKind &DarwinRefKind,
180 int64_t &Addend);
181};
Tim Northover3b0846e2014-05-24 12:50:23 +0000182
183/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
184/// instruction.
185class AArch64Operand : public MCParsedAsmOperand {
186private:
187 enum KindTy {
188 k_Immediate,
189 k_ShiftedImm,
190 k_CondCode,
191 k_Register,
192 k_VectorList,
193 k_VectorIndex,
194 k_Token,
195 k_SysReg,
196 k_SysCR,
197 k_Prefetch,
198 k_ShiftExtend,
199 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000200 k_Barrier,
201 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000202 } Kind;
203
204 SMLoc StartLoc, EndLoc;
205
206 struct TokOp {
207 const char *Data;
208 unsigned Length;
209 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
210 };
211
212 struct RegOp {
213 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000214 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000215
216 int ElementWidth;
Tim Northover3b0846e2014-05-24 12:50:23 +0000217 };
218
219 struct VectorListOp {
220 unsigned RegNum;
221 unsigned Count;
222 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000223 unsigned ElementWidth;
224 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000225 };
226
227 struct VectorIndexOp {
228 unsigned Val;
229 };
230
231 struct ImmOp {
232 const MCExpr *Val;
233 };
234
235 struct ShiftedImmOp {
236 const MCExpr *Val;
237 unsigned ShiftAmount;
238 };
239
240 struct CondCodeOp {
241 AArch64CC::CondCode Code;
242 };
243
244 struct FPImmOp {
245 unsigned Val; // Encoded 8-bit representation.
246 };
247
248 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000249 const char *Data;
250 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000251 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000252 };
253
254 struct SysRegOp {
255 const char *Data;
256 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000257 uint32_t MRSReg;
258 uint32_t MSRReg;
259 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000260 };
261
262 struct SysCRImmOp {
263 unsigned Val;
264 };
265
266 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000267 const char *Data;
268 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000269 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000270 };
271
Oliver Stannarda34e4702015-12-01 10:48:51 +0000272 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000273 const char *Data;
274 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000275 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000276 };
277
Tim Northover3b0846e2014-05-24 12:50:23 +0000278 struct ShiftExtendOp {
279 AArch64_AM::ShiftExtendType Type;
280 unsigned Amount;
281 bool HasExplicitAmount;
282 };
283
284 struct ExtendOp {
285 unsigned Val;
286 };
287
288 union {
289 struct TokOp Tok;
290 struct RegOp Reg;
291 struct VectorListOp VectorList;
292 struct VectorIndexOp VectorIndex;
293 struct ImmOp Imm;
294 struct ShiftedImmOp ShiftedImm;
295 struct CondCodeOp CondCode;
296 struct FPImmOp FPImm;
297 struct BarrierOp Barrier;
298 struct SysRegOp SysReg;
299 struct SysCRImmOp SysCRImm;
300 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000301 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000302 struct ShiftExtendOp ShiftExtend;
303 };
304
305 // Keep the MCContext around as the MCExprs may need manipulated during
306 // the add<>Operands() calls.
307 MCContext &Ctx;
308
David Blaikie960ea3f2014-06-08 16:18:35 +0000309public:
David Blaikie9f380a32015-03-16 18:06:57 +0000310 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000311
Tim Northover3b0846e2014-05-24 12:50:23 +0000312 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
313 Kind = o.Kind;
314 StartLoc = o.StartLoc;
315 EndLoc = o.EndLoc;
316 switch (Kind) {
317 case k_Token:
318 Tok = o.Tok;
319 break;
320 case k_Immediate:
321 Imm = o.Imm;
322 break;
323 case k_ShiftedImm:
324 ShiftedImm = o.ShiftedImm;
325 break;
326 case k_CondCode:
327 CondCode = o.CondCode;
328 break;
329 case k_FPImm:
330 FPImm = o.FPImm;
331 break;
332 case k_Barrier:
333 Barrier = o.Barrier;
334 break;
335 case k_Register:
336 Reg = o.Reg;
337 break;
338 case k_VectorList:
339 VectorList = o.VectorList;
340 break;
341 case k_VectorIndex:
342 VectorIndex = o.VectorIndex;
343 break;
344 case k_SysReg:
345 SysReg = o.SysReg;
346 break;
347 case k_SysCR:
348 SysCRImm = o.SysCRImm;
349 break;
350 case k_Prefetch:
351 Prefetch = o.Prefetch;
352 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000353 case k_PSBHint:
354 PSBHint = o.PSBHint;
355 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000356 case k_ShiftExtend:
357 ShiftExtend = o.ShiftExtend;
358 break;
359 }
360 }
361
362 /// getStartLoc - Get the location of the first token of this operand.
363 SMLoc getStartLoc() const override { return StartLoc; }
364 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000365 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000366
367 StringRef getToken() const {
368 assert(Kind == k_Token && "Invalid access!");
369 return StringRef(Tok.Data, Tok.Length);
370 }
371
372 bool isTokenSuffix() const {
373 assert(Kind == k_Token && "Invalid access!");
374 return Tok.IsSuffix;
375 }
376
377 const MCExpr *getImm() const {
378 assert(Kind == k_Immediate && "Invalid access!");
379 return Imm.Val;
380 }
381
382 const MCExpr *getShiftedImmVal() const {
383 assert(Kind == k_ShiftedImm && "Invalid access!");
384 return ShiftedImm.Val;
385 }
386
387 unsigned getShiftedImmShift() const {
388 assert(Kind == k_ShiftedImm && "Invalid access!");
389 return ShiftedImm.ShiftAmount;
390 }
391
392 AArch64CC::CondCode getCondCode() const {
393 assert(Kind == k_CondCode && "Invalid access!");
394 return CondCode.Code;
395 }
396
397 unsigned getFPImm() const {
398 assert(Kind == k_FPImm && "Invalid access!");
399 return FPImm.Val;
400 }
401
402 unsigned getBarrier() const {
403 assert(Kind == k_Barrier && "Invalid access!");
404 return Barrier.Val;
405 }
406
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000407 StringRef getBarrierName() const {
408 assert(Kind == k_Barrier && "Invalid access!");
409 return StringRef(Barrier.Data, Barrier.Length);
410 }
411
Tim Northover3b0846e2014-05-24 12:50:23 +0000412 unsigned getReg() const override {
413 assert(Kind == k_Register && "Invalid access!");
414 return Reg.RegNum;
415 }
416
417 unsigned getVectorListStart() const {
418 assert(Kind == k_VectorList && "Invalid access!");
419 return VectorList.RegNum;
420 }
421
422 unsigned getVectorListCount() const {
423 assert(Kind == k_VectorList && "Invalid access!");
424 return VectorList.Count;
425 }
426
427 unsigned getVectorIndex() const {
428 assert(Kind == k_VectorIndex && "Invalid access!");
429 return VectorIndex.Val;
430 }
431
432 StringRef getSysReg() const {
433 assert(Kind == k_SysReg && "Invalid access!");
434 return StringRef(SysReg.Data, SysReg.Length);
435 }
436
Tim Northover3b0846e2014-05-24 12:50:23 +0000437 unsigned getSysCR() const {
438 assert(Kind == k_SysCR && "Invalid access!");
439 return SysCRImm.Val;
440 }
441
442 unsigned getPrefetch() const {
443 assert(Kind == k_Prefetch && "Invalid access!");
444 return Prefetch.Val;
445 }
446
Oliver Stannarda34e4702015-12-01 10:48:51 +0000447 unsigned getPSBHint() const {
448 assert(Kind == k_PSBHint && "Invalid access!");
449 return PSBHint.Val;
450 }
451
452 StringRef getPSBHintName() const {
453 assert(Kind == k_PSBHint && "Invalid access!");
454 return StringRef(PSBHint.Data, PSBHint.Length);
455 }
456
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000457 StringRef getPrefetchName() const {
458 assert(Kind == k_Prefetch && "Invalid access!");
459 return StringRef(Prefetch.Data, Prefetch.Length);
460 }
461
Tim Northover3b0846e2014-05-24 12:50:23 +0000462 AArch64_AM::ShiftExtendType getShiftExtendType() const {
463 assert(Kind == k_ShiftExtend && "Invalid access!");
464 return ShiftExtend.Type;
465 }
466
467 unsigned getShiftExtendAmount() const {
468 assert(Kind == k_ShiftExtend && "Invalid access!");
469 return ShiftExtend.Amount;
470 }
471
472 bool hasShiftExtendAmount() const {
473 assert(Kind == k_ShiftExtend && "Invalid access!");
474 return ShiftExtend.HasExplicitAmount;
475 }
476
477 bool isImm() const override { return Kind == k_Immediate; }
478 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000479
480 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
481
482 template <int Bits, int Scale> bool isSImmScaled() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000483 if (!isImm())
484 return false;
485 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
486 if (!MCE)
487 return false;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000488
489 int64_t Shift = Bits - 1;
490 int64_t MinVal = (int64_t(1) << Shift) * -Scale;
491 int64_t MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
492
Tim Northover3b0846e2014-05-24 12:50:23 +0000493 int64_t Val = MCE->getValue();
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000494 return Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0;
Tim Northover3b0846e2014-05-24 12:50:23 +0000495 }
496
Sander de Smalen245e0e62018-01-22 10:46:00 +0000497 bool isSVEPattern() const {
498 if (!isImm())
499 return false;
500 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
501 if (!MCE)
502 return false;
503 int64_t Val = MCE->getValue();
504 return Val >= 0 && Val < 32;
505 }
506
Tim Northover3b0846e2014-05-24 12:50:23 +0000507 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
508 AArch64MCExpr::VariantKind ELFRefKind;
509 MCSymbolRefExpr::VariantKind DarwinRefKind;
510 int64_t Addend;
511 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
512 Addend)) {
513 // If we don't understand the expression, assume the best and
514 // let the fixup and relocation code deal with it.
515 return true;
516 }
517
518 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
519 ELFRefKind == AArch64MCExpr::VK_LO12 ||
520 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
521 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
522 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
523 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
524 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
525 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000526 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
527 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
528 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000529 // Note that we don't range-check the addend. It's adjusted modulo page
530 // size when converted, so there is no "out of range" condition when using
531 // @pageoff.
532 return Addend >= 0 && (Addend % Scale) == 0;
533 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
534 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
535 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
536 return Addend == 0;
537 }
538
539 return false;
540 }
541
542 template <int Scale> bool isUImm12Offset() const {
543 if (!isImm())
544 return false;
545
546 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
547 if (!MCE)
548 return isSymbolicUImm12Offset(getImm(), Scale);
549
550 int64_t Val = MCE->getValue();
551 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
552 }
553
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000554 template <int N, int M>
555 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000556 if (!isImm())
557 return false;
558 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
559 if (!MCE)
560 return false;
561 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000562 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000563 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000564
Sander de Smalena1c259c2018-01-29 13:05:38 +0000565 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
566 // a logical immediate can always be represented when inverted.
567 template <typename T>
568 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000569 if (!isImm())
570 return false;
571 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
572 if (!MCE)
573 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000574
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000575 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000576 int64_t SVal = typename std::make_signed<T>::type(Val);
577 int64_t UVal = typename std::make_unsigned<T>::type(Val);
578 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000579 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000580
Sander de Smalena1c259c2018-01-29 13:05:38 +0000581 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000582 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000583
Tim Northover3b0846e2014-05-24 12:50:23 +0000584 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000585
Tim Northover3b0846e2014-05-24 12:50:23 +0000586 bool isAddSubImm() const {
587 if (!isShiftedImm() && !isImm())
588 return false;
589
590 const MCExpr *Expr;
591
592 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
593 if (isShiftedImm()) {
594 unsigned Shift = ShiftedImm.ShiftAmount;
595 Expr = ShiftedImm.Val;
596 if (Shift != 0 && Shift != 12)
597 return false;
598 } else {
599 Expr = getImm();
600 }
601
602 AArch64MCExpr::VariantKind ELFRefKind;
603 MCSymbolRefExpr::VariantKind DarwinRefKind;
604 int64_t Addend;
605 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
606 DarwinRefKind, Addend)) {
607 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
608 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
609 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
610 || ELFRefKind == AArch64MCExpr::VK_LO12
611 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
612 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
613 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
614 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
615 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
616 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000617 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
618 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
619 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000620 }
621
Diana Picusc93518d2016-10-11 09:17:47 +0000622 // If it's a constant, it should be a real immediate in range:
623 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
624 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
625
626 // If it's an expression, we hope for the best and let the fixup/relocation
627 // code deal with it.
628 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000629 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000630
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000631 bool isAddSubImmNeg() const {
632 if (!isShiftedImm() && !isImm())
633 return false;
634
635 const MCExpr *Expr;
636
637 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
638 if (isShiftedImm()) {
639 unsigned Shift = ShiftedImm.ShiftAmount;
640 Expr = ShiftedImm.Val;
641 if (Shift != 0 && Shift != 12)
642 return false;
643 } else
644 Expr = getImm();
645
646 // Otherwise it should be a real negative immediate in range:
647 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
648 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
649 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000650
Tim Northover3b0846e2014-05-24 12:50:23 +0000651 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000652
Tim Northover3b0846e2014-05-24 12:50:23 +0000653 bool isSIMDImmType10() const {
654 if (!isImm())
655 return false;
656 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
657 if (!MCE)
658 return false;
659 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
660 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000661
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000662 template<int N>
663 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000664 if (!isImm())
665 return false;
666 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
667 if (!MCE)
668 return true;
669 int64_t Val = MCE->getValue();
670 if (Val & 0x3)
671 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000672 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
673 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000674 }
675
676 bool
677 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
678 if (!isImm())
679 return false;
680
681 AArch64MCExpr::VariantKind ELFRefKind;
682 MCSymbolRefExpr::VariantKind DarwinRefKind;
683 int64_t Addend;
684 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
685 DarwinRefKind, Addend)) {
686 return false;
687 }
688 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
689 return false;
690
691 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
692 if (ELFRefKind == AllowedModifiers[i])
693 return Addend == 0;
694 }
695
696 return false;
697 }
698
699 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000700 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000701 }
702
703 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000704 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
705 AArch64MCExpr::VK_TPREL_G2,
706 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000707 }
708
709 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000710 return isMovWSymbol({
711 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000712 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
713 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000714 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000715 }
716
717 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000718 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
719 AArch64MCExpr::VK_TPREL_G0,
720 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000721 }
722
723 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000724 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000725 }
726
727 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000728 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000729 }
730
731 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000732 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
733 AArch64MCExpr::VK_TPREL_G1_NC,
734 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000735 }
736
737 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000738 return isMovWSymbol(
739 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
740 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000741 }
742
743 template<int RegWidth, int Shift>
744 bool isMOVZMovAlias() const {
745 if (!isImm()) return false;
746
747 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
748 if (!CE) return false;
749 uint64_t Value = CE->getValue();
750
Tim Northoverdaa1c012016-06-16 01:42:25 +0000751 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000752 }
753
754 template<int RegWidth, int Shift>
755 bool isMOVNMovAlias() const {
756 if (!isImm()) return false;
757
758 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
759 if (!CE) return false;
760 uint64_t Value = CE->getValue();
761
Tim Northoverdaa1c012016-06-16 01:42:25 +0000762 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000763 }
764
765 bool isFPImm() const { return Kind == k_FPImm; }
766 bool isBarrier() const { return Kind == k_Barrier; }
767 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000768
Tim Northover3b0846e2014-05-24 12:50:23 +0000769 bool isMRSSystemRegister() const {
770 if (!isSysReg()) return false;
771
Tim Northover7cd58932015-01-22 17:23:04 +0000772 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000773 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000774
Tim Northover3b0846e2014-05-24 12:50:23 +0000775 bool isMSRSystemRegister() const {
776 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000777 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000778 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000779
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000780 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000781 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000782 return (SysReg.PStateField == AArch64PState::PAN ||
783 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000784 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000785
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000786 bool isSystemPStateFieldWithImm0_15() const {
787 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000788 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000789 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000790
Florian Hahnc4422242017-11-07 13:07:50 +0000791 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000792 return Kind == k_Register;
793 }
794
795 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000796 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
797 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000798
Florian Hahnc4422242017-11-07 13:07:50 +0000799 bool isNeonVectorReg() const {
800 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
801 }
802
803 bool isNeonVectorRegLo() const {
804 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000805 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
806 Reg.RegNum);
807 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000808
Sander de Smalencd6be962017-12-20 11:02:42 +0000809 template <unsigned Class> bool isSVEVectorReg() const {
810 RegKind RK;
811 switch (Class) {
812 case AArch64::ZPRRegClassID:
813 RK = RegKind::SVEDataVector;
814 break;
815 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000816 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000817 RK = RegKind::SVEPredicateVector;
818 break;
819 default:
820 llvm_unreachable("Unsupport register class");
821 }
822
823 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000824 AArch64MCRegisterClasses[Class].contains(getReg());
825 }
826
Sander de Smalencd6be962017-12-20 11:02:42 +0000827 template <int ElementWidth, unsigned Class>
828 bool isSVEVectorRegOfWidth() const {
829 return isSVEVectorReg<Class>() &&
Sander de Smalen73937b72018-04-11 07:36:10 +0000830 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth);
Florian Hahn91f11e52017-11-07 16:45:48 +0000831 }
832
Tim Northover3b0846e2014-05-24 12:50:23 +0000833 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000834 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000835 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
836 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000837
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000838 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000839 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000840 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
841 Reg.RegNum);
842 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000843
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000844 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000845 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000846 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
847 Reg.RegNum);
848 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000849
850 bool isGPR64sp0() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000851 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000852 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
853 }
854
Sam Parker5f934642017-08-31 09:27:04 +0000855 template<int64_t Angle, int64_t Remainder>
856 bool isComplexRotation() const {
857 if (!isImm()) return false;
858
859 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
860 if (!CE) return false;
861 uint64_t Value = CE->getValue();
862
863 return (Value % Angle == Remainder && Value <= 270);
864 }
865
Tim Northover3b0846e2014-05-24 12:50:23 +0000866 /// Is this a vector list with the type implicit (presumably attached to the
867 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +0000868 template <RegKind VectorKind, unsigned NumRegs>
869 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000870 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +0000871 VectorList.NumElements == 0 &&
872 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000873 }
874
Sander de Smalen650234b2018-04-12 11:40:52 +0000875 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
876 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +0000877 bool isTypedVectorList() const {
878 if (Kind != k_VectorList)
879 return false;
880 if (VectorList.Count != NumRegs)
881 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +0000882 if (VectorList.RegisterKind != VectorKind)
883 return false;
884 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +0000885 return false;
886 return VectorList.NumElements == NumElements;
887 }
888
889 bool isVectorIndex1() const {
890 return Kind == k_VectorIndex && VectorIndex.Val == 1;
891 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000892
Tim Northover3b0846e2014-05-24 12:50:23 +0000893 bool isVectorIndexB() const {
894 return Kind == k_VectorIndex && VectorIndex.Val < 16;
895 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000896
Tim Northover3b0846e2014-05-24 12:50:23 +0000897 bool isVectorIndexH() const {
898 return Kind == k_VectorIndex && VectorIndex.Val < 8;
899 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000900
Tim Northover3b0846e2014-05-24 12:50:23 +0000901 bool isVectorIndexS() const {
902 return Kind == k_VectorIndex && VectorIndex.Val < 4;
903 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000904
Tim Northover3b0846e2014-05-24 12:50:23 +0000905 bool isVectorIndexD() const {
906 return Kind == k_VectorIndex && VectorIndex.Val < 2;
907 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000908
Tim Northover3b0846e2014-05-24 12:50:23 +0000909 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000910
Tim Northover3b0846e2014-05-24 12:50:23 +0000911 bool isTokenEqual(StringRef Str) const {
912 return Kind == k_Token && getToken() == Str;
913 }
914 bool isSysCR() const { return Kind == k_SysCR; }
915 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000916 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000917 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
918 bool isShifter() const {
919 if (!isShiftExtend())
920 return false;
921
922 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
923 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
924 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
925 ST == AArch64_AM::MSL);
926 }
927 bool isExtend() const {
928 if (!isShiftExtend())
929 return false;
930
931 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
932 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
933 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
934 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
935 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
936 ET == AArch64_AM::LSL) &&
937 getShiftExtendAmount() <= 4;
938 }
939
940 bool isExtend64() const {
941 if (!isExtend())
942 return false;
943 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
944 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
945 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
946 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000947
Tim Northover3b0846e2014-05-24 12:50:23 +0000948 bool isExtendLSL64() const {
949 if (!isExtend())
950 return false;
951 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
952 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
953 ET == AArch64_AM::LSL) &&
954 getShiftExtendAmount() <= 4;
955 }
956
957 template<int Width> bool isMemXExtend() const {
958 if (!isExtend())
959 return false;
960 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
961 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
962 (getShiftExtendAmount() == Log2_32(Width / 8) ||
963 getShiftExtendAmount() == 0);
964 }
965
966 template<int Width> bool isMemWExtend() const {
967 if (!isExtend())
968 return false;
969 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
970 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
971 (getShiftExtendAmount() == Log2_32(Width / 8) ||
972 getShiftExtendAmount() == 0);
973 }
974
975 template <unsigned width>
976 bool isArithmeticShifter() const {
977 if (!isShifter())
978 return false;
979
980 // An arithmetic shifter is LSL, LSR, or ASR.
981 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
982 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
983 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
984 }
985
986 template <unsigned width>
987 bool isLogicalShifter() const {
988 if (!isShifter())
989 return false;
990
991 // A logical shifter is LSL, LSR, ASR or ROR.
992 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
993 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
994 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
995 getShiftExtendAmount() < width;
996 }
997
998 bool isMovImm32Shifter() const {
999 if (!isShifter())
1000 return false;
1001
1002 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1003 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1004 if (ST != AArch64_AM::LSL)
1005 return false;
1006 uint64_t Val = getShiftExtendAmount();
1007 return (Val == 0 || Val == 16);
1008 }
1009
1010 bool isMovImm64Shifter() const {
1011 if (!isShifter())
1012 return false;
1013
1014 // A MOVi shifter is LSL of 0 or 16.
1015 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1016 if (ST != AArch64_AM::LSL)
1017 return false;
1018 uint64_t Val = getShiftExtendAmount();
1019 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1020 }
1021
1022 bool isLogicalVecShifter() const {
1023 if (!isShifter())
1024 return false;
1025
1026 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1027 unsigned Shift = getShiftExtendAmount();
1028 return getShiftExtendType() == AArch64_AM::LSL &&
1029 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1030 }
1031
1032 bool isLogicalVecHalfWordShifter() const {
1033 if (!isLogicalVecShifter())
1034 return false;
1035
1036 // A logical vector shifter is a left shift by 0 or 8.
1037 unsigned Shift = getShiftExtendAmount();
1038 return getShiftExtendType() == AArch64_AM::LSL &&
1039 (Shift == 0 || Shift == 8);
1040 }
1041
1042 bool isMoveVecShifter() const {
1043 if (!isShiftExtend())
1044 return false;
1045
1046 // A logical vector shifter is a left shift by 8 or 16.
1047 unsigned Shift = getShiftExtendAmount();
1048 return getShiftExtendType() == AArch64_AM::MSL &&
1049 (Shift == 8 || Shift == 16);
1050 }
1051
1052 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1053 // to LDUR/STUR when the offset is not legal for the former but is for
1054 // the latter. As such, in addition to checking for being a legal unscaled
1055 // address, also check that it is not a legal scaled address. This avoids
1056 // ambiguity in the matcher.
1057 template<int Width>
1058 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001059 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001060 }
1061
1062 bool isAdrpLabel() const {
1063 // Validation was handled during parsing, so we just sanity check that
1064 // something didn't go haywire.
1065 if (!isImm())
1066 return false;
1067
1068 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1069 int64_t Val = CE->getValue();
1070 int64_t Min = - (4096 * (1LL << (21 - 1)));
1071 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1072 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1073 }
1074
1075 return true;
1076 }
1077
1078 bool isAdrLabel() const {
1079 // Validation was handled during parsing, so we just sanity check that
1080 // something didn't go haywire.
1081 if (!isImm())
1082 return false;
1083
1084 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1085 int64_t Val = CE->getValue();
1086 int64_t Min = - (1LL << (21 - 1));
1087 int64_t Max = ((1LL << (21 - 1)) - 1);
1088 return Val >= Min && Val <= Max;
1089 }
1090
1091 return true;
1092 }
1093
1094 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1095 // Add as immediates when possible. Null MCExpr = 0.
1096 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001097 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001098 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001099 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001100 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001101 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001102 }
1103
1104 void addRegOperands(MCInst &Inst, unsigned N) const {
1105 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001106 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001107 }
1108
1109 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1110 assert(N == 1 && "Invalid number of operands!");
1111 assert(
1112 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1113
1114 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1115 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1116 RI->getEncodingValue(getReg()));
1117
Jim Grosbache9119e42015-05-13 18:37:00 +00001118 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001119 }
1120
1121 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1122 assert(N == 1 && "Invalid number of operands!");
1123 assert(
1124 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001125 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001126 }
1127
1128 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1129 assert(N == 1 && "Invalid number of operands!");
1130 assert(
1131 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001132 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001133 }
1134
1135 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1136 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001137 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001138 }
1139
Sander de Smalen525e3222018-04-12 13:19:32 +00001140 enum VecListIndexType {
1141 VecListIdx_DReg = 0,
1142 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001143 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001144 };
1145
1146 template <VecListIndexType RegTy, unsigned NumRegs>
1147 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001148 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001149 static const unsigned FirstRegs[][5] = {
1150 /* DReg */ { AArch64::Q0,
1151 AArch64::D0, AArch64::D0_D1,
1152 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1153 /* QReg */ { AArch64::Q0,
1154 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001155 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1156 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001157 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001158 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001159 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001160
Sander de Smalen7a210db2018-04-16 10:46:18 +00001161 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1162 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001163
Sander de Smalen525e3222018-04-12 13:19:32 +00001164 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1165 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1166 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001167 }
1168
1169 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1170 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001171 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001172 }
1173
1174 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1175 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001176 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001177 }
1178
1179 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1180 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001181 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001182 }
1183
1184 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1185 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001186 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001187 }
1188
1189 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1190 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001191 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001192 }
1193
1194 void addImmOperands(MCInst &Inst, unsigned N) const {
1195 assert(N == 1 && "Invalid number of operands!");
1196 // If this is a pageoff symrefexpr with an addend, adjust the addend
1197 // to be only the page-offset portion. Otherwise, just add the expr
1198 // as-is.
1199 addExpr(Inst, getImm());
1200 }
1201
1202 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1203 assert(N == 2 && "Invalid number of operands!");
1204 if (isShiftedImm()) {
1205 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001206 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001207 } else {
1208 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001209 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001210 }
1211 }
1212
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001213 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1214 assert(N == 2 && "Invalid number of operands!");
1215
1216 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1217 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1218 int64_t Val = -CE->getValue();
1219 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1220
1221 Inst.addOperand(MCOperand::createImm(Val));
1222 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1223 }
1224
Tim Northover3b0846e2014-05-24 12:50:23 +00001225 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1226 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001227 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001228 }
1229
1230 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1231 assert(N == 1 && "Invalid number of operands!");
1232 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1233 if (!MCE)
1234 addExpr(Inst, getImm());
1235 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001236 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001237 }
1238
1239 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1240 addImmOperands(Inst, N);
1241 }
1242
1243 template<int Scale>
1244 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1245 assert(N == 1 && "Invalid number of operands!");
1246 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1247
1248 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001249 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001250 return;
1251 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001252 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001253 }
1254
1255 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1256 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001257 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001258 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001259 }
1260
Sam Parker6d42de72017-08-11 13:14:00 +00001261 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1262 assert(N == 1 && "Invalid number of operands!");
1263 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1264 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1265 }
1266
Tim Northover3b0846e2014-05-24 12:50:23 +00001267 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1268 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001269 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001270 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001271 }
1272
1273 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1274 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001275 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001276 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001277 }
1278
1279 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1280 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001281 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001282 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001283 }
1284
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001285 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1286 assert(N == 1 && "Invalid number of operands!");
1287 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1288 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1289 }
1290
Tim Northover3b0846e2014-05-24 12:50:23 +00001291 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1292 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001293 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001294 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001295 }
1296
1297 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1298 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001299 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001300 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001301 }
1302
1303 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1304 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001305 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001306 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001307 }
1308
1309 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1310 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001311 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001312 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001313 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001314 }
1315
1316 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1317 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001318 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001319 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001320 }
1321
1322 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1323 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001324 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001325 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001326 }
1327
1328 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1329 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001330 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001331 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001332 }
1333
1334 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1335 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001336 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001337 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001338 }
1339
1340 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1341 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001342 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001343 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001344 }
1345
1346 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1347 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001348 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001349 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001350 }
1351
1352 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1353 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001354 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001355 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001356 }
1357
1358 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1359 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001360 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001361 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001362 }
1363
1364 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1365 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001366 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001367 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001368 }
1369
1370 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1371 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001372 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001373 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001374 }
1375
Sander de Smalen5c625982018-04-13 12:56:14 +00001376 template <int Scale>
1377 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1378 assert(N == 1 && "Invalid number of operands!");
1379 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1380 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1381 }
1382
Sander de Smalena1c259c2018-01-29 13:05:38 +00001383 template <typename T>
1384 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001385 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001386 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001387 typename std::make_unsigned<T>::type Val = MCE->getValue();
1388 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001389 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001390 }
1391
Sander de Smalena1c259c2018-01-29 13:05:38 +00001392 template <typename T>
1393 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001394 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001395 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001396 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1397 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001398 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001399 }
1400
Tim Northover3b0846e2014-05-24 12:50:23 +00001401 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1402 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001403 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001404 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001405 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001406 }
1407
1408 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1409 // Branch operands don't encode the low bits, so shift them off
1410 // here. If it's a label, however, just put it on directly as there's
1411 // not enough information now to do anything.
1412 assert(N == 1 && "Invalid number of operands!");
1413 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1414 if (!MCE) {
1415 addExpr(Inst, getImm());
1416 return;
1417 }
1418 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001419 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001420 }
1421
1422 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1423 // Branch operands don't encode the low bits, so shift them off
1424 // here. If it's a label, however, just put it on directly as there's
1425 // not enough information now to do anything.
1426 assert(N == 1 && "Invalid number of operands!");
1427 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1428 if (!MCE) {
1429 addExpr(Inst, getImm());
1430 return;
1431 }
1432 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001433 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 }
1435
1436 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1437 // Branch operands don't encode the low bits, so shift them off
1438 // here. If it's a label, however, just put it on directly as there's
1439 // not enough information now to do anything.
1440 assert(N == 1 && "Invalid number of operands!");
1441 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1442 if (!MCE) {
1443 addExpr(Inst, getImm());
1444 return;
1445 }
1446 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001447 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001448 }
1449
1450 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1451 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001452 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001453 }
1454
1455 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1456 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001457 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001458 }
1459
1460 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1461 assert(N == 1 && "Invalid number of operands!");
1462
Jim Grosbache9119e42015-05-13 18:37:00 +00001463 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001464 }
1465
1466 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1467 assert(N == 1 && "Invalid number of operands!");
1468
Jim Grosbache9119e42015-05-13 18:37:00 +00001469 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001470 }
1471
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001472 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1473 assert(N == 1 && "Invalid number of operands!");
1474
1475 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1476 }
1477
1478 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001479 assert(N == 1 && "Invalid number of operands!");
1480
Jim Grosbache9119e42015-05-13 18:37:00 +00001481 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001482 }
1483
1484 void addSysCROperands(MCInst &Inst, unsigned N) const {
1485 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001486 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001487 }
1488
1489 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1490 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001491 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001492 }
1493
Oliver Stannarda34e4702015-12-01 10:48:51 +00001494 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1495 assert(N == 1 && "Invalid number of operands!");
1496 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1497 }
1498
Tim Northover3b0846e2014-05-24 12:50:23 +00001499 void addShifterOperands(MCInst &Inst, unsigned N) const {
1500 assert(N == 1 && "Invalid number of operands!");
1501 unsigned Imm =
1502 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001503 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001504 }
1505
1506 void addExtendOperands(MCInst &Inst, unsigned N) const {
1507 assert(N == 1 && "Invalid number of operands!");
1508 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1509 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1510 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001511 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001512 }
1513
1514 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1515 assert(N == 1 && "Invalid number of operands!");
1516 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1517 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1518 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001519 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001520 }
1521
1522 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1523 assert(N == 2 && "Invalid number of operands!");
1524 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1525 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001526 Inst.addOperand(MCOperand::createImm(IsSigned));
1527 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001528 }
1529
1530 // For 8-bit load/store instructions with a register offset, both the
1531 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1532 // they're disambiguated by whether the shift was explicit or implicit rather
1533 // than its size.
1534 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1535 assert(N == 2 && "Invalid number of operands!");
1536 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1537 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001538 Inst.addOperand(MCOperand::createImm(IsSigned));
1539 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001540 }
1541
1542 template<int Shift>
1543 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1544 assert(N == 1 && "Invalid number of operands!");
1545
1546 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1547 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001548 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001549 }
1550
1551 template<int Shift>
1552 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1553 assert(N == 1 && "Invalid number of operands!");
1554
1555 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1556 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001557 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001558 }
1559
Sam Parker5f934642017-08-31 09:27:04 +00001560 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1561 assert(N == 1 && "Invalid number of operands!");
1562 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1563 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1564 }
1565
1566 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1567 assert(N == 1 && "Invalid number of operands!");
1568 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1569 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1570 }
1571
Tim Northover3b0846e2014-05-24 12:50:23 +00001572 void print(raw_ostream &OS) const override;
1573
David Blaikie960ea3f2014-06-08 16:18:35 +00001574 static std::unique_ptr<AArch64Operand>
1575 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1576 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001577 Op->Tok.Data = Str.data();
1578 Op->Tok.Length = Str.size();
1579 Op->Tok.IsSuffix = IsSuffix;
1580 Op->StartLoc = S;
1581 Op->EndLoc = S;
1582 return Op;
1583 }
1584
David Blaikie960ea3f2014-06-08 16:18:35 +00001585 static std::unique_ptr<AArch64Operand>
Florian Hahnc4422242017-11-07 13:07:50 +00001586 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001587 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001588 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001589 Op->Reg.Kind = Kind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001590 Op->StartLoc = S;
1591 Op->EndLoc = E;
1592 return Op;
1593 }
1594
David Blaikie960ea3f2014-06-08 16:18:35 +00001595 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001596 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1597 SMLoc S, SMLoc E, MCContext &Ctx) {
1598 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1599 Kind == RegKind::SVEPredicateVector) &&
1600 "Invalid vector kind");
Florian Hahn91f11e52017-11-07 16:45:48 +00001601 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1602 Op->Reg.RegNum = RegNum;
1603 Op->Reg.ElementWidth = ElementWidth;
1604 Op->Reg.Kind = Kind;
1605 Op->StartLoc = S;
1606 Op->EndLoc = E;
1607 return Op;
1608 }
1609
1610 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001611 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001612 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1613 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001614 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001615 Op->VectorList.RegNum = RegNum;
1616 Op->VectorList.Count = Count;
1617 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001618 Op->VectorList.ElementWidth = ElementWidth;
1619 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001620 Op->StartLoc = S;
1621 Op->EndLoc = E;
1622 return Op;
1623 }
1624
David Blaikie960ea3f2014-06-08 16:18:35 +00001625 static std::unique_ptr<AArch64Operand>
1626 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1627 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001628 Op->VectorIndex.Val = Idx;
1629 Op->StartLoc = S;
1630 Op->EndLoc = E;
1631 return Op;
1632 }
1633
David Blaikie960ea3f2014-06-08 16:18:35 +00001634 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1635 SMLoc E, MCContext &Ctx) {
1636 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001637 Op->Imm.Val = Val;
1638 Op->StartLoc = S;
1639 Op->EndLoc = E;
1640 return Op;
1641 }
1642
David Blaikie960ea3f2014-06-08 16:18:35 +00001643 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1644 unsigned ShiftAmount,
1645 SMLoc S, SMLoc E,
1646 MCContext &Ctx) {
1647 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001648 Op->ShiftedImm .Val = Val;
1649 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1650 Op->StartLoc = S;
1651 Op->EndLoc = E;
1652 return Op;
1653 }
1654
David Blaikie960ea3f2014-06-08 16:18:35 +00001655 static std::unique_ptr<AArch64Operand>
1656 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1657 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001658 Op->CondCode.Code = Code;
1659 Op->StartLoc = S;
1660 Op->EndLoc = E;
1661 return Op;
1662 }
1663
David Blaikie960ea3f2014-06-08 16:18:35 +00001664 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1665 MCContext &Ctx) {
1666 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001667 Op->FPImm.Val = Val;
1668 Op->StartLoc = S;
1669 Op->EndLoc = S;
1670 return Op;
1671 }
1672
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001673 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1674 StringRef Str,
1675 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001676 MCContext &Ctx) {
1677 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001678 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001679 Op->Barrier.Data = Str.data();
1680 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001681 Op->StartLoc = S;
1682 Op->EndLoc = S;
1683 return Op;
1684 }
1685
Tim Northover7cd58932015-01-22 17:23:04 +00001686 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1687 uint32_t MRSReg,
1688 uint32_t MSRReg,
1689 uint32_t PStateField,
1690 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001691 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001692 Op->SysReg.Data = Str.data();
1693 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001694 Op->SysReg.MRSReg = MRSReg;
1695 Op->SysReg.MSRReg = MSRReg;
1696 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001697 Op->StartLoc = S;
1698 Op->EndLoc = S;
1699 return Op;
1700 }
1701
David Blaikie960ea3f2014-06-08 16:18:35 +00001702 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1703 SMLoc E, MCContext &Ctx) {
1704 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001705 Op->SysCRImm.Val = Val;
1706 Op->StartLoc = S;
1707 Op->EndLoc = E;
1708 return Op;
1709 }
1710
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001711 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1712 StringRef Str,
1713 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001714 MCContext &Ctx) {
1715 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001716 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001717 Op->Barrier.Data = Str.data();
1718 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001719 Op->StartLoc = S;
1720 Op->EndLoc = S;
1721 return Op;
1722 }
1723
Oliver Stannarda34e4702015-12-01 10:48:51 +00001724 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1725 StringRef Str,
1726 SMLoc S,
1727 MCContext &Ctx) {
1728 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1729 Op->PSBHint.Val = Val;
1730 Op->PSBHint.Data = Str.data();
1731 Op->PSBHint.Length = Str.size();
1732 Op->StartLoc = S;
1733 Op->EndLoc = S;
1734 return Op;
1735 }
1736
David Blaikie960ea3f2014-06-08 16:18:35 +00001737 static std::unique_ptr<AArch64Operand>
1738 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1739 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1740 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001741 Op->ShiftExtend.Type = ShOp;
1742 Op->ShiftExtend.Amount = Val;
1743 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1744 Op->StartLoc = S;
1745 Op->EndLoc = E;
1746 return Op;
1747 }
1748};
1749
1750} // end anonymous namespace.
1751
1752void AArch64Operand::print(raw_ostream &OS) const {
1753 switch (Kind) {
1754 case k_FPImm:
1755 OS << "<fpimm " << getFPImm() << "("
1756 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1757 break;
1758 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001759 StringRef Name = getBarrierName();
1760 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001761 OS << "<barrier " << Name << ">";
1762 else
1763 OS << "<barrier invalid #" << getBarrier() << ">";
1764 break;
1765 }
1766 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001767 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001768 break;
1769 case k_ShiftedImm: {
1770 unsigned Shift = getShiftedImmShift();
1771 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001772 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001773 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1774 break;
1775 }
1776 case k_CondCode:
1777 OS << "<condcode " << getCondCode() << ">";
1778 break;
1779 case k_Register:
1780 OS << "<register " << getReg() << ">";
1781 break;
1782 case k_VectorList: {
1783 OS << "<vectorlist ";
1784 unsigned Reg = getVectorListStart();
1785 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1786 OS << Reg + i << " ";
1787 OS << ">";
1788 break;
1789 }
1790 case k_VectorIndex:
1791 OS << "<vectorindex " << getVectorIndex() << ">";
1792 break;
1793 case k_SysReg:
1794 OS << "<sysreg: " << getSysReg() << '>';
1795 break;
1796 case k_Token:
1797 OS << "'" << getToken() << "'";
1798 break;
1799 case k_SysCR:
1800 OS << "c" << getSysCR();
1801 break;
1802 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001803 StringRef Name = getPrefetchName();
1804 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001805 OS << "<prfop " << Name << ">";
1806 else
1807 OS << "<prfop invalid #" << getPrefetch() << ">";
1808 break;
1809 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001810 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001811 OS << getPSBHintName();
1812 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001813 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001814 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1815 << getShiftExtendAmount();
1816 if (!hasShiftExtendAmount())
1817 OS << "<imp>";
1818 OS << '>';
1819 break;
1820 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001821}
1822
1823/// @name Auto-generated Match Functions
1824/// {
1825
1826static unsigned MatchRegisterName(StringRef Name);
1827
1828/// }
1829
Florian Hahnc4422242017-11-07 13:07:50 +00001830static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001831 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001832 .Case("v0", AArch64::Q0)
1833 .Case("v1", AArch64::Q1)
1834 .Case("v2", AArch64::Q2)
1835 .Case("v3", AArch64::Q3)
1836 .Case("v4", AArch64::Q4)
1837 .Case("v5", AArch64::Q5)
1838 .Case("v6", AArch64::Q6)
1839 .Case("v7", AArch64::Q7)
1840 .Case("v8", AArch64::Q8)
1841 .Case("v9", AArch64::Q9)
1842 .Case("v10", AArch64::Q10)
1843 .Case("v11", AArch64::Q11)
1844 .Case("v12", AArch64::Q12)
1845 .Case("v13", AArch64::Q13)
1846 .Case("v14", AArch64::Q14)
1847 .Case("v15", AArch64::Q15)
1848 .Case("v16", AArch64::Q16)
1849 .Case("v17", AArch64::Q17)
1850 .Case("v18", AArch64::Q18)
1851 .Case("v19", AArch64::Q19)
1852 .Case("v20", AArch64::Q20)
1853 .Case("v21", AArch64::Q21)
1854 .Case("v22", AArch64::Q22)
1855 .Case("v23", AArch64::Q23)
1856 .Case("v24", AArch64::Q24)
1857 .Case("v25", AArch64::Q25)
1858 .Case("v26", AArch64::Q26)
1859 .Case("v27", AArch64::Q27)
1860 .Case("v28", AArch64::Q28)
1861 .Case("v29", AArch64::Q29)
1862 .Case("v30", AArch64::Q30)
1863 .Case("v31", AArch64::Q31)
1864 .Default(0);
1865}
1866
Sander de Smalen73937b72018-04-11 07:36:10 +00001867/// Returns an optional pair of (#elements, element-width) if Suffix
1868/// is a valid vector kind. Where the number of elements in a vector
1869/// or the vector width is implicit or explicitly unknown (but still a
1870/// valid suffix kind), 0 is used.
1871static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1872 RegKind VectorKind) {
1873 std::pair<int, int> Res = {-1, -1};
1874
1875 switch (VectorKind) {
1876 case RegKind::NeonVector:
1877 Res =
1878 StringSwitch<std::pair<int, int>>(Suffix.lower())
1879 .Case("", {0, 0})
1880 .Case(".1d", {1, 64})
1881 .Case(".1q", {1, 128})
1882 // '.2h' needed for fp16 scalar pairwise reductions
1883 .Case(".2h", {2, 16})
1884 .Case(".2s", {2, 32})
1885 .Case(".2d", {2, 64})
1886 // '.4b' is another special case for the ARMv8.2a dot product
1887 // operand
1888 .Case(".4b", {4, 8})
1889 .Case(".4h", {4, 16})
1890 .Case(".4s", {4, 32})
1891 .Case(".8b", {8, 8})
1892 .Case(".8h", {8, 16})
1893 .Case(".16b", {16, 8})
1894 // Accept the width neutral ones, too, for verbose syntax. If those
1895 // aren't used in the right places, the token operand won't match so
1896 // all will work out.
1897 .Case(".b", {0, 8})
1898 .Case(".h", {0, 16})
1899 .Case(".s", {0, 32})
1900 .Case(".d", {0, 64})
1901 .Default({-1, -1});
1902 break;
1903 case RegKind::SVEPredicateVector:
1904 case RegKind::SVEDataVector:
1905 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1906 .Case("", {0, 0})
1907 .Case(".b", {0, 8})
1908 .Case(".h", {0, 16})
1909 .Case(".s", {0, 32})
1910 .Case(".d", {0, 64})
1911 .Case(".q", {0, 128})
1912 .Default({-1, -1});
1913 break;
1914 default:
1915 llvm_unreachable("Unsupported RegKind");
1916 }
1917
1918 if (Res == std::make_pair(-1, -1))
1919 return Optional<std::pair<int, int>>();
1920
1921 return Optional<std::pair<int, int>>(Res);
1922}
1923
1924static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1925 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001926}
1927
Florian Hahn91f11e52017-11-07 16:45:48 +00001928static unsigned matchSVEDataVectorRegName(StringRef Name) {
1929 return StringSwitch<unsigned>(Name.lower())
1930 .Case("z0", AArch64::Z0)
1931 .Case("z1", AArch64::Z1)
1932 .Case("z2", AArch64::Z2)
1933 .Case("z3", AArch64::Z3)
1934 .Case("z4", AArch64::Z4)
1935 .Case("z5", AArch64::Z5)
1936 .Case("z6", AArch64::Z6)
1937 .Case("z7", AArch64::Z7)
1938 .Case("z8", AArch64::Z8)
1939 .Case("z9", AArch64::Z9)
1940 .Case("z10", AArch64::Z10)
1941 .Case("z11", AArch64::Z11)
1942 .Case("z12", AArch64::Z12)
1943 .Case("z13", AArch64::Z13)
1944 .Case("z14", AArch64::Z14)
1945 .Case("z15", AArch64::Z15)
1946 .Case("z16", AArch64::Z16)
1947 .Case("z17", AArch64::Z17)
1948 .Case("z18", AArch64::Z18)
1949 .Case("z19", AArch64::Z19)
1950 .Case("z20", AArch64::Z20)
1951 .Case("z21", AArch64::Z21)
1952 .Case("z22", AArch64::Z22)
1953 .Case("z23", AArch64::Z23)
1954 .Case("z24", AArch64::Z24)
1955 .Case("z25", AArch64::Z25)
1956 .Case("z26", AArch64::Z26)
1957 .Case("z27", AArch64::Z27)
1958 .Case("z28", AArch64::Z28)
1959 .Case("z29", AArch64::Z29)
1960 .Case("z30", AArch64::Z30)
1961 .Case("z31", AArch64::Z31)
1962 .Default(0);
1963}
1964
Sander de Smalencd6be962017-12-20 11:02:42 +00001965static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1966 return StringSwitch<unsigned>(Name.lower())
1967 .Case("p0", AArch64::P0)
1968 .Case("p1", AArch64::P1)
1969 .Case("p2", AArch64::P2)
1970 .Case("p3", AArch64::P3)
1971 .Case("p4", AArch64::P4)
1972 .Case("p5", AArch64::P5)
1973 .Case("p6", AArch64::P6)
1974 .Case("p7", AArch64::P7)
1975 .Case("p8", AArch64::P8)
1976 .Case("p9", AArch64::P9)
1977 .Case("p10", AArch64::P10)
1978 .Case("p11", AArch64::P11)
1979 .Case("p12", AArch64::P12)
1980 .Case("p13", AArch64::P13)
1981 .Case("p14", AArch64::P14)
1982 .Case("p15", AArch64::P15)
1983 .Default(0);
1984}
1985
Tim Northover3b0846e2014-05-24 12:50:23 +00001986bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1987 SMLoc &EndLoc) {
1988 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00001989 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00001990 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00001991 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00001992}
1993
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001994// Matches a register name or register alias previously defined by '.req'
1995unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001996 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001997 unsigned RegNum = 0;
1998 if ((RegNum = matchSVEDataVectorRegName(Name)))
1999 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2000
Sander de Smalencd6be962017-12-20 11:02:42 +00002001 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2002 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2003
Sander de Smalenc067c302017-12-20 09:45:45 +00002004 if ((RegNum = MatchNeonVectorRegName(Name)))
2005 return Kind == RegKind::NeonVector ? RegNum : 0;
2006
2007 // The parsed register must be of RegKind Scalar
2008 if ((RegNum = MatchRegisterName(Name)))
2009 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002010
Florian Hahnc4422242017-11-07 13:07:50 +00002011 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002012 // Handle a few common aliases of registers.
2013 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2014 .Case("fp", AArch64::FP)
2015 .Case("lr", AArch64::LR)
2016 .Case("x31", AArch64::XZR)
2017 .Case("w31", AArch64::WZR)
2018 .Default(0))
2019 return Kind == RegKind::Scalar ? RegNum : 0;
2020
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002021 // Check for aliases registered via .req. Canonicalize to lower case.
2022 // That's more consistent since register names are case insensitive, and
2023 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2024 auto Entry = RegisterReqs.find(Name.lower());
2025 if (Entry == RegisterReqs.end())
2026 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002027
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002028 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002029 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002030 RegNum = Entry->getValue().second;
2031 }
2032 return RegNum;
2033}
2034
Sander de Smalen50d87022018-04-19 07:35:08 +00002035/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002036/// Identifier when called, and if it is a register name the token is eaten and
2037/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002038OperandMatchResultTy
2039AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002040 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002041 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002042 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002043 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002044
2045 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002046 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2047 if (Reg == 0)
2048 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002049
Sander de Smalen50d87022018-04-19 07:35:08 +00002050 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002051 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002052 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002053}
2054
Tim Northover3b0846e2014-05-24 12:50:23 +00002055/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002056OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002057AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002058 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002059 SMLoc S = getLoc();
2060
2061 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2062 Error(S, "Expected cN operand where 0 <= N <= 15");
2063 return MatchOperand_ParseFail;
2064 }
2065
2066 StringRef Tok = Parser.getTok().getIdentifier();
2067 if (Tok[0] != 'c' && Tok[0] != 'C') {
2068 Error(S, "Expected cN operand where 0 <= N <= 15");
2069 return MatchOperand_ParseFail;
2070 }
2071
2072 uint32_t CRNum;
2073 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2074 if (BadNum || CRNum > 15) {
2075 Error(S, "Expected cN operand where 0 <= N <= 15");
2076 return MatchOperand_ParseFail;
2077 }
2078
2079 Parser.Lex(); // Eat identifier token.
2080 Operands.push_back(
2081 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2082 return MatchOperand_Success;
2083}
2084
2085/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002086OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002087AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002088 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002089 SMLoc S = getLoc();
2090 const AsmToken &Tok = Parser.getTok();
2091 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002092 // Eat optional hash.
2093 if (parseOptionalToken(AsmToken::Hash) ||
2094 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002095 const MCExpr *ImmVal;
2096 if (getParser().parseExpression(ImmVal))
2097 return MatchOperand_ParseFail;
2098
2099 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2100 if (!MCE) {
2101 TokError("immediate value expected for prefetch operand");
2102 return MatchOperand_ParseFail;
2103 }
2104 unsigned prfop = MCE->getValue();
2105 if (prfop > 31) {
2106 TokError("prefetch operand out of range, [0,31] expected");
2107 return MatchOperand_ParseFail;
2108 }
2109
Tim Northovere6ae6762016-07-05 21:23:04 +00002110 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2111 Operands.push_back(AArch64Operand::CreatePrefetch(
2112 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002113 return MatchOperand_Success;
2114 }
2115
2116 if (Tok.isNot(AsmToken::Identifier)) {
2117 TokError("pre-fetch hint expected");
2118 return MatchOperand_ParseFail;
2119 }
2120
Tim Northovere6ae6762016-07-05 21:23:04 +00002121 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2122 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002123 TokError("pre-fetch hint expected");
2124 return MatchOperand_ParseFail;
2125 }
2126
2127 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002128 Operands.push_back(AArch64Operand::CreatePrefetch(
2129 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002130 return MatchOperand_Success;
2131}
2132
Oliver Stannarda34e4702015-12-01 10:48:51 +00002133/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002134OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002135AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2136 MCAsmParser &Parser = getParser();
2137 SMLoc S = getLoc();
2138 const AsmToken &Tok = Parser.getTok();
2139 if (Tok.isNot(AsmToken::Identifier)) {
2140 TokError("invalid operand for instruction");
2141 return MatchOperand_ParseFail;
2142 }
2143
Tim Northovere6ae6762016-07-05 21:23:04 +00002144 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2145 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002146 TokError("invalid operand for instruction");
2147 return MatchOperand_ParseFail;
2148 }
2149
2150 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002151 Operands.push_back(AArch64Operand::CreatePSBHint(
2152 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002153 return MatchOperand_Success;
2154}
2155
Tim Northover3b0846e2014-05-24 12:50:23 +00002156/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2157/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002158OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002159AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002160 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002161 SMLoc S = getLoc();
2162 const MCExpr *Expr;
2163
2164 if (Parser.getTok().is(AsmToken::Hash)) {
2165 Parser.Lex(); // Eat hash token.
2166 }
2167
2168 if (parseSymbolicImmVal(Expr))
2169 return MatchOperand_ParseFail;
2170
2171 AArch64MCExpr::VariantKind ELFRefKind;
2172 MCSymbolRefExpr::VariantKind DarwinRefKind;
2173 int64_t Addend;
2174 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2175 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2176 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2177 // No modifier was specified at all; this is the syntax for an ELF basic
2178 // ADRP relocation (unfortunately).
2179 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002180 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002181 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2182 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2183 Addend != 0) {
2184 Error(S, "gotpage label reference not allowed an addend");
2185 return MatchOperand_ParseFail;
2186 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2187 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2188 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2189 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2190 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2191 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2192 // The operand must be an @page or @gotpage qualified symbolref.
2193 Error(S, "page or gotpage label reference expected");
2194 return MatchOperand_ParseFail;
2195 }
2196 }
2197
2198 // We have either a label reference possibly with addend or an immediate. The
2199 // addend is a raw value here. The linker will adjust it to only reference the
2200 // page.
2201 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2202 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2203
2204 return MatchOperand_Success;
2205}
2206
2207/// tryParseAdrLabel - Parse and validate a source label for the ADR
2208/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002209OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002210AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2211 SMLoc S = getLoc();
2212 const MCExpr *Expr;
2213
Nirav Davee833c6c2016-11-08 18:31:04 +00002214 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002215 if (getParser().parseExpression(Expr))
2216 return MatchOperand_ParseFail;
2217
2218 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2219 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2220
2221 return MatchOperand_Success;
2222}
2223
2224/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002225OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002226AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002227 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002228 SMLoc S = getLoc();
2229
Nirav Davee833c6c2016-11-08 18:31:04 +00002230 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002231
2232 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002233 bool isNegative = parseOptionalToken(AsmToken::Minus);
2234
Tim Northover3b0846e2014-05-24 12:50:23 +00002235 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002236 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002237 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002238 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002239 Val = Tok.getIntVal();
2240 if (Val > 255 || Val < 0) {
2241 TokError("encoded floating point value out of range");
2242 return MatchOperand_ParseFail;
2243 }
2244 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002245 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002246 if (isNegative)
2247 RealVal.changeSign();
2248
Tim Northover3b0846e2014-05-24 12:50:23 +00002249 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002250 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002251
John Brawn5ca5daa2017-04-20 10:13:54 +00002252 // Check for out of range values. As an exception we let Zero through,
2253 // but as tokens instead of an FPImm so that it can be matched by the
2254 // appropriate alias if one exists.
2255 if (RealVal.isPosZero()) {
2256 Parser.Lex(); // Eat the token.
2257 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2258 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2259 return MatchOperand_Success;
2260 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002261 TokError("expected compatible register or floating-point constant");
2262 return MatchOperand_ParseFail;
2263 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002264 }
2265 Parser.Lex(); // Eat the token.
2266 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2267 return MatchOperand_Success;
2268 }
2269
2270 if (!Hash)
2271 return MatchOperand_NoMatch;
2272
2273 TokError("invalid floating point immediate");
2274 return MatchOperand_ParseFail;
2275}
2276
2277/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002278OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002279AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002280 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002281 SMLoc S = getLoc();
2282
2283 if (Parser.getTok().is(AsmToken::Hash))
2284 Parser.Lex(); // Eat '#'
2285 else if (Parser.getTok().isNot(AsmToken::Integer))
2286 // Operand should start from # or should be integer, emit error otherwise.
2287 return MatchOperand_NoMatch;
2288
2289 const MCExpr *Imm;
2290 if (parseSymbolicImmVal(Imm))
2291 return MatchOperand_ParseFail;
2292 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2293 uint64_t ShiftAmount = 0;
2294 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2295 if (MCE) {
2296 int64_t Val = MCE->getValue();
2297 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002298 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002299 ShiftAmount = 12;
2300 }
2301 }
2302 SMLoc E = Parser.getTok().getLoc();
2303 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2304 getContext()));
2305 return MatchOperand_Success;
2306 }
2307
2308 // Eat ','
2309 Parser.Lex();
2310
2311 // The optional operand must be "lsl #N" where N is non-negative.
2312 if (!Parser.getTok().is(AsmToken::Identifier) ||
2313 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2314 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2315 return MatchOperand_ParseFail;
2316 }
2317
2318 // Eat 'lsl'
2319 Parser.Lex();
2320
Nirav Davee833c6c2016-11-08 18:31:04 +00002321 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002322
2323 if (Parser.getTok().isNot(AsmToken::Integer)) {
2324 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2325 return MatchOperand_ParseFail;
2326 }
2327
2328 int64_t ShiftAmount = Parser.getTok().getIntVal();
2329
2330 if (ShiftAmount < 0) {
2331 Error(Parser.getTok().getLoc(), "positive shift amount required");
2332 return MatchOperand_ParseFail;
2333 }
2334 Parser.Lex(); // Eat the number
2335
2336 SMLoc E = Parser.getTok().getLoc();
2337 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2338 S, E, getContext()));
2339 return MatchOperand_Success;
2340}
2341
2342/// parseCondCodeString - Parse a Condition Code string.
2343AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2344 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2345 .Case("eq", AArch64CC::EQ)
2346 .Case("ne", AArch64CC::NE)
2347 .Case("cs", AArch64CC::HS)
2348 .Case("hs", AArch64CC::HS)
2349 .Case("cc", AArch64CC::LO)
2350 .Case("lo", AArch64CC::LO)
2351 .Case("mi", AArch64CC::MI)
2352 .Case("pl", AArch64CC::PL)
2353 .Case("vs", AArch64CC::VS)
2354 .Case("vc", AArch64CC::VC)
2355 .Case("hi", AArch64CC::HI)
2356 .Case("ls", AArch64CC::LS)
2357 .Case("ge", AArch64CC::GE)
2358 .Case("lt", AArch64CC::LT)
2359 .Case("gt", AArch64CC::GT)
2360 .Case("le", AArch64CC::LE)
2361 .Case("al", AArch64CC::AL)
2362 .Case("nv", AArch64CC::NV)
2363 .Default(AArch64CC::Invalid);
2364 return CC;
2365}
2366
2367/// parseCondCode - Parse a Condition Code operand.
2368bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2369 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002370 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002371 SMLoc S = getLoc();
2372 const AsmToken &Tok = Parser.getTok();
2373 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2374
2375 StringRef Cond = Tok.getString();
2376 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2377 if (CC == AArch64CC::Invalid)
2378 return TokError("invalid condition code");
2379 Parser.Lex(); // Eat identifier token.
2380
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002381 if (invertCondCode) {
2382 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2383 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002384 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002385 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002386
2387 Operands.push_back(
2388 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2389 return false;
2390}
2391
2392/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2393/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002394OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002395AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002396 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002397 const AsmToken &Tok = Parser.getTok();
2398 std::string LowerID = Tok.getString().lower();
2399 AArch64_AM::ShiftExtendType ShOp =
2400 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2401 .Case("lsl", AArch64_AM::LSL)
2402 .Case("lsr", AArch64_AM::LSR)
2403 .Case("asr", AArch64_AM::ASR)
2404 .Case("ror", AArch64_AM::ROR)
2405 .Case("msl", AArch64_AM::MSL)
2406 .Case("uxtb", AArch64_AM::UXTB)
2407 .Case("uxth", AArch64_AM::UXTH)
2408 .Case("uxtw", AArch64_AM::UXTW)
2409 .Case("uxtx", AArch64_AM::UXTX)
2410 .Case("sxtb", AArch64_AM::SXTB)
2411 .Case("sxth", AArch64_AM::SXTH)
2412 .Case("sxtw", AArch64_AM::SXTW)
2413 .Case("sxtx", AArch64_AM::SXTX)
2414 .Default(AArch64_AM::InvalidShiftExtend);
2415
2416 if (ShOp == AArch64_AM::InvalidShiftExtend)
2417 return MatchOperand_NoMatch;
2418
2419 SMLoc S = Tok.getLoc();
2420 Parser.Lex();
2421
Nirav Davee833c6c2016-11-08 18:31:04 +00002422 bool Hash = parseOptionalToken(AsmToken::Hash);
2423
Tim Northover3b0846e2014-05-24 12:50:23 +00002424 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2425 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2426 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2427 ShOp == AArch64_AM::MSL) {
2428 // We expect a number here.
2429 TokError("expected #imm after shift specifier");
2430 return MatchOperand_ParseFail;
2431 }
2432
Chad Rosier2ff37b82016-12-27 16:58:09 +00002433 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002434 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2435 Operands.push_back(
2436 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2437 return MatchOperand_Success;
2438 }
2439
Chad Rosier2ff37b82016-12-27 16:58:09 +00002440 // Make sure we do actually have a number, identifier or a parenthesized
2441 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002442 SMLoc E = Parser.getTok().getLoc();
2443 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002444 !Parser.getTok().is(AsmToken::LParen) &&
2445 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002446 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002447 return MatchOperand_ParseFail;
2448 }
2449
2450 const MCExpr *ImmVal;
2451 if (getParser().parseExpression(ImmVal))
2452 return MatchOperand_ParseFail;
2453
2454 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2455 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002456 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002457 return MatchOperand_ParseFail;
2458 }
2459
Jim Grosbach57fd2622014-09-23 22:16:02 +00002460 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002461 Operands.push_back(AArch64Operand::CreateShiftExtend(
2462 ShOp, MCE->getValue(), true, S, E, getContext()));
2463 return MatchOperand_Success;
2464}
2465
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002466static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2467 if (FBS[AArch64::HasV8_1aOps])
2468 Str += "ARMv8.1a";
2469 else if (FBS[AArch64::HasV8_2aOps])
2470 Str += "ARMv8.2a";
2471 else
2472 Str += "(unknown)";
2473}
2474
2475void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2476 SMLoc S) {
2477 const uint16_t Op2 = Encoding & 7;
2478 const uint16_t Cm = (Encoding & 0x78) >> 3;
2479 const uint16_t Cn = (Encoding & 0x780) >> 7;
2480 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2481
2482 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2483
2484 Operands.push_back(
2485 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2486 Operands.push_back(
2487 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2488 Operands.push_back(
2489 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2490 Expr = MCConstantExpr::create(Op2, getContext());
2491 Operands.push_back(
2492 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2493}
2494
Tim Northover3b0846e2014-05-24 12:50:23 +00002495/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2496/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2497bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2498 OperandVector &Operands) {
2499 if (Name.find('.') != StringRef::npos)
2500 return TokError("invalid operand");
2501
2502 Mnemonic = Name;
2503 Operands.push_back(
2504 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2505
Rafael Espindola961d4692014-11-11 05:18:41 +00002506 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002507 const AsmToken &Tok = Parser.getTok();
2508 StringRef Op = Tok.getString();
2509 SMLoc S = Tok.getLoc();
2510
Tim Northover3b0846e2014-05-24 12:50:23 +00002511 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002512 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2513 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002514 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002515 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2516 std::string Str("IC " + std::string(IC->Name) + " requires ");
2517 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2518 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002519 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002520 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002521 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002522 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2523 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002524 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002525 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2526 std::string Str("DC " + std::string(DC->Name) + " requires ");
2527 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2528 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002529 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002530 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002531 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002532 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2533 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002534 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002535 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2536 std::string Str("AT " + std::string(AT->Name) + " requires ");
2537 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2538 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002539 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002540 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002541 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002542 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2543 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002544 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002545 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2546 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2547 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2548 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002549 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002550 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002551 }
2552
Tim Northover3b0846e2014-05-24 12:50:23 +00002553 Parser.Lex(); // Eat operand.
2554
2555 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2556 bool HasRegister = false;
2557
2558 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002559 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002560 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2561 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002562 HasRegister = true;
2563 }
2564
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002565 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002566 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002567 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002568 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002569
Nirav Davee833c6c2016-11-08 18:31:04 +00002570 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2571 return true;
2572
Tim Northover3b0846e2014-05-24 12:50:23 +00002573 return false;
2574}
2575
Alex Bradbury58eba092016-11-01 16:32:05 +00002576OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002577AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002578 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002579 const AsmToken &Tok = Parser.getTok();
2580
2581 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002582 if (parseOptionalToken(AsmToken::Hash) ||
2583 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002584 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002585 const MCExpr *ImmVal;
2586 SMLoc ExprLoc = getLoc();
2587 if (getParser().parseExpression(ImmVal))
2588 return MatchOperand_ParseFail;
2589 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2590 if (!MCE) {
2591 Error(ExprLoc, "immediate value expected for barrier operand");
2592 return MatchOperand_ParseFail;
2593 }
2594 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2595 Error(ExprLoc, "barrier operand out of range");
2596 return MatchOperand_ParseFail;
2597 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002598 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2599 Operands.push_back(AArch64Operand::CreateBarrier(
2600 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002601 return MatchOperand_Success;
2602 }
2603
2604 if (Tok.isNot(AsmToken::Identifier)) {
2605 TokError("invalid operand for instruction");
2606 return MatchOperand_ParseFail;
2607 }
2608
Tim Northover3b0846e2014-05-24 12:50:23 +00002609 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002610 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2611 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002612 TokError("'sy' or #imm operand expected");
2613 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002614 } else if (!DB) {
2615 TokError("invalid barrier option name");
2616 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002617 }
2618
Tim Northovere6ae6762016-07-05 21:23:04 +00002619 Operands.push_back(AArch64Operand::CreateBarrier(
2620 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002621 Parser.Lex(); // Consume the option
2622
2623 return MatchOperand_Success;
2624}
2625
Alex Bradbury58eba092016-11-01 16:32:05 +00002626OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002627AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002628 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002629 const AsmToken &Tok = Parser.getTok();
2630
2631 if (Tok.isNot(AsmToken::Identifier))
2632 return MatchOperand_NoMatch;
2633
Tim Northovere6ae6762016-07-05 21:23:04 +00002634 int MRSReg, MSRReg;
2635 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2636 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2637 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2638 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2639 } else
2640 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002641
Tim Northovere6ae6762016-07-05 21:23:04 +00002642 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2643 unsigned PStateImm = -1;
2644 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2645 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002646
Tim Northovere6ae6762016-07-05 21:23:04 +00002647 Operands.push_back(
2648 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2649 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002650 Parser.Lex(); // Eat identifier
2651
2652 return MatchOperand_Success;
2653}
2654
Florian Hahnc4422242017-11-07 13:07:50 +00002655/// tryParseNeonVectorRegister - Parse a vector register operand.
2656bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002657 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002658 if (Parser.getTok().isNot(AsmToken::Identifier))
2659 return true;
2660
2661 SMLoc S = getLoc();
2662 // Check for a vector register specifier first.
2663 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002664 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002665 OperandMatchResultTy Res =
2666 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2667 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002668 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002669
2670 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2671 if (!KindRes)
2672 return true;
2673
2674 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002675 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002676 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2677 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002678
Tim Northover3b0846e2014-05-24 12:50:23 +00002679 // If there was an explicit qualifier, that goes on as a literal text
2680 // operand.
2681 if (!Kind.empty())
2682 Operands.push_back(
2683 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2684
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002685 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2686}
2687
2688OperandMatchResultTy
2689AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002690 SMLoc SIdx = getLoc();
2691 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002692 const MCExpr *ImmVal;
2693 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002694 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002695 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2696 if (!MCE) {
2697 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002698 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002699 }
2700
2701 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002702
Nirav Davee833c6c2016-11-08 18:31:04 +00002703 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002704 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002705
2706 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2707 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002708 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002709 }
2710
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002711 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002712}
2713
Sander de Smalen73937b72018-04-11 07:36:10 +00002714// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002715// optional kind specifier. If it is a register specifier, eat the token
2716// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002717OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002718AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002719 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002720 MCAsmParser &Parser = getParser();
2721 const AsmToken &Tok = Parser.getTok();
2722
Florian Hahn91f11e52017-11-07 16:45:48 +00002723 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002724 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002725
2726 StringRef Name = Tok.getString();
2727 // If there is a kind specifier, it's separated from the register name by
2728 // a '.'.
2729 size_t Start = 0, Next = Name.find('.');
2730 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002731 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002732
2733 if (RegNum) {
2734 if (Next != StringRef::npos) {
2735 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002736 if (!isValidVectorKind(Kind, MatchKind)) {
2737 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002738 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002739 }
2740 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002741 Parser.Lex(); // Eat the register token.
2742
2743 Reg = RegNum;
2744 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002745 }
2746
Sander de Smalen8e607342017-11-15 15:44:43 +00002747 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002748}
2749
Sander de Smalencd6be962017-12-20 11:02:42 +00002750/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2751OperandMatchResultTy
2752AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2753 // Check for a SVE predicate register specifier first.
2754 const SMLoc S = getLoc();
2755 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002756 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002757 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002758 if (Res != MatchOperand_Success)
2759 return Res;
2760
Sander de Smalen73937b72018-04-11 07:36:10 +00002761 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2762 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002763 return MatchOperand_NoMatch;
2764
Sander de Smalen73937b72018-04-11 07:36:10 +00002765 unsigned ElementWidth = KindRes->second;
2766 Operands.push_back(AArch64Operand::CreateVectorReg(
2767 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2768 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002769
Sander de Smalen7868e742018-01-09 11:17:06 +00002770 // Not all predicates are followed by a '/m' or '/z'.
2771 MCAsmParser &Parser = getParser();
2772 if (Parser.getTok().isNot(AsmToken::Slash))
2773 return MatchOperand_Success;
2774
2775 // But when they do they shouldn't have an element type suffix.
2776 if (!Kind.empty()) {
2777 Error(S, "not expecting size suffix");
2778 return MatchOperand_ParseFail;
2779 }
2780
2781 // Add a literal slash as operand
2782 Operands.push_back(
2783 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2784
2785 Parser.Lex(); // Eat the slash.
2786
2787 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002788 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002789 if (Pred != "z" && Pred != "m") {
2790 Error(getLoc(), "expecting 'm' or 'z' predication");
2791 return MatchOperand_ParseFail;
2792 }
2793
2794 // Add zero/merge token.
2795 const char *ZM = Pred == "z" ? "z" : "m";
2796 Operands.push_back(
2797 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2798
2799 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002800 return MatchOperand_Success;
2801}
2802
Sander de Smalen50d87022018-04-19 07:35:08 +00002803/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002804bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2805 SMLoc S = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002806 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002807 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002808 return false;
2809
2810 // Try for a scalar register.
Sander de Smalen50d87022018-04-19 07:35:08 +00002811 unsigned Reg;
2812 if (tryParseScalarRegister(Reg) != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002813 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002814 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2815 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002816
Tim Northover3b0846e2014-05-24 12:50:23 +00002817 return false;
2818}
2819
2820bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002821 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002822 bool HasELFModifier = false;
2823 AArch64MCExpr::VariantKind RefKind;
2824
Nirav Davee833c6c2016-11-08 18:31:04 +00002825 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002826 HasELFModifier = true;
2827
Nirav Davee833c6c2016-11-08 18:31:04 +00002828 if (Parser.getTok().isNot(AsmToken::Identifier))
2829 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002830
2831 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2832 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2833 .Case("lo12", AArch64MCExpr::VK_LO12)
2834 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2835 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2836 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2837 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2838 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2839 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2840 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2841 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2842 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2843 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2844 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2845 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2846 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2847 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2848 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2849 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2850 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2851 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2852 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2853 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2854 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2855 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2856 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2857 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2858 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2859 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2860 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2861 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2862 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2863 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2864 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2865 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2866 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2867 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002868 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2869 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002870 .Default(AArch64MCExpr::VK_INVALID);
2871
Nirav Davee833c6c2016-11-08 18:31:04 +00002872 if (RefKind == AArch64MCExpr::VK_INVALID)
2873 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002874
2875 Parser.Lex(); // Eat identifier
2876
Nirav Davee833c6c2016-11-08 18:31:04 +00002877 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002878 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002879 }
2880
2881 if (getParser().parseExpression(ImmVal))
2882 return true;
2883
2884 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002885 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002886
2887 return false;
2888}
2889
Sander de Smalen650234b2018-04-12 11:40:52 +00002890template <RegKind VectorKind>
2891OperandMatchResultTy
2892AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
2893 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002894 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00002895 if (!Parser.getTok().is(AsmToken::LCurly))
2896 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002897
2898 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00002899 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00002900 bool NoMatchIsError) {
2901 auto RegTok = Parser.getTok();
2902 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
2903 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002904 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00002905 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002906 llvm_unreachable("Expected a valid vector kind");
2907 }
2908
Sander de Smalen650234b2018-04-12 11:40:52 +00002909 if (RegTok.isNot(AsmToken::Identifier) ||
2910 ParseRes == MatchOperand_ParseFail ||
2911 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
2912 Error(Loc, "vector register expected");
2913 return MatchOperand_ParseFail;
2914 }
2915
2916 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002917 };
2918
Tim Northover3b0846e2014-05-24 12:50:23 +00002919 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00002920 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00002921 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00002922
Tim Northover3b0846e2014-05-24 12:50:23 +00002923 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002924 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002925 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
2926
2927 // Put back the original left bracket if there was no match, so that
2928 // different types of list-operands can be matched (e.g. SVE, Neon).
2929 if (ParseRes == MatchOperand_NoMatch)
2930 Parser.getLexer().UnLex(LCurly);
2931
2932 if (ParseRes != MatchOperand_Success)
2933 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002934
Tim Northover3b0846e2014-05-24 12:50:23 +00002935 int64_t PrevReg = FirstReg;
2936 unsigned Count = 1;
2937
Nirav Davee833c6c2016-11-08 18:31:04 +00002938 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002939 SMLoc Loc = getLoc();
2940 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002941
Sander de Smalen50d87022018-04-19 07:35:08 +00002942 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002943 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2944 if (ParseRes != MatchOperand_Success)
2945 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002946
Tim Northover3b0846e2014-05-24 12:50:23 +00002947 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002948 if (Kind != NextKind) {
2949 Error(Loc, "mismatched register size suffix");
2950 return MatchOperand_ParseFail;
2951 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002952
2953 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2954
2955 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002956 Error(Loc, "invalid number of vectors");
2957 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002958 }
2959
2960 Count += Space;
2961 }
2962 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002963 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002964 SMLoc Loc = getLoc();
2965 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002966 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002967 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2968 if (ParseRes != MatchOperand_Success)
2969 return ParseRes;
2970
Tim Northover3b0846e2014-05-24 12:50:23 +00002971 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002972 if (Kind != NextKind) {
2973 Error(Loc, "mismatched register size suffix");
2974 return MatchOperand_ParseFail;
2975 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002976
2977 // Registers must be incremental (with wraparound at 31)
2978 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00002979 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
2980 Error(Loc, "registers must be sequential");
2981 return MatchOperand_ParseFail;
2982 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002983
2984 PrevReg = Reg;
2985 ++Count;
2986 }
2987 }
2988
Nirav Davee833c6c2016-11-08 18:31:04 +00002989 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00002990 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002991
Sander de Smalen650234b2018-04-12 11:40:52 +00002992 if (Count > 4) {
2993 Error(S, "invalid number of vectors");
2994 return MatchOperand_ParseFail;
2995 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002996
2997 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00002998 unsigned ElementWidth = 0;
2999 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003000 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003001 std::tie(NumElements, ElementWidth) = *VK;
3002 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003003
3004 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003005 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3006 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003007
Sander de Smalen650234b2018-04-12 11:40:52 +00003008 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003009}
3010
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003011/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3012bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003013 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3014 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003015 return true;
3016
3017 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3018}
3019
Alex Bradbury58eba092016-11-01 16:32:05 +00003020OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003021AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003022 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003023
Sander de Smalen50d87022018-04-19 07:35:08 +00003024 unsigned RegNum;
3025 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3026 if (Res != MatchOperand_Success)
3027 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003028
Nirav Davee833c6c2016-11-08 18:31:04 +00003029 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003030 Operands.push_back(AArch64Operand::CreateReg(
3031 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003032 return MatchOperand_Success;
3033 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003034
Nirav Davee833c6c2016-11-08 18:31:04 +00003035 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003036
Sander de Smalen50d87022018-04-19 07:35:08 +00003037 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003038 Error(getLoc(), "index must be absent or #0");
3039 return MatchOperand_ParseFail;
3040 }
3041
3042 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003043 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003044 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3045 Error(getLoc(), "index must be absent or #0");
3046 return MatchOperand_ParseFail;
3047 }
3048
Sander de Smalen50d87022018-04-19 07:35:08 +00003049 Operands.push_back(AArch64Operand::CreateReg(
3050 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003051 return MatchOperand_Success;
3052}
3053
Sander de Smalen5c625982018-04-13 12:56:14 +00003054bool AArch64AsmParser::parseOptionalMulVl(OperandVector &Operands) {
3055 MCAsmParser &Parser = getParser();
3056
3057 // Some SVE instructions have a decoration after the immediate, i.e.
3058 // "mul vl". We parse them here and add tokens, which must be present in the
3059 // asm string in the tablegen instruction.
3060 if (!Parser.getTok().getString().equals_lower("mul") ||
3061 !Parser.getLexer().peekTok().getString().equals_lower("vl"))
3062 return true;
3063
3064 SMLoc S = getLoc();
3065 Operands.push_back(
3066 AArch64Operand::CreateToken("mul", false, S, getContext()));
3067 Parser.Lex(); // Eat the "mul"
3068
3069 S = getLoc();
3070 Operands.push_back(
3071 AArch64Operand::CreateToken("vl", false, S, getContext()));
3072 Parser.Lex(); // Eat the "vl"
3073
3074 return false;
3075}
3076
Tim Northover3b0846e2014-05-24 12:50:23 +00003077/// parseOperand - Parse a arm instruction operand. For now this parses the
3078/// operand regardless of the mnemonic.
3079bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3080 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003081 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003082
3083 OperandMatchResultTy ResTy =
3084 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3085
Tim Northover3b0846e2014-05-24 12:50:23 +00003086 // Check if the current operand has a custom associated parser, if so, try to
3087 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003088 if (ResTy == MatchOperand_Success)
3089 return false;
3090 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3091 // there was a match, but an error occurred, in which case, just return that
3092 // the operand parsing failed.
3093 if (ResTy == MatchOperand_ParseFail)
3094 return true;
3095
3096 // Nothing custom, so do general case parsing.
3097 SMLoc S, E;
3098 switch (getLexer().getKind()) {
3099 default: {
3100 SMLoc S = getLoc();
3101 const MCExpr *Expr;
3102 if (parseSymbolicImmVal(Expr))
3103 return Error(S, "invalid operand");
3104
3105 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3106 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3107 return false;
3108 }
3109 case AsmToken::LBrac: {
3110 SMLoc Loc = Parser.getTok().getLoc();
3111 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3112 getContext()));
3113 Parser.Lex(); // Eat '['
3114
3115 // There's no comma after a '[', so we can parse the next operand
3116 // immediately.
3117 return parseOperand(Operands, false, false);
3118 }
3119 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003120 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003121 case AsmToken::Identifier: {
3122 // If we're expecting a Condition Code operand, then just parse that.
3123 if (isCondCode)
3124 return parseCondCode(Operands, invertCondCode);
3125
3126 // If it's a register name, parse it.
3127 if (!parseRegister(Operands))
3128 return false;
3129
Sander de Smalen5c625982018-04-13 12:56:14 +00003130 // See if this is a "mul vl" decoration used by SVE instructions.
3131 if (!parseOptionalMulVl(Operands))
3132 return false;
3133
Tim Northover3b0846e2014-05-24 12:50:23 +00003134 // This could be an optional "shift" or "extend" operand.
3135 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3136 // We can only continue if no tokens were eaten.
3137 if (GotShift != MatchOperand_NoMatch)
3138 return GotShift;
3139
3140 // This was not a register so parse other operands that start with an
3141 // identifier (like labels) as expressions and create them as immediates.
3142 const MCExpr *IdVal;
3143 S = getLoc();
3144 if (getParser().parseExpression(IdVal))
3145 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003146 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3147 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3148 return false;
3149 }
3150 case AsmToken::Integer:
3151 case AsmToken::Real:
3152 case AsmToken::Hash: {
3153 // #42 -> immediate.
3154 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003155
3156 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003157
3158 // Parse a negative sign
3159 bool isNegative = false;
3160 if (Parser.getTok().is(AsmToken::Minus)) {
3161 isNegative = true;
3162 // We need to consume this token only when we have a Real, otherwise
3163 // we let parseSymbolicImmVal take care of it
3164 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3165 Parser.Lex();
3166 }
3167
3168 // The only Real that should come through here is a literal #0.0 for
3169 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3170 // so convert the value.
3171 const AsmToken &Tok = Parser.getTok();
3172 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003173 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003174 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3175 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3176 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3177 Mnemonic != "fcmlt")
3178 return TokError("unexpected floating point literal");
3179 else if (IntVal != 0 || isNegative)
3180 return TokError("expected floating-point constant #0.0");
3181 Parser.Lex(); // Eat the token.
3182
3183 Operands.push_back(
3184 AArch64Operand::CreateToken("#0", false, S, getContext()));
3185 Operands.push_back(
3186 AArch64Operand::CreateToken(".0", false, S, getContext()));
3187 return false;
3188 }
3189
3190 const MCExpr *ImmVal;
3191 if (parseSymbolicImmVal(ImmVal))
3192 return true;
3193
3194 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3195 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3196 return false;
3197 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003198 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003199 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003200 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003201 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003202 Parser.Lex(); // Eat '='
3203 const MCExpr *SubExprVal;
3204 if (getParser().parseExpression(SubExprVal))
3205 return true;
3206
David Peixottoae5ba762014-07-18 16:05:14 +00003207 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003208 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003209 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003210
3211 bool IsXReg =
3212 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3213 Operands[1]->getReg());
3214
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003215 MCContext& Ctx = getContext();
3216 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3217 // 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 +00003218 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003219 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3220 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3221 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3222 ShiftAmt += 16;
3223 Imm >>= 16;
3224 }
3225 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3226 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3227 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003228 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003229 if (ShiftAmt)
3230 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3231 ShiftAmt, true, S, E, Ctx));
3232 return false;
3233 }
David Peixottoae5ba762014-07-18 16:05:14 +00003234 APInt Simm = APInt(64, Imm << ShiftAmt);
3235 // check if the immediate is an unsigned or signed 32-bit int for W regs
3236 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3237 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003238 }
3239 // 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 +00003240 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003241 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003242 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3243 return false;
3244 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003245 }
3246}
3247
3248/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3249/// operands.
3250bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3251 StringRef Name, SMLoc NameLoc,
3252 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003253 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003254 Name = StringSwitch<StringRef>(Name.lower())
3255 .Case("beq", "b.eq")
3256 .Case("bne", "b.ne")
3257 .Case("bhs", "b.hs")
3258 .Case("bcs", "b.cs")
3259 .Case("blo", "b.lo")
3260 .Case("bcc", "b.cc")
3261 .Case("bmi", "b.mi")
3262 .Case("bpl", "b.pl")
3263 .Case("bvs", "b.vs")
3264 .Case("bvc", "b.vc")
3265 .Case("bhi", "b.hi")
3266 .Case("bls", "b.ls")
3267 .Case("bge", "b.ge")
3268 .Case("blt", "b.lt")
3269 .Case("bgt", "b.gt")
3270 .Case("ble", "b.le")
3271 .Case("bal", "b.al")
3272 .Case("bnv", "b.nv")
3273 .Default(Name);
3274
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003275 // First check for the AArch64-specific .req directive.
3276 if (Parser.getTok().is(AsmToken::Identifier) &&
3277 Parser.getTok().getIdentifier() == ".req") {
3278 parseDirectiveReq(Name, NameLoc);
3279 // We always return 'error' for this, as we're done with this
3280 // statement and don't need to match the 'instruction."
3281 return true;
3282 }
3283
Tim Northover3b0846e2014-05-24 12:50:23 +00003284 // Create the leading tokens for the mnemonic, split by '.' characters.
3285 size_t Start = 0, Next = Name.find('.');
3286 StringRef Head = Name.slice(Start, Next);
3287
3288 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003289 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3290 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003291
3292 Operands.push_back(
3293 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3294 Mnemonic = Head;
3295
3296 // Handle condition codes for a branch mnemonic
3297 if (Head == "b" && Next != StringRef::npos) {
3298 Start = Next;
3299 Next = Name.find('.', Start + 1);
3300 Head = Name.slice(Start + 1, Next);
3301
3302 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3303 (Head.data() - Name.data()));
3304 AArch64CC::CondCode CC = parseCondCodeString(Head);
3305 if (CC == AArch64CC::Invalid)
3306 return Error(SuffixLoc, "invalid condition code");
3307 Operands.push_back(
3308 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3309 Operands.push_back(
3310 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3311 }
3312
3313 // Add the remaining tokens in the mnemonic.
3314 while (Next != StringRef::npos) {
3315 Start = Next;
3316 Next = Name.find('.', Start + 1);
3317 Head = Name.slice(Start, Next);
3318 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3319 (Head.data() - Name.data()) + 1);
3320 Operands.push_back(
3321 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3322 }
3323
3324 // Conditional compare instructions have a Condition Code operand, which needs
3325 // to be parsed and an immediate operand created.
3326 bool condCodeFourthOperand =
3327 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3328 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3329 Head == "csinc" || Head == "csinv" || Head == "csneg");
3330
3331 // These instructions are aliases to some of the conditional select
3332 // instructions. However, the condition code is inverted in the aliased
3333 // instruction.
3334 //
3335 // FIXME: Is this the correct way to handle these? Or should the parser
3336 // generate the aliased instructions directly?
3337 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3338 bool condCodeThirdOperand =
3339 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3340
3341 // Read the remaining operands.
3342 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3343 // Read the first operand.
3344 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003345 return true;
3346 }
3347
3348 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003349 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003350 // Parse and remember the operand.
3351 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3352 (N == 3 && condCodeThirdOperand) ||
3353 (N == 2 && condCodeSecondOperand),
3354 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003355 return true;
3356 }
3357
3358 // After successfully parsing some operands there are two special cases to
3359 // consider (i.e. notional operands not separated by commas). Both are due
3360 // to memory specifiers:
3361 // + An RBrac will end an address for load/store/prefetch
3362 // + An '!' will indicate a pre-indexed operation.
3363 //
3364 // It's someone else's responsibility to make sure these tokens are sane
3365 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003366
Nirav Davee833c6c2016-11-08 18:31:04 +00003367 SMLoc RLoc = Parser.getTok().getLoc();
3368 if (parseOptionalToken(AsmToken::RBrac))
3369 Operands.push_back(
3370 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3371 SMLoc ELoc = Parser.getTok().getLoc();
3372 if (parseOptionalToken(AsmToken::Exclaim))
3373 Operands.push_back(
3374 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003375
3376 ++N;
3377 }
3378 }
3379
Nirav Davee833c6c2016-11-08 18:31:04 +00003380 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3381 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003382
Tim Northover3b0846e2014-05-24 12:50:23 +00003383 return false;
3384}
3385
3386// FIXME: This entire function is a giant hack to provide us with decent
3387// operand range validation/diagnostics until TableGen/MC can be extended
3388// to support autogeneration of this kind of validation.
3389bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3390 SmallVectorImpl<SMLoc> &Loc) {
3391 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3392 // Check for indexed addressing modes w/ the base register being the
3393 // same as a destination/source register or pair load where
3394 // the Rt == Rt2. All of those are undefined behaviour.
3395 switch (Inst.getOpcode()) {
3396 case AArch64::LDPSWpre:
3397 case AArch64::LDPWpost:
3398 case AArch64::LDPWpre:
3399 case AArch64::LDPXpost:
3400 case AArch64::LDPXpre: {
3401 unsigned Rt = Inst.getOperand(1).getReg();
3402 unsigned Rt2 = Inst.getOperand(2).getReg();
3403 unsigned Rn = Inst.getOperand(3).getReg();
3404 if (RI->isSubRegisterEq(Rn, Rt))
3405 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3406 "is also a destination");
3407 if (RI->isSubRegisterEq(Rn, Rt2))
3408 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3409 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003410 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003411 }
3412 case AArch64::LDPDi:
3413 case AArch64::LDPQi:
3414 case AArch64::LDPSi:
3415 case AArch64::LDPSWi:
3416 case AArch64::LDPWi:
3417 case AArch64::LDPXi: {
3418 unsigned Rt = Inst.getOperand(0).getReg();
3419 unsigned Rt2 = Inst.getOperand(1).getReg();
3420 if (Rt == Rt2)
3421 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3422 break;
3423 }
3424 case AArch64::LDPDpost:
3425 case AArch64::LDPDpre:
3426 case AArch64::LDPQpost:
3427 case AArch64::LDPQpre:
3428 case AArch64::LDPSpost:
3429 case AArch64::LDPSpre:
3430 case AArch64::LDPSWpost: {
3431 unsigned Rt = Inst.getOperand(1).getReg();
3432 unsigned Rt2 = Inst.getOperand(2).getReg();
3433 if (Rt == Rt2)
3434 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3435 break;
3436 }
3437 case AArch64::STPDpost:
3438 case AArch64::STPDpre:
3439 case AArch64::STPQpost:
3440 case AArch64::STPQpre:
3441 case AArch64::STPSpost:
3442 case AArch64::STPSpre:
3443 case AArch64::STPWpost:
3444 case AArch64::STPWpre:
3445 case AArch64::STPXpost:
3446 case AArch64::STPXpre: {
3447 unsigned Rt = Inst.getOperand(1).getReg();
3448 unsigned Rt2 = Inst.getOperand(2).getReg();
3449 unsigned Rn = Inst.getOperand(3).getReg();
3450 if (RI->isSubRegisterEq(Rn, Rt))
3451 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3452 "is also a source");
3453 if (RI->isSubRegisterEq(Rn, Rt2))
3454 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3455 "is also a source");
3456 break;
3457 }
3458 case AArch64::LDRBBpre:
3459 case AArch64::LDRBpre:
3460 case AArch64::LDRHHpre:
3461 case AArch64::LDRHpre:
3462 case AArch64::LDRSBWpre:
3463 case AArch64::LDRSBXpre:
3464 case AArch64::LDRSHWpre:
3465 case AArch64::LDRSHXpre:
3466 case AArch64::LDRSWpre:
3467 case AArch64::LDRWpre:
3468 case AArch64::LDRXpre:
3469 case AArch64::LDRBBpost:
3470 case AArch64::LDRBpost:
3471 case AArch64::LDRHHpost:
3472 case AArch64::LDRHpost:
3473 case AArch64::LDRSBWpost:
3474 case AArch64::LDRSBXpost:
3475 case AArch64::LDRSHWpost:
3476 case AArch64::LDRSHXpost:
3477 case AArch64::LDRSWpost:
3478 case AArch64::LDRWpost:
3479 case AArch64::LDRXpost: {
3480 unsigned Rt = Inst.getOperand(1).getReg();
3481 unsigned Rn = Inst.getOperand(2).getReg();
3482 if (RI->isSubRegisterEq(Rn, Rt))
3483 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3484 "is also a source");
3485 break;
3486 }
3487 case AArch64::STRBBpost:
3488 case AArch64::STRBpost:
3489 case AArch64::STRHHpost:
3490 case AArch64::STRHpost:
3491 case AArch64::STRWpost:
3492 case AArch64::STRXpost:
3493 case AArch64::STRBBpre:
3494 case AArch64::STRBpre:
3495 case AArch64::STRHHpre:
3496 case AArch64::STRHpre:
3497 case AArch64::STRWpre:
3498 case AArch64::STRXpre: {
3499 unsigned Rt = Inst.getOperand(1).getReg();
3500 unsigned Rn = Inst.getOperand(2).getReg();
3501 if (RI->isSubRegisterEq(Rn, Rt))
3502 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3503 "is also a source");
3504 break;
3505 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003506 case AArch64::STXRB:
3507 case AArch64::STXRH:
3508 case AArch64::STXRW:
3509 case AArch64::STXRX:
3510 case AArch64::STLXRB:
3511 case AArch64::STLXRH:
3512 case AArch64::STLXRW:
3513 case AArch64::STLXRX: {
3514 unsigned Rs = Inst.getOperand(0).getReg();
3515 unsigned Rt = Inst.getOperand(1).getReg();
3516 unsigned Rn = Inst.getOperand(2).getReg();
3517 if (RI->isSubRegisterEq(Rt, Rs) ||
3518 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3519 return Error(Loc[0],
3520 "unpredictable STXR instruction, status is also a source");
3521 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003522 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003523 case AArch64::STXPW:
3524 case AArch64::STXPX:
3525 case AArch64::STLXPW:
3526 case AArch64::STLXPX: {
3527 unsigned Rs = Inst.getOperand(0).getReg();
3528 unsigned Rt1 = Inst.getOperand(1).getReg();
3529 unsigned Rt2 = Inst.getOperand(2).getReg();
3530 unsigned Rn = Inst.getOperand(3).getReg();
3531 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3532 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3533 return Error(Loc[0],
3534 "unpredictable STXP instruction, status is also a source");
3535 break;
3536 }
3537 }
3538
Tim Northover3b0846e2014-05-24 12:50:23 +00003539
3540 // Now check immediate ranges. Separate from the above as there is overlap
3541 // in the instructions being checked and this keeps the nested conditionals
3542 // to a minimum.
3543 switch (Inst.getOpcode()) {
3544 case AArch64::ADDSWri:
3545 case AArch64::ADDSXri:
3546 case AArch64::ADDWri:
3547 case AArch64::ADDXri:
3548 case AArch64::SUBSWri:
3549 case AArch64::SUBSXri:
3550 case AArch64::SUBWri:
3551 case AArch64::SUBXri: {
3552 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3553 // some slight duplication here.
3554 if (Inst.getOperand(2).isExpr()) {
3555 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3556 AArch64MCExpr::VariantKind ELFRefKind;
3557 MCSymbolRefExpr::VariantKind DarwinRefKind;
3558 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003559 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3560
3561 // Only allow these with ADDXri.
3562 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3563 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3564 Inst.getOpcode() == AArch64::ADDXri)
3565 return false;
3566
3567 // Only allow these with ADDXri/ADDWri
3568 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3569 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3570 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3571 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3572 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3573 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3574 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003575 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3576 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3577 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003578 (Inst.getOpcode() == AArch64::ADDXri ||
3579 Inst.getOpcode() == AArch64::ADDWri))
3580 return false;
3581
3582 // Don't allow symbol refs in the immediate field otherwise
3583 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3584 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3585 // 'cmp w0, 'borked')
3586 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003587 }
Diana Picusc93518d2016-10-11 09:17:47 +00003588 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003589 }
3590 return false;
3591 }
3592 default:
3593 return false;
3594 }
3595}
3596
Craig Topper05515562017-10-26 06:46:41 +00003597static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3598 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003599
3600bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3601 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003602 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003603 case Match_InvalidTiedOperand:
3604 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003605 case Match_MissingFeature:
3606 return Error(Loc,
3607 "instruction requires a CPU feature not currently enabled");
3608 case Match_InvalidOperand:
3609 return Error(Loc, "invalid operand for instruction");
3610 case Match_InvalidSuffix:
3611 return Error(Loc, "invalid type suffix for instruction");
3612 case Match_InvalidCondCode:
3613 return Error(Loc, "expected AArch64 condition code");
3614 case Match_AddSubRegExtendSmall:
3615 return Error(Loc,
3616 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3617 case Match_AddSubRegExtendLarge:
3618 return Error(Loc,
3619 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3620 case Match_AddSubSecondSource:
3621 return Error(Loc,
3622 "expected compatible register, symbol or integer in range [0, 4095]");
3623 case Match_LogicalSecondSource:
3624 return Error(Loc, "expected compatible register or logical immediate");
3625 case Match_InvalidMovImm32Shift:
3626 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3627 case Match_InvalidMovImm64Shift:
3628 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3629 case Match_AddSubRegShift32:
3630 return Error(Loc,
3631 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3632 case Match_AddSubRegShift64:
3633 return Error(Loc,
3634 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3635 case Match_InvalidFPImm:
3636 return Error(Loc,
3637 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003638 case Match_InvalidMemoryIndexedSImm6:
3639 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003640 case Match_InvalidMemoryIndexedSImm5:
3641 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003642 case Match_InvalidMemoryIndexed1SImm4:
3643 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003644 case Match_InvalidMemoryIndexed2SImm4:
3645 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003646 case Match_InvalidMemoryIndexed3SImm4:
3647 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003648 case Match_InvalidMemoryIndexed4SImm4:
3649 return Error(Loc, "index must be a multiple of 3 in range [-32, 28].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003650 case Match_InvalidMemoryIndexedSImm9:
3651 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003652 case Match_InvalidMemoryIndexedSImm10:
3653 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003654 case Match_InvalidMemoryIndexed4SImm7:
3655 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3656 case Match_InvalidMemoryIndexed8SImm7:
3657 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3658 case Match_InvalidMemoryIndexed16SImm7:
3659 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3660 case Match_InvalidMemoryWExtend8:
3661 return Error(Loc,
3662 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3663 case Match_InvalidMemoryWExtend16:
3664 return Error(Loc,
3665 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3666 case Match_InvalidMemoryWExtend32:
3667 return Error(Loc,
3668 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3669 case Match_InvalidMemoryWExtend64:
3670 return Error(Loc,
3671 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3672 case Match_InvalidMemoryWExtend128:
3673 return Error(Loc,
3674 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3675 case Match_InvalidMemoryXExtend8:
3676 return Error(Loc,
3677 "expected 'lsl' or 'sxtx' with optional shift of #0");
3678 case Match_InvalidMemoryXExtend16:
3679 return Error(Loc,
3680 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3681 case Match_InvalidMemoryXExtend32:
3682 return Error(Loc,
3683 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3684 case Match_InvalidMemoryXExtend64:
3685 return Error(Loc,
3686 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3687 case Match_InvalidMemoryXExtend128:
3688 return Error(Loc,
3689 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3690 case Match_InvalidMemoryIndexed1:
3691 return Error(Loc, "index must be an integer in range [0, 4095].");
3692 case Match_InvalidMemoryIndexed2:
3693 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3694 case Match_InvalidMemoryIndexed4:
3695 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3696 case Match_InvalidMemoryIndexed8:
3697 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3698 case Match_InvalidMemoryIndexed16:
3699 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003700 case Match_InvalidImm0_1:
3701 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003702 case Match_InvalidImm0_7:
3703 return Error(Loc, "immediate must be an integer in range [0, 7].");
3704 case Match_InvalidImm0_15:
3705 return Error(Loc, "immediate must be an integer in range [0, 15].");
3706 case Match_InvalidImm0_31:
3707 return Error(Loc, "immediate must be an integer in range [0, 31].");
3708 case Match_InvalidImm0_63:
3709 return Error(Loc, "immediate must be an integer in range [0, 63].");
3710 case Match_InvalidImm0_127:
3711 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003712 case Match_InvalidImm0_255:
3713 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003714 case Match_InvalidImm0_65535:
3715 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3716 case Match_InvalidImm1_8:
3717 return Error(Loc, "immediate must be an integer in range [1, 8].");
3718 case Match_InvalidImm1_16:
3719 return Error(Loc, "immediate must be an integer in range [1, 16].");
3720 case Match_InvalidImm1_32:
3721 return Error(Loc, "immediate must be an integer in range [1, 32].");
3722 case Match_InvalidImm1_64:
3723 return Error(Loc, "immediate must be an integer in range [1, 64].");
3724 case Match_InvalidIndex1:
3725 return Error(Loc, "expected lane specifier '[1]'");
3726 case Match_InvalidIndexB:
3727 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3728 case Match_InvalidIndexH:
3729 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3730 case Match_InvalidIndexS:
3731 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3732 case Match_InvalidIndexD:
3733 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3734 case Match_InvalidLabel:
3735 return Error(Loc, "expected label or encodable integer pc offset");
3736 case Match_MRS:
3737 return Error(Loc, "expected readable system register");
3738 case Match_MSR:
3739 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003740 case Match_InvalidComplexRotationEven:
3741 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3742 case Match_InvalidComplexRotationOdd:
3743 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003744 case Match_MnemonicFail: {
3745 std::string Suggestion = AArch64MnemonicSpellCheck(
3746 ((AArch64Operand &)*Operands[0]).getToken(),
3747 ComputeAvailableFeatures(STI->getFeatureBits()));
3748 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3749 }
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003750 case Match_InvalidSVEPattern:
3751 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003752 case Match_InvalidSVEPredicateAnyReg:
3753 case Match_InvalidSVEPredicateBReg:
3754 case Match_InvalidSVEPredicateHReg:
3755 case Match_InvalidSVEPredicateSReg:
3756 case Match_InvalidSVEPredicateDReg:
3757 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003758 case Match_InvalidSVEPredicate3bAnyReg:
3759 case Match_InvalidSVEPredicate3bBReg:
3760 case Match_InvalidSVEPredicate3bHReg:
3761 case Match_InvalidSVEPredicate3bSReg:
3762 case Match_InvalidSVEPredicate3bDReg:
3763 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003764 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003765 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003766 }
3767}
3768
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003769static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003770
3771bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3772 OperandVector &Operands,
3773 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003774 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003775 bool MatchingInlineAsm) {
3776 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003777 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3778 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003779
David Blaikie960ea3f2014-06-08 16:18:35 +00003780 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003781 unsigned NumOperands = Operands.size();
3782
3783 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003784 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3785 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003786 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003787 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003788 if (Op3CE) {
3789 uint64_t Op3Val = Op3CE->getValue();
3790 uint64_t NewOp3Val = 0;
3791 uint64_t NewOp4Val = 0;
3792 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003793 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003794 NewOp3Val = (32 - Op3Val) & 0x1f;
3795 NewOp4Val = 31 - Op3Val;
3796 } else {
3797 NewOp3Val = (64 - Op3Val) & 0x3f;
3798 NewOp4Val = 63 - Op3Val;
3799 }
3800
Jim Grosbach13760bd2015-05-30 01:25:56 +00003801 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3802 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003803
3804 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003805 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003806 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003807 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3808 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3809 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003810 }
3811 }
Tim Northover03b99f62015-04-30 18:28:58 +00003812 } else if (NumOperands == 4 && Tok == "bfc") {
3813 // FIXME: Horrible hack to handle BFC->BFM alias.
3814 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3815 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3816 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3817
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003818 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003819 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3820 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3821
3822 if (LSBCE && WidthCE) {
3823 uint64_t LSB = LSBCE->getValue();
3824 uint64_t Width = WidthCE->getValue();
3825
3826 uint64_t RegWidth = 0;
3827 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3828 Op1.getReg()))
3829 RegWidth = 64;
3830 else
3831 RegWidth = 32;
3832
3833 if (LSB >= RegWidth)
3834 return Error(LSBOp.getStartLoc(),
3835 "expected integer in range [0, 31]");
3836 if (Width < 1 || Width > RegWidth)
3837 return Error(WidthOp.getStartLoc(),
3838 "expected integer in range [1, 32]");
3839
3840 uint64_t ImmR = 0;
3841 if (RegWidth == 32)
3842 ImmR = (32 - LSB) & 0x1f;
3843 else
3844 ImmR = (64 - LSB) & 0x3f;
3845
3846 uint64_t ImmS = Width - 1;
3847
3848 if (ImmR != 0 && ImmS >= ImmR)
3849 return Error(WidthOp.getStartLoc(),
3850 "requested insert overflows register");
3851
Jim Grosbach13760bd2015-05-30 01:25:56 +00003852 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3853 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003854 Operands[0] = AArch64Operand::CreateToken(
3855 "bfm", false, Op.getStartLoc(), getContext());
3856 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003857 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3858 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003859 Operands[3] = AArch64Operand::CreateImm(
3860 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3861 Operands.emplace_back(
3862 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3863 WidthOp.getEndLoc(), getContext()));
3864 }
3865 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003866 } else if (NumOperands == 5) {
3867 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3868 // UBFIZ -> UBFM aliases.
3869 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003870 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3871 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3872 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003873
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003874 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003875 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3876 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003877
3878 if (Op3CE && Op4CE) {
3879 uint64_t Op3Val = Op3CE->getValue();
3880 uint64_t Op4Val = Op4CE->getValue();
3881
3882 uint64_t RegWidth = 0;
3883 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003884 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003885 RegWidth = 64;
3886 else
3887 RegWidth = 32;
3888
3889 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003890 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003891 "expected integer in range [0, 31]");
3892 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003893 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003894 "expected integer in range [1, 32]");
3895
3896 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003897 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003898 NewOp3Val = (32 - Op3Val) & 0x1f;
3899 else
3900 NewOp3Val = (64 - Op3Val) & 0x3f;
3901
3902 uint64_t NewOp4Val = Op4Val - 1;
3903
3904 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003905 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003906 "requested insert overflows register");
3907
3908 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003909 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003910 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003911 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003912 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003913 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003914 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003915 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003916 if (Tok == "bfi")
3917 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003918 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003919 else if (Tok == "sbfiz")
3920 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003921 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003922 else if (Tok == "ubfiz")
3923 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003924 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003925 else
3926 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003927 }
3928 }
3929
3930 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3931 // UBFX -> UBFM aliases.
3932 } else if (NumOperands == 5 &&
3933 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003934 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3935 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3936 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003937
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003938 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003939 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3940 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003941
3942 if (Op3CE && Op4CE) {
3943 uint64_t Op3Val = Op3CE->getValue();
3944 uint64_t Op4Val = Op4CE->getValue();
3945
3946 uint64_t RegWidth = 0;
3947 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003948 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003949 RegWidth = 64;
3950 else
3951 RegWidth = 32;
3952
3953 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003954 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003955 "expected integer in range [0, 31]");
3956 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003957 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003958 "expected integer in range [1, 32]");
3959
3960 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3961
3962 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003963 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003964 "requested extract overflows register");
3965
3966 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003967 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003968 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003969 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003970 if (Tok == "bfxil")
3971 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003972 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003973 else if (Tok == "sbfx")
3974 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003975 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003976 else if (Tok == "ubfx")
3977 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003978 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003979 else
3980 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003981 }
3982 }
3983 }
3984 }
Tim Northover9097a072017-12-18 10:36:00 +00003985
3986 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
3987 // instruction for FP registers correctly in some rare circumstances. Convert
3988 // it to a safe instruction and warn (because silently changing someone's
3989 // assembly is rude).
3990 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
3991 NumOperands == 4 && Tok == "movi") {
3992 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3993 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3994 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3995 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
3996 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
3997 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
3998 if (Suffix.lower() == ".2d" &&
3999 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4000 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4001 " correctly on this CPU, converting to equivalent movi.16b");
4002 // Switch the suffix to .16b.
4003 unsigned Idx = Op1.isToken() ? 1 : 2;
4004 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4005 getContext());
4006 }
4007 }
4008 }
4009
Tim Northover3b0846e2014-05-24 12:50:23 +00004010 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4011 // InstAlias can't quite handle this since the reg classes aren't
4012 // subclasses.
4013 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4014 // The source register can be Wn here, but the matcher expects a
4015 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004016 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004017 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004018 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004019 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4020 Op.getStartLoc(), Op.getEndLoc(),
4021 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004022 }
4023 }
4024 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4025 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004026 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004027 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004028 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004029 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004030 // The source register can be Wn here, but the matcher expects a
4031 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004032 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004033 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004034 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004035 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4036 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004037 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004038 }
4039 }
4040 }
4041 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4042 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004043 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004044 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004045 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004046 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004047 // The source register can be Wn here, but the matcher expects a
4048 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004049 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004050 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004051 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004052 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4053 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004054 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004055 }
4056 }
4057 }
4058
Tim Northover3b0846e2014-05-24 12:50:23 +00004059 MCInst Inst;
4060 // First try to match against the secondary set of tables containing the
4061 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4062 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004063 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004064
4065 // If that fails, try against the alternate table containing long-form NEON:
4066 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004067 if (MatchResult != Match_Success) {
4068 // But first, save the short-form match result: we can use it in case the
4069 // long-form match also fails.
4070 auto ShortFormNEONErrorInfo = ErrorInfo;
4071 auto ShortFormNEONMatchResult = MatchResult;
4072
Tim Northover3b0846e2014-05-24 12:50:23 +00004073 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004074 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004075
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004076 // Now, both matches failed, and the long-form match failed on the mnemonic
4077 // suffix token operand. The short-form match failure is probably more
4078 // relevant: use it instead.
4079 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004080 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004081 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4082 MatchResult = ShortFormNEONMatchResult;
4083 ErrorInfo = ShortFormNEONErrorInfo;
4084 }
4085 }
4086
Tim Northover3b0846e2014-05-24 12:50:23 +00004087 switch (MatchResult) {
4088 case Match_Success: {
4089 // Perform range checking and other semantic validations
4090 SmallVector<SMLoc, 8> OperandLocs;
4091 NumOperands = Operands.size();
4092 for (unsigned i = 1; i < NumOperands; ++i)
4093 OperandLocs.push_back(Operands[i]->getStartLoc());
4094 if (validateInstruction(Inst, OperandLocs))
4095 return true;
4096
4097 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004098 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004099 return false;
4100 }
4101 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004102 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004103 // Special case the error message for the very common case where only
4104 // a single subtarget feature is missing (neon, e.g.).
4105 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004106 uint64_t Mask = 1;
4107 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4108 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004109 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004110 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004111 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004112 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004113 }
4114 return Error(IDLoc, Msg);
4115 }
4116 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004117 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004118 case Match_InvalidOperand: {
4119 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004120
Tim Northover26bb14e2014-08-18 11:49:42 +00004121 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004122 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004123 return Error(IDLoc, "too few operands for instruction",
4124 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004125
David Blaikie960ea3f2014-06-08 16:18:35 +00004126 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004127 if (ErrorLoc == SMLoc())
4128 ErrorLoc = IDLoc;
4129 }
4130 // If the match failed on a suffix token operand, tweak the diagnostic
4131 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004132 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4133 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004134 MatchResult = Match_InvalidSuffix;
4135
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004136 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004137 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004138 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004139 case Match_InvalidMemoryIndexed1:
4140 case Match_InvalidMemoryIndexed2:
4141 case Match_InvalidMemoryIndexed4:
4142 case Match_InvalidMemoryIndexed8:
4143 case Match_InvalidMemoryIndexed16:
4144 case Match_InvalidCondCode:
4145 case Match_AddSubRegExtendSmall:
4146 case Match_AddSubRegExtendLarge:
4147 case Match_AddSubSecondSource:
4148 case Match_LogicalSecondSource:
4149 case Match_AddSubRegShift32:
4150 case Match_AddSubRegShift64:
4151 case Match_InvalidMovImm32Shift:
4152 case Match_InvalidMovImm64Shift:
4153 case Match_InvalidFPImm:
4154 case Match_InvalidMemoryWExtend8:
4155 case Match_InvalidMemoryWExtend16:
4156 case Match_InvalidMemoryWExtend32:
4157 case Match_InvalidMemoryWExtend64:
4158 case Match_InvalidMemoryWExtend128:
4159 case Match_InvalidMemoryXExtend8:
4160 case Match_InvalidMemoryXExtend16:
4161 case Match_InvalidMemoryXExtend32:
4162 case Match_InvalidMemoryXExtend64:
4163 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004164 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004165 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004166 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004167 case Match_InvalidMemoryIndexed4SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004168 case Match_InvalidMemoryIndexed4SImm7:
4169 case Match_InvalidMemoryIndexed8SImm7:
4170 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen5c625982018-04-13 12:56:14 +00004171 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004172 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004173 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004174 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004175 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004176 case Match_InvalidImm0_7:
4177 case Match_InvalidImm0_15:
4178 case Match_InvalidImm0_31:
4179 case Match_InvalidImm0_63:
4180 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004181 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004182 case Match_InvalidImm0_65535:
4183 case Match_InvalidImm1_8:
4184 case Match_InvalidImm1_16:
4185 case Match_InvalidImm1_32:
4186 case Match_InvalidImm1_64:
4187 case Match_InvalidIndex1:
4188 case Match_InvalidIndexB:
4189 case Match_InvalidIndexH:
4190 case Match_InvalidIndexS:
4191 case Match_InvalidIndexD:
4192 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004193 case Match_InvalidComplexRotationEven:
4194 case Match_InvalidComplexRotationOdd:
Sander de Smalencd6be962017-12-20 11:02:42 +00004195 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004196 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004197 case Match_InvalidSVEPredicateBReg:
4198 case Match_InvalidSVEPredicateHReg:
4199 case Match_InvalidSVEPredicateSReg:
4200 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004201 case Match_InvalidSVEPredicate3bAnyReg:
4202 case Match_InvalidSVEPredicate3bBReg:
4203 case Match_InvalidSVEPredicate3bHReg:
4204 case Match_InvalidSVEPredicate3bSReg:
4205 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004206 case Match_MSR:
4207 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004208 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004209 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004210 // Any time we get here, there's nothing fancy to do. Just get the
4211 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004212 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004213 if (ErrorLoc == SMLoc())
4214 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004215 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004216 }
4217 }
4218
4219 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004220}
4221
4222/// ParseDirective parses the arm specific directives
4223bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004224 const MCObjectFileInfo::Environment Format =
4225 getContext().getObjectFileInfo()->getObjectFileType();
4226 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4227 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004228
Tim Northover3b0846e2014-05-24 12:50:23 +00004229 StringRef IDVal = DirectiveID.getIdentifier();
4230 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004231 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004232 parseDirectiveArch(Loc);
4233 else if (IDVal == ".cpu")
4234 parseDirectiveCPU(Loc);
4235 else if (IDVal == ".hword")
4236 parseDirectiveWord(2, Loc);
4237 else if (IDVal == ".word")
4238 parseDirectiveWord(4, Loc);
4239 else if (IDVal == ".xword")
4240 parseDirectiveWord(8, Loc);
4241 else if (IDVal == ".tlsdesccall")
4242 parseDirectiveTLSDescCall(Loc);
4243 else if (IDVal == ".ltorg" || IDVal == ".pool")
4244 parseDirectiveLtorg(Loc);
4245 else if (IDVal == ".unreq")
4246 parseDirectiveUnreq(Loc);
4247 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004248 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004249 parseDirectiveInst(Loc);
4250 else
4251 return true;
4252 } else if (IDVal == MCLOHDirectiveName())
4253 parseDirectiveLOH(IDVal, Loc);
4254 else
4255 return true;
4256 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004257}
4258
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004259static const struct {
4260 const char *Name;
4261 const FeatureBitset Features;
4262} ExtensionMap[] = {
4263 { "crc", {AArch64::FeatureCRC} },
4264 { "crypto", {AArch64::FeatureCrypto} },
4265 { "fp", {AArch64::FeatureFPARMv8} },
4266 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004267 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004268 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004269
4270 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004271 { "pan", {} },
4272 { "lor", {} },
4273 { "rdma", {} },
4274 { "profile", {} },
4275};
4276
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004277/// parseDirectiveArch
4278/// ::= .arch token
4279bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4280 SMLoc ArchLoc = getLoc();
4281
4282 StringRef Arch, ExtensionString;
4283 std::tie(Arch, ExtensionString) =
4284 getParser().parseStringToEndOfStatement().trim().split('+');
4285
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004286 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4287 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004288 return Error(ArchLoc, "unknown arch name");
4289
4290 if (parseToken(AsmToken::EndOfStatement))
4291 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004292
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004293 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004294 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004295 AArch64::getArchFeatures(ID, AArch64Features);
4296 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4297 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004298
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004299 MCSubtargetInfo &STI = copySTI();
4300 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4301 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4302
4303 SmallVector<StringRef, 4> RequestedExtensions;
4304 if (!ExtensionString.empty())
4305 ExtensionString.split(RequestedExtensions, '+');
4306
4307 FeatureBitset Features = STI.getFeatureBits();
4308 for (auto Name : RequestedExtensions) {
4309 bool EnableFeature = true;
4310
4311 if (Name.startswith_lower("no")) {
4312 EnableFeature = false;
4313 Name = Name.substr(2);
4314 }
4315
4316 for (const auto &Extension : ExtensionMap) {
4317 if (Extension.Name != Name)
4318 continue;
4319
4320 if (Extension.Features.none())
4321 report_fatal_error("unsupported architectural extension: " + Name);
4322
4323 FeatureBitset ToggleFeatures = EnableFeature
4324 ? (~Features & Extension.Features)
4325 : ( Features & Extension.Features);
4326 uint64_t Features =
4327 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4328 setAvailableFeatures(Features);
4329 break;
4330 }
4331 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004332 return false;
4333}
4334
Tim Northover8b96c7e2017-05-15 19:42:15 +00004335static SMLoc incrementLoc(SMLoc L, int Offset) {
4336 return SMLoc::getFromPointer(L.getPointer() + Offset);
4337}
4338
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004339/// parseDirectiveCPU
4340/// ::= .cpu id
4341bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004342 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004343
4344 StringRef CPU, ExtensionString;
4345 std::tie(CPU, ExtensionString) =
4346 getParser().parseStringToEndOfStatement().trim().split('+');
4347
Nirav Davee833c6c2016-11-08 18:31:04 +00004348 if (parseToken(AsmToken::EndOfStatement))
4349 return true;
4350
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004351 SmallVector<StringRef, 4> RequestedExtensions;
4352 if (!ExtensionString.empty())
4353 ExtensionString.split(RequestedExtensions, '+');
4354
4355 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4356 // once that is tablegen'ed
4357 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004358 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004359 return false;
4360 }
4361
4362 MCSubtargetInfo &STI = copySTI();
4363 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004364 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004365
4366 FeatureBitset Features = STI.getFeatureBits();
4367 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004368 // Advance source location past '+'.
4369 CurLoc = incrementLoc(CurLoc, 1);
4370
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004371 bool EnableFeature = true;
4372
4373 if (Name.startswith_lower("no")) {
4374 EnableFeature = false;
4375 Name = Name.substr(2);
4376 }
4377
Tim Northover8b96c7e2017-05-15 19:42:15 +00004378 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004379 for (const auto &Extension : ExtensionMap) {
4380 if (Extension.Name != Name)
4381 continue;
4382
4383 if (Extension.Features.none())
4384 report_fatal_error("unsupported architectural extension: " + Name);
4385
4386 FeatureBitset ToggleFeatures = EnableFeature
4387 ? (~Features & Extension.Features)
4388 : ( Features & Extension.Features);
4389 uint64_t Features =
4390 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4391 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004392 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004393
4394 break;
4395 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004396
4397 if (!FoundExtension)
4398 Error(CurLoc, "unsupported architectural extension");
4399
4400 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004401 }
4402 return false;
4403}
4404
Tim Northover3b0846e2014-05-24 12:50:23 +00004405/// parseDirectiveWord
4406/// ::= .word [ expression (, expression)* ]
4407bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004408 auto parseOp = [&]() -> bool {
4409 const MCExpr *Value;
4410 if (getParser().parseExpression(Value))
4411 return true;
4412 getParser().getStreamer().EmitValue(Value, Size, L);
4413 return false;
4414 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004415
Nirav Davee833c6c2016-11-08 18:31:04 +00004416 if (parseMany(parseOp))
4417 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004418 return false;
4419}
4420
Chad Rosierdcd2a302014-10-22 20:35:57 +00004421/// parseDirectiveInst
4422/// ::= .inst opcode [, ...]
4423bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004424 if (getLexer().is(AsmToken::EndOfStatement))
4425 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004426
Nirav Davee833c6c2016-11-08 18:31:04 +00004427 auto parseOp = [&]() -> bool {
4428 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004429 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004430 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4431 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004432 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004433 if (check(!Value, L, "expected constant expression"))
4434 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004435 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004436 return false;
4437 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004438
Nirav Davee833c6c2016-11-08 18:31:04 +00004439 if (parseMany(parseOp))
4440 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004441 return false;
4442}
4443
Tim Northover3b0846e2014-05-24 12:50:23 +00004444// parseDirectiveTLSDescCall:
4445// ::= .tlsdesccall symbol
4446bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4447 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004448 if (check(getParser().parseIdentifier(Name), L,
4449 "expected symbol after directive") ||
4450 parseToken(AsmToken::EndOfStatement))
4451 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004452
Jim Grosbach6f482002015-05-18 18:43:14 +00004453 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004454 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4455 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004456
4457 MCInst Inst;
4458 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004459 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004460
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004461 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004462 return false;
4463}
4464
4465/// ::= .loh <lohName | lohId> label1, ..., labelN
4466/// The number of arguments depends on the loh identifier.
4467bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004468 MCLOHType Kind;
4469 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4470 if (getParser().getTok().isNot(AsmToken::Integer))
4471 return TokError("expected an identifier or a number in directive");
4472 // We successfully get a numeric value for the identifier.
4473 // Check if it is valid.
4474 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004475 if (Id <= -1U && !isValidMCLOHType(Id))
4476 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004477 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004478 } else {
4479 StringRef Name = getTok().getIdentifier();
4480 // We successfully parse an identifier.
4481 // Check if it is a recognized one.
4482 int Id = MCLOHNameToId(Name);
4483
4484 if (Id == -1)
4485 return TokError("invalid identifier in directive");
4486 Kind = (MCLOHType)Id;
4487 }
4488 // Consume the identifier.
4489 Lex();
4490 // Get the number of arguments of this LOH.
4491 int NbArgs = MCLOHIdToNbArgs(Kind);
4492
4493 assert(NbArgs != -1 && "Invalid number of arguments");
4494
4495 SmallVector<MCSymbol *, 3> Args;
4496 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4497 StringRef Name;
4498 if (getParser().parseIdentifier(Name))
4499 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004500 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004501
4502 if (Idx + 1 == NbArgs)
4503 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004504 if (parseToken(AsmToken::Comma,
4505 "unexpected token in '" + Twine(IDVal) + "' directive"))
4506 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004507 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004508 if (parseToken(AsmToken::EndOfStatement,
4509 "unexpected token in '" + Twine(IDVal) + "' directive"))
4510 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004511
4512 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4513 return false;
4514}
4515
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004516/// parseDirectiveLtorg
4517/// ::= .ltorg | .pool
4518bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004519 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4520 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004521 getTargetStreamer().emitCurrentConstantPool();
4522 return false;
4523}
4524
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004525/// parseDirectiveReq
4526/// ::= name .req registername
4527bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004528 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004529 Parser.Lex(); // Eat the '.req' token.
4530 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004531 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004532 unsigned RegNum;
4533 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004534
Sander de Smalen50d87022018-04-19 07:35:08 +00004535 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004536 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004537 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004538 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004539
Sander de Smalen50d87022018-04-19 07:35:08 +00004540 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004541 return true;
4542
Sander de Smalen50d87022018-04-19 07:35:08 +00004543 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004544 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004545 }
4546
Sander de Smalen50d87022018-04-19 07:35:08 +00004547 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004548 StringRef Kind;
4549 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004550 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004551 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004552
Sander de Smalen50d87022018-04-19 07:35:08 +00004553 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004554 return true;
4555
Sander de Smalen50d87022018-04-19 07:35:08 +00004556 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004557 return Error(SRegLoc,
4558 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004559 }
4560
Sander de Smalen50d87022018-04-19 07:35:08 +00004561 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00004562 StringRef Kind;
4563 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004564 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004565
Sander de Smalen50d87022018-04-19 07:35:08 +00004566 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00004567 return true;
4568
Sander de Smalen50d87022018-04-19 07:35:08 +00004569 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00004570 return Error(SRegLoc,
4571 "sve predicate register without type specifier expected");
4572 }
4573
Sander de Smalen50d87022018-04-19 07:35:08 +00004574 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00004575 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004576
4577 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004578 if (parseToken(AsmToken::EndOfStatement,
4579 "unexpected input in .req directive"))
4580 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004581
Sander de Smalen8e607342017-11-15 15:44:43 +00004582 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004583 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004584 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4585
Nirav Dave2364748a2016-09-16 18:30:20 +00004586 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004587}
4588
4589/// parseDirectiveUneq
4590/// ::= .unreq registername
4591bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004592 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004593 if (getTok().isNot(AsmToken::Identifier))
4594 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004595 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4596 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004597 if (parseToken(AsmToken::EndOfStatement))
4598 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004599 return false;
4600}
4601
Tim Northover3b0846e2014-05-24 12:50:23 +00004602bool
4603AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4604 AArch64MCExpr::VariantKind &ELFRefKind,
4605 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4606 int64_t &Addend) {
4607 ELFRefKind = AArch64MCExpr::VK_INVALID;
4608 DarwinRefKind = MCSymbolRefExpr::VK_None;
4609 Addend = 0;
4610
4611 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4612 ELFRefKind = AE->getKind();
4613 Expr = AE->getSubExpr();
4614 }
4615
4616 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4617 if (SE) {
4618 // It's a simple symbol reference with no addend.
4619 DarwinRefKind = SE->getKind();
4620 return true;
4621 }
4622
4623 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4624 if (!BE)
4625 return false;
4626
4627 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4628 if (!SE)
4629 return false;
4630 DarwinRefKind = SE->getKind();
4631
4632 if (BE->getOpcode() != MCBinaryExpr::Add &&
4633 BE->getOpcode() != MCBinaryExpr::Sub)
4634 return false;
4635
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004636 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004637 // on here than we can deal with.
4638 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4639 if (!AddendExpr)
4640 return false;
4641
4642 Addend = AddendExpr->getValue();
4643 if (BE->getOpcode() == MCBinaryExpr::Sub)
4644 Addend = -Addend;
4645
4646 // It's some symbol reference + a constant addend, but really
4647 // shouldn't use both Darwin and ELF syntax.
4648 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4649 DarwinRefKind == MCSymbolRefExpr::VK_None;
4650}
4651
4652/// Force static initialization.
4653extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004654 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4655 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4656 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004657}
4658
4659#define GET_REGISTER_MATCHER
4660#define GET_SUBTARGET_FEATURE_NAME
4661#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004662#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004663#include "AArch64GenAsmMatcher.inc"
4664
4665// Define this matcher function after the auto-generated include so we
4666// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004667unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004668 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004669 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004670 // If the kind is a token for a literal immediate, check if our asm
4671 // operand matches. This is for InstAliases which have a fixed-value
4672 // immediate in the syntax.
4673 int64_t ExpectedVal;
4674 switch (Kind) {
4675 default:
4676 return Match_InvalidOperand;
4677 case MCK__35_0:
4678 ExpectedVal = 0;
4679 break;
4680 case MCK__35_1:
4681 ExpectedVal = 1;
4682 break;
4683 case MCK__35_12:
4684 ExpectedVal = 12;
4685 break;
4686 case MCK__35_16:
4687 ExpectedVal = 16;
4688 break;
4689 case MCK__35_2:
4690 ExpectedVal = 2;
4691 break;
4692 case MCK__35_24:
4693 ExpectedVal = 24;
4694 break;
4695 case MCK__35_3:
4696 ExpectedVal = 3;
4697 break;
4698 case MCK__35_32:
4699 ExpectedVal = 32;
4700 break;
4701 case MCK__35_4:
4702 ExpectedVal = 4;
4703 break;
4704 case MCK__35_48:
4705 ExpectedVal = 48;
4706 break;
4707 case MCK__35_6:
4708 ExpectedVal = 6;
4709 break;
4710 case MCK__35_64:
4711 ExpectedVal = 64;
4712 break;
4713 case MCK__35_8:
4714 ExpectedVal = 8;
4715 break;
4716 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004717 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004718 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004719 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004720 if (!CE)
4721 return Match_InvalidOperand;
4722 if (CE->getValue() == ExpectedVal)
4723 return Match_Success;
4724 return Match_InvalidOperand;
4725}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004726
Alex Bradbury58eba092016-11-01 16:32:05 +00004727OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004728AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4729
4730 SMLoc S = getLoc();
4731
4732 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4733 Error(S, "expected register");
4734 return MatchOperand_ParseFail;
4735 }
4736
Sander de Smalen50d87022018-04-19 07:35:08 +00004737 unsigned FirstReg;
4738 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
4739 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004740 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00004741
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004742 const MCRegisterClass &WRegClass =
4743 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4744 const MCRegisterClass &XRegClass =
4745 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4746
4747 bool isXReg = XRegClass.contains(FirstReg),
4748 isWReg = WRegClass.contains(FirstReg);
4749 if (!isXReg && !isWReg) {
4750 Error(S, "expected first even register of a "
4751 "consecutive same-size even/odd register pair");
4752 return MatchOperand_ParseFail;
4753 }
4754
4755 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4756 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4757
4758 if (FirstEncoding & 0x1) {
4759 Error(S, "expected first even register of a "
4760 "consecutive same-size even/odd register pair");
4761 return MatchOperand_ParseFail;
4762 }
4763
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004764 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00004765 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004766 return MatchOperand_ParseFail;
4767 }
4768 // Eat the comma
4769 getParser().Lex();
4770
4771 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00004772 unsigned SecondReg;
4773 Res = tryParseScalarRegister(SecondReg);
4774 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004775 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004776
Eugene Zelenko049b0172017-01-06 00:30:53 +00004777 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004778 (isXReg && !XRegClass.contains(SecondReg)) ||
4779 (isWReg && !WRegClass.contains(SecondReg))) {
4780 Error(E,"expected second odd register of a "
4781 "consecutive same-size even/odd register pair");
4782 return MatchOperand_ParseFail;
4783 }
Joel Jones504bf332016-10-24 13:37:13 +00004784
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004785 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004786 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004787 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4788 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4789 } else {
4790 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4791 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4792 }
4793
Florian Hahnc4422242017-11-07 13:07:50 +00004794 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4795 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004796
4797 return MatchOperand_Success;
4798}
Florian Hahn91f11e52017-11-07 16:45:48 +00004799
4800template <bool ParseSuffix>
4801OperandMatchResultTy
4802AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004803 const SMLoc S = getLoc();
4804 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00004805 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00004806 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004807
Sander de Smalen8e607342017-11-15 15:44:43 +00004808 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004809 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004810
4811 if (Res != MatchOperand_Success)
4812 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004813
4814 if (ParseSuffix && Kind.empty())
4815 return MatchOperand_NoMatch;
4816
Sander de Smalen73937b72018-04-11 07:36:10 +00004817 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
4818 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00004819 return MatchOperand_NoMatch;
4820
Sander de Smalen73937b72018-04-11 07:36:10 +00004821 unsigned ElementWidth = KindRes->second;
4822 Operands.push_back(AArch64Operand::CreateVectorReg(
4823 RegNum, RegKind::SVEDataVector, ElementWidth, S, S,
4824 getContext()));
Florian Hahn91f11e52017-11-07 16:45:48 +00004825
4826 return MatchOperand_Success;
4827}
Sander de Smalen245e0e62018-01-22 10:46:00 +00004828
4829OperandMatchResultTy
4830AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
4831 MCAsmParser &Parser = getParser();
4832
4833 SMLoc SS = getLoc();
4834 const AsmToken &TokE = Parser.getTok();
4835 bool IsHash = TokE.is(AsmToken::Hash);
4836
4837 if (!IsHash && TokE.isNot(AsmToken::Identifier))
4838 return MatchOperand_NoMatch;
4839
4840 int64_t Pattern;
4841 if (IsHash) {
4842 Parser.Lex(); // Eat hash
4843
4844 // Parse the immediate operand.
4845 const MCExpr *ImmVal;
4846 SS = getLoc();
4847 if (Parser.parseExpression(ImmVal))
4848 return MatchOperand_ParseFail;
4849
4850 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4851 if (!MCE)
4852 return MatchOperand_ParseFail;
4853
4854 Pattern = MCE->getValue();
4855 } else {
4856 // Parse the pattern
4857 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
4858 if (!Pat)
4859 return MatchOperand_NoMatch;
4860
4861 Parser.Lex();
4862 Pattern = Pat->Encoding;
4863 assert(Pattern >= 0 && Pattern < 32);
4864 }
4865
4866 Operands.push_back(
4867 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
4868 SS, getLoc(), getContext()));
4869
4870 return MatchOperand_Success;
4871}