blob: 787c035df1083c1a79c2061da953a3105dc3c918 [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 int tryParseRegister();
Tim Northover3b0846e2014-05-24 12:50:23 +000089 bool parseRegister(OperandVector &Operands);
90 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
Sander de Smalenc88f9a12018-04-11 14:10:37 +000091 bool parseNeonVectorList(OperandVector &Operands);
Sander de Smalen5c625982018-04-13 12:56:14 +000092 bool parseOptionalMulVl(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000093 bool parseOperand(OperandVector &Operands, bool isCondCode,
94 bool invertCondCode);
95
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +000096 bool showMatchError(SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000097
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000098 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000099 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000100 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +0000101 bool parseDirectiveInst(SMLoc L);
102
Tim Northover3b0846e2014-05-24 12:50:23 +0000103 bool parseDirectiveTLSDescCall(SMLoc L);
104
105 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000106 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000107
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000108 bool parseDirectiveReq(StringRef Name, SMLoc L);
109 bool parseDirectiveUnreq(SMLoc L);
110
Tim Northover3b0846e2014-05-24 12:50:23 +0000111 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
112 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
113 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000114 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000115 bool MatchingInlineAsm) override;
116/// @name Auto-generated Match Functions
117/// {
118
119#define GET_ASSEMBLER_HEADER
120#include "AArch64GenAsmMatcher.inc"
121
122 /// }
123
Sander de Smalen73937b72018-04-11 07:36:10 +0000124 OperandMatchResultTy tryParseVectorRegister(int &Reg, StringRef &Kind,
125 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,
1157 AArch64::Z0 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001158 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001159
Sander de Smalenea626e32018-04-13 09:11:53 +00001160 assert((RegTy != VecListIdx_ZReg || NumRegs <= 1) &&
1161 " NumRegs must be 0 or 1 for ZRegs");
1162
Sander de Smalen525e3222018-04-12 13:19:32 +00001163 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1164 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1165 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001166 }
1167
1168 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1169 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001170 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001171 }
1172
1173 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1174 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001175 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001176 }
1177
1178 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1179 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001180 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001181 }
1182
1183 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1184 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001185 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001186 }
1187
1188 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1189 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001190 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001191 }
1192
1193 void addImmOperands(MCInst &Inst, unsigned N) const {
1194 assert(N == 1 && "Invalid number of operands!");
1195 // If this is a pageoff symrefexpr with an addend, adjust the addend
1196 // to be only the page-offset portion. Otherwise, just add the expr
1197 // as-is.
1198 addExpr(Inst, getImm());
1199 }
1200
1201 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1202 assert(N == 2 && "Invalid number of operands!");
1203 if (isShiftedImm()) {
1204 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001205 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001206 } else {
1207 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001208 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001209 }
1210 }
1211
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001212 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1213 assert(N == 2 && "Invalid number of operands!");
1214
1215 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1216 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1217 int64_t Val = -CE->getValue();
1218 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1219
1220 Inst.addOperand(MCOperand::createImm(Val));
1221 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1222 }
1223
Tim Northover3b0846e2014-05-24 12:50:23 +00001224 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1225 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001226 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001227 }
1228
1229 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1230 assert(N == 1 && "Invalid number of operands!");
1231 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1232 if (!MCE)
1233 addExpr(Inst, getImm());
1234 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001235 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001236 }
1237
1238 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1239 addImmOperands(Inst, N);
1240 }
1241
1242 template<int Scale>
1243 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1244 assert(N == 1 && "Invalid number of operands!");
1245 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1246
1247 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001248 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001249 return;
1250 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001251 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001252 }
1253
1254 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1255 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001256 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001257 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001258 }
1259
Sam Parker6d42de72017-08-11 13:14:00 +00001260 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1261 assert(N == 1 && "Invalid number of operands!");
1262 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1263 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1264 }
1265
Tim Northover3b0846e2014-05-24 12:50:23 +00001266 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1267 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001268 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001269 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001270 }
1271
1272 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1273 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001274 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001275 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001276 }
1277
1278 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1279 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001280 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001281 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001282 }
1283
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001284 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1285 assert(N == 1 && "Invalid number of operands!");
1286 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1287 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1288 }
1289
Tim Northover3b0846e2014-05-24 12:50:23 +00001290 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1291 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001292 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001293 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001294 }
1295
1296 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1297 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001298 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001299 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001300 }
1301
1302 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1303 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001304 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001305 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001306 }
1307
1308 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1309 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001310 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001311 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001312 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001313 }
1314
1315 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1316 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001317 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001318 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001319 }
1320
1321 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1322 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001323 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001324 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001325 }
1326
1327 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1328 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001329 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001330 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001331 }
1332
1333 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1334 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001335 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001336 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001337 }
1338
1339 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1340 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001341 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001342 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001343 }
1344
1345 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1346 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001347 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001348 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001349 }
1350
1351 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1352 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001353 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001354 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001355 }
1356
1357 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1358 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001359 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001360 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001361 }
1362
1363 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1364 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001365 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001366 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001367 }
1368
1369 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1370 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001371 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001372 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001373 }
1374
Sander de Smalen5c625982018-04-13 12:56:14 +00001375 template <int Scale>
1376 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1377 assert(N == 1 && "Invalid number of operands!");
1378 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1379 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1380 }
1381
Sander de Smalena1c259c2018-01-29 13:05:38 +00001382 template <typename T>
1383 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001384 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001385 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001386 typename std::make_unsigned<T>::type Val = MCE->getValue();
1387 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001388 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001389 }
1390
Sander de Smalena1c259c2018-01-29 13:05:38 +00001391 template <typename T>
1392 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001393 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001394 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001395 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1396 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001397 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001398 }
1399
Tim Northover3b0846e2014-05-24 12:50:23 +00001400 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1401 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001402 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001403 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001404 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001405 }
1406
1407 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1408 // Branch operands don't encode the low bits, so shift them off
1409 // here. If it's a label, however, just put it on directly as there's
1410 // not enough information now to do anything.
1411 assert(N == 1 && "Invalid number of operands!");
1412 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1413 if (!MCE) {
1414 addExpr(Inst, getImm());
1415 return;
1416 }
1417 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001418 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001419 }
1420
1421 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1422 // Branch operands don't encode the low bits, so shift them off
1423 // here. If it's a label, however, just put it on directly as there's
1424 // not enough information now to do anything.
1425 assert(N == 1 && "Invalid number of operands!");
1426 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1427 if (!MCE) {
1428 addExpr(Inst, getImm());
1429 return;
1430 }
1431 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001432 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001433 }
1434
1435 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1436 // Branch operands don't encode the low bits, so shift them off
1437 // here. If it's a label, however, just put it on directly as there's
1438 // not enough information now to do anything.
1439 assert(N == 1 && "Invalid number of operands!");
1440 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1441 if (!MCE) {
1442 addExpr(Inst, getImm());
1443 return;
1444 }
1445 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001446 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001447 }
1448
1449 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1450 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001451 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001452 }
1453
1454 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1455 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001456 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001457 }
1458
1459 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1460 assert(N == 1 && "Invalid number of operands!");
1461
Jim Grosbache9119e42015-05-13 18:37:00 +00001462 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001463 }
1464
1465 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1466 assert(N == 1 && "Invalid number of operands!");
1467
Jim Grosbache9119e42015-05-13 18:37:00 +00001468 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001469 }
1470
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001471 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1472 assert(N == 1 && "Invalid number of operands!");
1473
1474 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1475 }
1476
1477 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001478 assert(N == 1 && "Invalid number of operands!");
1479
Jim Grosbache9119e42015-05-13 18:37:00 +00001480 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001481 }
1482
1483 void addSysCROperands(MCInst &Inst, unsigned N) const {
1484 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001485 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001486 }
1487
1488 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1489 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001490 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001491 }
1492
Oliver Stannarda34e4702015-12-01 10:48:51 +00001493 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1494 assert(N == 1 && "Invalid number of operands!");
1495 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1496 }
1497
Tim Northover3b0846e2014-05-24 12:50:23 +00001498 void addShifterOperands(MCInst &Inst, unsigned N) const {
1499 assert(N == 1 && "Invalid number of operands!");
1500 unsigned Imm =
1501 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001502 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001503 }
1504
1505 void addExtendOperands(MCInst &Inst, unsigned N) const {
1506 assert(N == 1 && "Invalid number of operands!");
1507 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1508 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1509 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001510 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001511 }
1512
1513 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1514 assert(N == 1 && "Invalid number of operands!");
1515 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1516 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1517 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001518 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001519 }
1520
1521 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1522 assert(N == 2 && "Invalid number of operands!");
1523 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1524 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001525 Inst.addOperand(MCOperand::createImm(IsSigned));
1526 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001527 }
1528
1529 // For 8-bit load/store instructions with a register offset, both the
1530 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1531 // they're disambiguated by whether the shift was explicit or implicit rather
1532 // than its size.
1533 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1534 assert(N == 2 && "Invalid number of operands!");
1535 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1536 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001537 Inst.addOperand(MCOperand::createImm(IsSigned));
1538 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001539 }
1540
1541 template<int Shift>
1542 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1543 assert(N == 1 && "Invalid number of operands!");
1544
1545 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1546 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001547 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001548 }
1549
1550 template<int Shift>
1551 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1552 assert(N == 1 && "Invalid number of operands!");
1553
1554 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1555 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001556 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001557 }
1558
Sam Parker5f934642017-08-31 09:27:04 +00001559 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1560 assert(N == 1 && "Invalid number of operands!");
1561 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1562 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1563 }
1564
1565 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1566 assert(N == 1 && "Invalid number of operands!");
1567 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1568 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1569 }
1570
Tim Northover3b0846e2014-05-24 12:50:23 +00001571 void print(raw_ostream &OS) const override;
1572
David Blaikie960ea3f2014-06-08 16:18:35 +00001573 static std::unique_ptr<AArch64Operand>
1574 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1575 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001576 Op->Tok.Data = Str.data();
1577 Op->Tok.Length = Str.size();
1578 Op->Tok.IsSuffix = IsSuffix;
1579 Op->StartLoc = S;
1580 Op->EndLoc = S;
1581 return Op;
1582 }
1583
David Blaikie960ea3f2014-06-08 16:18:35 +00001584 static std::unique_ptr<AArch64Operand>
Florian Hahnc4422242017-11-07 13:07:50 +00001585 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001586 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001587 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001588 Op->Reg.Kind = Kind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001589 Op->StartLoc = S;
1590 Op->EndLoc = E;
1591 return Op;
1592 }
1593
David Blaikie960ea3f2014-06-08 16:18:35 +00001594 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001595 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1596 SMLoc S, SMLoc E, MCContext &Ctx) {
1597 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1598 Kind == RegKind::SVEPredicateVector) &&
1599 "Invalid vector kind");
Florian Hahn91f11e52017-11-07 16:45:48 +00001600 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1601 Op->Reg.RegNum = RegNum;
1602 Op->Reg.ElementWidth = ElementWidth;
1603 Op->Reg.Kind = Kind;
1604 Op->StartLoc = S;
1605 Op->EndLoc = E;
1606 return Op;
1607 }
1608
1609 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001610 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001611 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1612 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001613 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001614 Op->VectorList.RegNum = RegNum;
1615 Op->VectorList.Count = Count;
1616 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001617 Op->VectorList.ElementWidth = ElementWidth;
1618 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001619 Op->StartLoc = S;
1620 Op->EndLoc = E;
1621 return Op;
1622 }
1623
David Blaikie960ea3f2014-06-08 16:18:35 +00001624 static std::unique_ptr<AArch64Operand>
1625 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1626 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001627 Op->VectorIndex.Val = Idx;
1628 Op->StartLoc = S;
1629 Op->EndLoc = E;
1630 return Op;
1631 }
1632
David Blaikie960ea3f2014-06-08 16:18:35 +00001633 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1634 SMLoc E, MCContext &Ctx) {
1635 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001636 Op->Imm.Val = Val;
1637 Op->StartLoc = S;
1638 Op->EndLoc = E;
1639 return Op;
1640 }
1641
David Blaikie960ea3f2014-06-08 16:18:35 +00001642 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1643 unsigned ShiftAmount,
1644 SMLoc S, SMLoc E,
1645 MCContext &Ctx) {
1646 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001647 Op->ShiftedImm .Val = Val;
1648 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1649 Op->StartLoc = S;
1650 Op->EndLoc = E;
1651 return Op;
1652 }
1653
David Blaikie960ea3f2014-06-08 16:18:35 +00001654 static std::unique_ptr<AArch64Operand>
1655 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1656 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001657 Op->CondCode.Code = Code;
1658 Op->StartLoc = S;
1659 Op->EndLoc = E;
1660 return Op;
1661 }
1662
David Blaikie960ea3f2014-06-08 16:18:35 +00001663 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1664 MCContext &Ctx) {
1665 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001666 Op->FPImm.Val = Val;
1667 Op->StartLoc = S;
1668 Op->EndLoc = S;
1669 return Op;
1670 }
1671
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001672 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1673 StringRef Str,
1674 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001675 MCContext &Ctx) {
1676 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001677 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001678 Op->Barrier.Data = Str.data();
1679 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001680 Op->StartLoc = S;
1681 Op->EndLoc = S;
1682 return Op;
1683 }
1684
Tim Northover7cd58932015-01-22 17:23:04 +00001685 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1686 uint32_t MRSReg,
1687 uint32_t MSRReg,
1688 uint32_t PStateField,
1689 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001690 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001691 Op->SysReg.Data = Str.data();
1692 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001693 Op->SysReg.MRSReg = MRSReg;
1694 Op->SysReg.MSRReg = MSRReg;
1695 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001696 Op->StartLoc = S;
1697 Op->EndLoc = S;
1698 return Op;
1699 }
1700
David Blaikie960ea3f2014-06-08 16:18:35 +00001701 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1702 SMLoc E, MCContext &Ctx) {
1703 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001704 Op->SysCRImm.Val = Val;
1705 Op->StartLoc = S;
1706 Op->EndLoc = E;
1707 return Op;
1708 }
1709
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001710 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1711 StringRef Str,
1712 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001713 MCContext &Ctx) {
1714 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001715 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001716 Op->Barrier.Data = Str.data();
1717 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001718 Op->StartLoc = S;
1719 Op->EndLoc = S;
1720 return Op;
1721 }
1722
Oliver Stannarda34e4702015-12-01 10:48:51 +00001723 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1724 StringRef Str,
1725 SMLoc S,
1726 MCContext &Ctx) {
1727 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1728 Op->PSBHint.Val = Val;
1729 Op->PSBHint.Data = Str.data();
1730 Op->PSBHint.Length = Str.size();
1731 Op->StartLoc = S;
1732 Op->EndLoc = S;
1733 return Op;
1734 }
1735
David Blaikie960ea3f2014-06-08 16:18:35 +00001736 static std::unique_ptr<AArch64Operand>
1737 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1738 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1739 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001740 Op->ShiftExtend.Type = ShOp;
1741 Op->ShiftExtend.Amount = Val;
1742 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1743 Op->StartLoc = S;
1744 Op->EndLoc = E;
1745 return Op;
1746 }
1747};
1748
1749} // end anonymous namespace.
1750
1751void AArch64Operand::print(raw_ostream &OS) const {
1752 switch (Kind) {
1753 case k_FPImm:
1754 OS << "<fpimm " << getFPImm() << "("
1755 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1756 break;
1757 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001758 StringRef Name = getBarrierName();
1759 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001760 OS << "<barrier " << Name << ">";
1761 else
1762 OS << "<barrier invalid #" << getBarrier() << ">";
1763 break;
1764 }
1765 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001766 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001767 break;
1768 case k_ShiftedImm: {
1769 unsigned Shift = getShiftedImmShift();
1770 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001771 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001772 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1773 break;
1774 }
1775 case k_CondCode:
1776 OS << "<condcode " << getCondCode() << ">";
1777 break;
1778 case k_Register:
1779 OS << "<register " << getReg() << ">";
1780 break;
1781 case k_VectorList: {
1782 OS << "<vectorlist ";
1783 unsigned Reg = getVectorListStart();
1784 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1785 OS << Reg + i << " ";
1786 OS << ">";
1787 break;
1788 }
1789 case k_VectorIndex:
1790 OS << "<vectorindex " << getVectorIndex() << ">";
1791 break;
1792 case k_SysReg:
1793 OS << "<sysreg: " << getSysReg() << '>';
1794 break;
1795 case k_Token:
1796 OS << "'" << getToken() << "'";
1797 break;
1798 case k_SysCR:
1799 OS << "c" << getSysCR();
1800 break;
1801 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001802 StringRef Name = getPrefetchName();
1803 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001804 OS << "<prfop " << Name << ">";
1805 else
1806 OS << "<prfop invalid #" << getPrefetch() << ">";
1807 break;
1808 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001809 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001810 OS << getPSBHintName();
1811 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001812 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001813 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1814 << getShiftExtendAmount();
1815 if (!hasShiftExtendAmount())
1816 OS << "<imp>";
1817 OS << '>';
1818 break;
1819 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001820}
1821
1822/// @name Auto-generated Match Functions
1823/// {
1824
1825static unsigned MatchRegisterName(StringRef Name);
1826
1827/// }
1828
Florian Hahnc4422242017-11-07 13:07:50 +00001829static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001830 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001831 .Case("v0", AArch64::Q0)
1832 .Case("v1", AArch64::Q1)
1833 .Case("v2", AArch64::Q2)
1834 .Case("v3", AArch64::Q3)
1835 .Case("v4", AArch64::Q4)
1836 .Case("v5", AArch64::Q5)
1837 .Case("v6", AArch64::Q6)
1838 .Case("v7", AArch64::Q7)
1839 .Case("v8", AArch64::Q8)
1840 .Case("v9", AArch64::Q9)
1841 .Case("v10", AArch64::Q10)
1842 .Case("v11", AArch64::Q11)
1843 .Case("v12", AArch64::Q12)
1844 .Case("v13", AArch64::Q13)
1845 .Case("v14", AArch64::Q14)
1846 .Case("v15", AArch64::Q15)
1847 .Case("v16", AArch64::Q16)
1848 .Case("v17", AArch64::Q17)
1849 .Case("v18", AArch64::Q18)
1850 .Case("v19", AArch64::Q19)
1851 .Case("v20", AArch64::Q20)
1852 .Case("v21", AArch64::Q21)
1853 .Case("v22", AArch64::Q22)
1854 .Case("v23", AArch64::Q23)
1855 .Case("v24", AArch64::Q24)
1856 .Case("v25", AArch64::Q25)
1857 .Case("v26", AArch64::Q26)
1858 .Case("v27", AArch64::Q27)
1859 .Case("v28", AArch64::Q28)
1860 .Case("v29", AArch64::Q29)
1861 .Case("v30", AArch64::Q30)
1862 .Case("v31", AArch64::Q31)
1863 .Default(0);
1864}
1865
Sander de Smalen73937b72018-04-11 07:36:10 +00001866/// Returns an optional pair of (#elements, element-width) if Suffix
1867/// is a valid vector kind. Where the number of elements in a vector
1868/// or the vector width is implicit or explicitly unknown (but still a
1869/// valid suffix kind), 0 is used.
1870static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1871 RegKind VectorKind) {
1872 std::pair<int, int> Res = {-1, -1};
1873
1874 switch (VectorKind) {
1875 case RegKind::NeonVector:
1876 Res =
1877 StringSwitch<std::pair<int, int>>(Suffix.lower())
1878 .Case("", {0, 0})
1879 .Case(".1d", {1, 64})
1880 .Case(".1q", {1, 128})
1881 // '.2h' needed for fp16 scalar pairwise reductions
1882 .Case(".2h", {2, 16})
1883 .Case(".2s", {2, 32})
1884 .Case(".2d", {2, 64})
1885 // '.4b' is another special case for the ARMv8.2a dot product
1886 // operand
1887 .Case(".4b", {4, 8})
1888 .Case(".4h", {4, 16})
1889 .Case(".4s", {4, 32})
1890 .Case(".8b", {8, 8})
1891 .Case(".8h", {8, 16})
1892 .Case(".16b", {16, 8})
1893 // Accept the width neutral ones, too, for verbose syntax. If those
1894 // aren't used in the right places, the token operand won't match so
1895 // all will work out.
1896 .Case(".b", {0, 8})
1897 .Case(".h", {0, 16})
1898 .Case(".s", {0, 32})
1899 .Case(".d", {0, 64})
1900 .Default({-1, -1});
1901 break;
1902 case RegKind::SVEPredicateVector:
1903 case RegKind::SVEDataVector:
1904 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1905 .Case("", {0, 0})
1906 .Case(".b", {0, 8})
1907 .Case(".h", {0, 16})
1908 .Case(".s", {0, 32})
1909 .Case(".d", {0, 64})
1910 .Case(".q", {0, 128})
1911 .Default({-1, -1});
1912 break;
1913 default:
1914 llvm_unreachable("Unsupported RegKind");
1915 }
1916
1917 if (Res == std::make_pair(-1, -1))
1918 return Optional<std::pair<int, int>>();
1919
1920 return Optional<std::pair<int, int>>(Res);
1921}
1922
1923static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1924 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001925}
1926
Florian Hahn91f11e52017-11-07 16:45:48 +00001927static unsigned matchSVEDataVectorRegName(StringRef Name) {
1928 return StringSwitch<unsigned>(Name.lower())
1929 .Case("z0", AArch64::Z0)
1930 .Case("z1", AArch64::Z1)
1931 .Case("z2", AArch64::Z2)
1932 .Case("z3", AArch64::Z3)
1933 .Case("z4", AArch64::Z4)
1934 .Case("z5", AArch64::Z5)
1935 .Case("z6", AArch64::Z6)
1936 .Case("z7", AArch64::Z7)
1937 .Case("z8", AArch64::Z8)
1938 .Case("z9", AArch64::Z9)
1939 .Case("z10", AArch64::Z10)
1940 .Case("z11", AArch64::Z11)
1941 .Case("z12", AArch64::Z12)
1942 .Case("z13", AArch64::Z13)
1943 .Case("z14", AArch64::Z14)
1944 .Case("z15", AArch64::Z15)
1945 .Case("z16", AArch64::Z16)
1946 .Case("z17", AArch64::Z17)
1947 .Case("z18", AArch64::Z18)
1948 .Case("z19", AArch64::Z19)
1949 .Case("z20", AArch64::Z20)
1950 .Case("z21", AArch64::Z21)
1951 .Case("z22", AArch64::Z22)
1952 .Case("z23", AArch64::Z23)
1953 .Case("z24", AArch64::Z24)
1954 .Case("z25", AArch64::Z25)
1955 .Case("z26", AArch64::Z26)
1956 .Case("z27", AArch64::Z27)
1957 .Case("z28", AArch64::Z28)
1958 .Case("z29", AArch64::Z29)
1959 .Case("z30", AArch64::Z30)
1960 .Case("z31", AArch64::Z31)
1961 .Default(0);
1962}
1963
Sander de Smalencd6be962017-12-20 11:02:42 +00001964static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1965 return StringSwitch<unsigned>(Name.lower())
1966 .Case("p0", AArch64::P0)
1967 .Case("p1", AArch64::P1)
1968 .Case("p2", AArch64::P2)
1969 .Case("p3", AArch64::P3)
1970 .Case("p4", AArch64::P4)
1971 .Case("p5", AArch64::P5)
1972 .Case("p6", AArch64::P6)
1973 .Case("p7", AArch64::P7)
1974 .Case("p8", AArch64::P8)
1975 .Case("p9", AArch64::P9)
1976 .Case("p10", AArch64::P10)
1977 .Case("p11", AArch64::P11)
1978 .Case("p12", AArch64::P12)
1979 .Case("p13", AArch64::P13)
1980 .Case("p14", AArch64::P14)
1981 .Case("p15", AArch64::P15)
1982 .Default(0);
1983}
1984
Tim Northover3b0846e2014-05-24 12:50:23 +00001985bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1986 SMLoc &EndLoc) {
1987 StartLoc = getLoc();
1988 RegNo = tryParseRegister();
1989 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1990 return (RegNo == (unsigned)-1);
1991}
1992
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001993// Matches a register name or register alias previously defined by '.req'
1994unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001995 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001996 unsigned RegNum = 0;
1997 if ((RegNum = matchSVEDataVectorRegName(Name)))
1998 return Kind == RegKind::SVEDataVector ? RegNum : 0;
1999
Sander de Smalencd6be962017-12-20 11:02:42 +00002000 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2001 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2002
Sander de Smalenc067c302017-12-20 09:45:45 +00002003 if ((RegNum = MatchNeonVectorRegName(Name)))
2004 return Kind == RegKind::NeonVector ? RegNum : 0;
2005
2006 // The parsed register must be of RegKind Scalar
2007 if ((RegNum = MatchRegisterName(Name)))
2008 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002009
Florian Hahnc4422242017-11-07 13:07:50 +00002010 if (!RegNum) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002011 // Check for aliases registered via .req. Canonicalize to lower case.
2012 // That's more consistent since register names are case insensitive, and
2013 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2014 auto Entry = RegisterReqs.find(Name.lower());
2015 if (Entry == RegisterReqs.end())
2016 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002017
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002018 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002019 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002020 RegNum = Entry->getValue().second;
2021 }
2022 return RegNum;
2023}
2024
Tim Northover3b0846e2014-05-24 12:50:23 +00002025/// tryParseRegister - Try to parse a register name. The token must be an
2026/// Identifier when called, and if it is a register name the token is eaten and
2027/// the register is added to the operand list.
2028int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002029 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002030 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002031 if (Tok.isNot(AsmToken::Identifier))
2032 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00002033
2034 std::string lowerCase = Tok.getString().lower();
Florian Hahnc4422242017-11-07 13:07:50 +00002035 unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
Sander de Smalenc067c302017-12-20 09:45:45 +00002036
Tim Northover3b0846e2014-05-24 12:50:23 +00002037 // Also handle a few aliases of registers.
2038 if (RegNum == 0)
2039 RegNum = StringSwitch<unsigned>(lowerCase)
2040 .Case("fp", AArch64::FP)
2041 .Case("lr", AArch64::LR)
2042 .Case("x31", AArch64::XZR)
2043 .Case("w31", AArch64::WZR)
2044 .Default(0);
2045
2046 if (RegNum == 0)
2047 return -1;
2048
2049 Parser.Lex(); // Eat identifier token.
2050 return RegNum;
2051}
2052
Tim Northover3b0846e2014-05-24 12:50:23 +00002053/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002054OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002055AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002056 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002057 SMLoc S = getLoc();
2058
2059 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2060 Error(S, "Expected cN operand where 0 <= N <= 15");
2061 return MatchOperand_ParseFail;
2062 }
2063
2064 StringRef Tok = Parser.getTok().getIdentifier();
2065 if (Tok[0] != 'c' && Tok[0] != 'C') {
2066 Error(S, "Expected cN operand where 0 <= N <= 15");
2067 return MatchOperand_ParseFail;
2068 }
2069
2070 uint32_t CRNum;
2071 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2072 if (BadNum || CRNum > 15) {
2073 Error(S, "Expected cN operand where 0 <= N <= 15");
2074 return MatchOperand_ParseFail;
2075 }
2076
2077 Parser.Lex(); // Eat identifier token.
2078 Operands.push_back(
2079 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2080 return MatchOperand_Success;
2081}
2082
2083/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002084OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002085AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002086 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002087 SMLoc S = getLoc();
2088 const AsmToken &Tok = Parser.getTok();
2089 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002090 // Eat optional hash.
2091 if (parseOptionalToken(AsmToken::Hash) ||
2092 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002093 const MCExpr *ImmVal;
2094 if (getParser().parseExpression(ImmVal))
2095 return MatchOperand_ParseFail;
2096
2097 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2098 if (!MCE) {
2099 TokError("immediate value expected for prefetch operand");
2100 return MatchOperand_ParseFail;
2101 }
2102 unsigned prfop = MCE->getValue();
2103 if (prfop > 31) {
2104 TokError("prefetch operand out of range, [0,31] expected");
2105 return MatchOperand_ParseFail;
2106 }
2107
Tim Northovere6ae6762016-07-05 21:23:04 +00002108 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2109 Operands.push_back(AArch64Operand::CreatePrefetch(
2110 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002111 return MatchOperand_Success;
2112 }
2113
2114 if (Tok.isNot(AsmToken::Identifier)) {
2115 TokError("pre-fetch hint expected");
2116 return MatchOperand_ParseFail;
2117 }
2118
Tim Northovere6ae6762016-07-05 21:23:04 +00002119 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2120 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002121 TokError("pre-fetch hint expected");
2122 return MatchOperand_ParseFail;
2123 }
2124
2125 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002126 Operands.push_back(AArch64Operand::CreatePrefetch(
2127 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002128 return MatchOperand_Success;
2129}
2130
Oliver Stannarda34e4702015-12-01 10:48:51 +00002131/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002132OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002133AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2134 MCAsmParser &Parser = getParser();
2135 SMLoc S = getLoc();
2136 const AsmToken &Tok = Parser.getTok();
2137 if (Tok.isNot(AsmToken::Identifier)) {
2138 TokError("invalid operand for instruction");
2139 return MatchOperand_ParseFail;
2140 }
2141
Tim Northovere6ae6762016-07-05 21:23:04 +00002142 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2143 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002144 TokError("invalid operand for instruction");
2145 return MatchOperand_ParseFail;
2146 }
2147
2148 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002149 Operands.push_back(AArch64Operand::CreatePSBHint(
2150 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002151 return MatchOperand_Success;
2152}
2153
Tim Northover3b0846e2014-05-24 12:50:23 +00002154/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2155/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002156OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002157AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002158 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002159 SMLoc S = getLoc();
2160 const MCExpr *Expr;
2161
2162 if (Parser.getTok().is(AsmToken::Hash)) {
2163 Parser.Lex(); // Eat hash token.
2164 }
2165
2166 if (parseSymbolicImmVal(Expr))
2167 return MatchOperand_ParseFail;
2168
2169 AArch64MCExpr::VariantKind ELFRefKind;
2170 MCSymbolRefExpr::VariantKind DarwinRefKind;
2171 int64_t Addend;
2172 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2173 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2174 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2175 // No modifier was specified at all; this is the syntax for an ELF basic
2176 // ADRP relocation (unfortunately).
2177 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002178 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002179 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2180 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2181 Addend != 0) {
2182 Error(S, "gotpage label reference not allowed an addend");
2183 return MatchOperand_ParseFail;
2184 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2185 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2186 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2187 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2188 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2189 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2190 // The operand must be an @page or @gotpage qualified symbolref.
2191 Error(S, "page or gotpage label reference expected");
2192 return MatchOperand_ParseFail;
2193 }
2194 }
2195
2196 // We have either a label reference possibly with addend or an immediate. The
2197 // addend is a raw value here. The linker will adjust it to only reference the
2198 // page.
2199 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2200 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2201
2202 return MatchOperand_Success;
2203}
2204
2205/// tryParseAdrLabel - Parse and validate a source label for the ADR
2206/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002207OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002208AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2209 SMLoc S = getLoc();
2210 const MCExpr *Expr;
2211
Nirav Davee833c6c2016-11-08 18:31:04 +00002212 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002213 if (getParser().parseExpression(Expr))
2214 return MatchOperand_ParseFail;
2215
2216 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2217 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2218
2219 return MatchOperand_Success;
2220}
2221
2222/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002223OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002224AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002225 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002226 SMLoc S = getLoc();
2227
Nirav Davee833c6c2016-11-08 18:31:04 +00002228 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002229
2230 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002231 bool isNegative = parseOptionalToken(AsmToken::Minus);
2232
Tim Northover3b0846e2014-05-24 12:50:23 +00002233 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002234 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002235 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002236 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002237 Val = Tok.getIntVal();
2238 if (Val > 255 || Val < 0) {
2239 TokError("encoded floating point value out of range");
2240 return MatchOperand_ParseFail;
2241 }
2242 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002243 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002244 if (isNegative)
2245 RealVal.changeSign();
2246
Tim Northover3b0846e2014-05-24 12:50:23 +00002247 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002248 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002249
John Brawn5ca5daa2017-04-20 10:13:54 +00002250 // Check for out of range values. As an exception we let Zero through,
2251 // but as tokens instead of an FPImm so that it can be matched by the
2252 // appropriate alias if one exists.
2253 if (RealVal.isPosZero()) {
2254 Parser.Lex(); // Eat the token.
2255 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2256 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2257 return MatchOperand_Success;
2258 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002259 TokError("expected compatible register or floating-point constant");
2260 return MatchOperand_ParseFail;
2261 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002262 }
2263 Parser.Lex(); // Eat the token.
2264 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2265 return MatchOperand_Success;
2266 }
2267
2268 if (!Hash)
2269 return MatchOperand_NoMatch;
2270
2271 TokError("invalid floating point immediate");
2272 return MatchOperand_ParseFail;
2273}
2274
2275/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002276OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002277AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002278 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002279 SMLoc S = getLoc();
2280
2281 if (Parser.getTok().is(AsmToken::Hash))
2282 Parser.Lex(); // Eat '#'
2283 else if (Parser.getTok().isNot(AsmToken::Integer))
2284 // Operand should start from # or should be integer, emit error otherwise.
2285 return MatchOperand_NoMatch;
2286
2287 const MCExpr *Imm;
2288 if (parseSymbolicImmVal(Imm))
2289 return MatchOperand_ParseFail;
2290 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2291 uint64_t ShiftAmount = 0;
2292 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2293 if (MCE) {
2294 int64_t Val = MCE->getValue();
2295 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002296 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002297 ShiftAmount = 12;
2298 }
2299 }
2300 SMLoc E = Parser.getTok().getLoc();
2301 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2302 getContext()));
2303 return MatchOperand_Success;
2304 }
2305
2306 // Eat ','
2307 Parser.Lex();
2308
2309 // The optional operand must be "lsl #N" where N is non-negative.
2310 if (!Parser.getTok().is(AsmToken::Identifier) ||
2311 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2312 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2313 return MatchOperand_ParseFail;
2314 }
2315
2316 // Eat 'lsl'
2317 Parser.Lex();
2318
Nirav Davee833c6c2016-11-08 18:31:04 +00002319 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002320
2321 if (Parser.getTok().isNot(AsmToken::Integer)) {
2322 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2323 return MatchOperand_ParseFail;
2324 }
2325
2326 int64_t ShiftAmount = Parser.getTok().getIntVal();
2327
2328 if (ShiftAmount < 0) {
2329 Error(Parser.getTok().getLoc(), "positive shift amount required");
2330 return MatchOperand_ParseFail;
2331 }
2332 Parser.Lex(); // Eat the number
2333
2334 SMLoc E = Parser.getTok().getLoc();
2335 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2336 S, E, getContext()));
2337 return MatchOperand_Success;
2338}
2339
2340/// parseCondCodeString - Parse a Condition Code string.
2341AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2342 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2343 .Case("eq", AArch64CC::EQ)
2344 .Case("ne", AArch64CC::NE)
2345 .Case("cs", AArch64CC::HS)
2346 .Case("hs", AArch64CC::HS)
2347 .Case("cc", AArch64CC::LO)
2348 .Case("lo", AArch64CC::LO)
2349 .Case("mi", AArch64CC::MI)
2350 .Case("pl", AArch64CC::PL)
2351 .Case("vs", AArch64CC::VS)
2352 .Case("vc", AArch64CC::VC)
2353 .Case("hi", AArch64CC::HI)
2354 .Case("ls", AArch64CC::LS)
2355 .Case("ge", AArch64CC::GE)
2356 .Case("lt", AArch64CC::LT)
2357 .Case("gt", AArch64CC::GT)
2358 .Case("le", AArch64CC::LE)
2359 .Case("al", AArch64CC::AL)
2360 .Case("nv", AArch64CC::NV)
2361 .Default(AArch64CC::Invalid);
2362 return CC;
2363}
2364
2365/// parseCondCode - Parse a Condition Code operand.
2366bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2367 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002368 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002369 SMLoc S = getLoc();
2370 const AsmToken &Tok = Parser.getTok();
2371 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2372
2373 StringRef Cond = Tok.getString();
2374 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2375 if (CC == AArch64CC::Invalid)
2376 return TokError("invalid condition code");
2377 Parser.Lex(); // Eat identifier token.
2378
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002379 if (invertCondCode) {
2380 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2381 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002382 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002383 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002384
2385 Operands.push_back(
2386 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2387 return false;
2388}
2389
2390/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2391/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002392OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002393AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002394 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002395 const AsmToken &Tok = Parser.getTok();
2396 std::string LowerID = Tok.getString().lower();
2397 AArch64_AM::ShiftExtendType ShOp =
2398 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2399 .Case("lsl", AArch64_AM::LSL)
2400 .Case("lsr", AArch64_AM::LSR)
2401 .Case("asr", AArch64_AM::ASR)
2402 .Case("ror", AArch64_AM::ROR)
2403 .Case("msl", AArch64_AM::MSL)
2404 .Case("uxtb", AArch64_AM::UXTB)
2405 .Case("uxth", AArch64_AM::UXTH)
2406 .Case("uxtw", AArch64_AM::UXTW)
2407 .Case("uxtx", AArch64_AM::UXTX)
2408 .Case("sxtb", AArch64_AM::SXTB)
2409 .Case("sxth", AArch64_AM::SXTH)
2410 .Case("sxtw", AArch64_AM::SXTW)
2411 .Case("sxtx", AArch64_AM::SXTX)
2412 .Default(AArch64_AM::InvalidShiftExtend);
2413
2414 if (ShOp == AArch64_AM::InvalidShiftExtend)
2415 return MatchOperand_NoMatch;
2416
2417 SMLoc S = Tok.getLoc();
2418 Parser.Lex();
2419
Nirav Davee833c6c2016-11-08 18:31:04 +00002420 bool Hash = parseOptionalToken(AsmToken::Hash);
2421
Tim Northover3b0846e2014-05-24 12:50:23 +00002422 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2423 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2424 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2425 ShOp == AArch64_AM::MSL) {
2426 // We expect a number here.
2427 TokError("expected #imm after shift specifier");
2428 return MatchOperand_ParseFail;
2429 }
2430
Chad Rosier2ff37b82016-12-27 16:58:09 +00002431 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002432 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2433 Operands.push_back(
2434 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2435 return MatchOperand_Success;
2436 }
2437
Chad Rosier2ff37b82016-12-27 16:58:09 +00002438 // Make sure we do actually have a number, identifier or a parenthesized
2439 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002440 SMLoc E = Parser.getTok().getLoc();
2441 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002442 !Parser.getTok().is(AsmToken::LParen) &&
2443 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002444 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002445 return MatchOperand_ParseFail;
2446 }
2447
2448 const MCExpr *ImmVal;
2449 if (getParser().parseExpression(ImmVal))
2450 return MatchOperand_ParseFail;
2451
2452 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2453 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002454 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002455 return MatchOperand_ParseFail;
2456 }
2457
Jim Grosbach57fd2622014-09-23 22:16:02 +00002458 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002459 Operands.push_back(AArch64Operand::CreateShiftExtend(
2460 ShOp, MCE->getValue(), true, S, E, getContext()));
2461 return MatchOperand_Success;
2462}
2463
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002464static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2465 if (FBS[AArch64::HasV8_1aOps])
2466 Str += "ARMv8.1a";
2467 else if (FBS[AArch64::HasV8_2aOps])
2468 Str += "ARMv8.2a";
2469 else
2470 Str += "(unknown)";
2471}
2472
2473void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2474 SMLoc S) {
2475 const uint16_t Op2 = Encoding & 7;
2476 const uint16_t Cm = (Encoding & 0x78) >> 3;
2477 const uint16_t Cn = (Encoding & 0x780) >> 7;
2478 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2479
2480 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2481
2482 Operands.push_back(
2483 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2484 Operands.push_back(
2485 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2486 Operands.push_back(
2487 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2488 Expr = MCConstantExpr::create(Op2, getContext());
2489 Operands.push_back(
2490 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2491}
2492
Tim Northover3b0846e2014-05-24 12:50:23 +00002493/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2494/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2495bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2496 OperandVector &Operands) {
2497 if (Name.find('.') != StringRef::npos)
2498 return TokError("invalid operand");
2499
2500 Mnemonic = Name;
2501 Operands.push_back(
2502 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2503
Rafael Espindola961d4692014-11-11 05:18:41 +00002504 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002505 const AsmToken &Tok = Parser.getTok();
2506 StringRef Op = Tok.getString();
2507 SMLoc S = Tok.getLoc();
2508
Tim Northover3b0846e2014-05-24 12:50:23 +00002509 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002510 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2511 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002512 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002513 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2514 std::string Str("IC " + std::string(IC->Name) + " requires ");
2515 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2516 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002517 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002518 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002519 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002520 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2521 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002522 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002523 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2524 std::string Str("DC " + std::string(DC->Name) + " requires ");
2525 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2526 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002527 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002528 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002529 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002530 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2531 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002532 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002533 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2534 std::string Str("AT " + std::string(AT->Name) + " requires ");
2535 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2536 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002537 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002538 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002539 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002540 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2541 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002542 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002543 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2544 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2545 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2546 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002547 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002548 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002549 }
2550
Tim Northover3b0846e2014-05-24 12:50:23 +00002551 Parser.Lex(); // Eat operand.
2552
2553 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2554 bool HasRegister = false;
2555
2556 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002557 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002558 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2559 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002560 HasRegister = true;
2561 }
2562
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002563 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002564 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002565 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002566 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002567
Nirav Davee833c6c2016-11-08 18:31:04 +00002568 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2569 return true;
2570
Tim Northover3b0846e2014-05-24 12:50:23 +00002571 return false;
2572}
2573
Alex Bradbury58eba092016-11-01 16:32:05 +00002574OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002575AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002576 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002577 const AsmToken &Tok = Parser.getTok();
2578
2579 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002580 if (parseOptionalToken(AsmToken::Hash) ||
2581 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002582 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002583 const MCExpr *ImmVal;
2584 SMLoc ExprLoc = getLoc();
2585 if (getParser().parseExpression(ImmVal))
2586 return MatchOperand_ParseFail;
2587 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2588 if (!MCE) {
2589 Error(ExprLoc, "immediate value expected for barrier operand");
2590 return MatchOperand_ParseFail;
2591 }
2592 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2593 Error(ExprLoc, "barrier operand out of range");
2594 return MatchOperand_ParseFail;
2595 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002596 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2597 Operands.push_back(AArch64Operand::CreateBarrier(
2598 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002599 return MatchOperand_Success;
2600 }
2601
2602 if (Tok.isNot(AsmToken::Identifier)) {
2603 TokError("invalid operand for instruction");
2604 return MatchOperand_ParseFail;
2605 }
2606
Tim Northover3b0846e2014-05-24 12:50:23 +00002607 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002608 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2609 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002610 TokError("'sy' or #imm operand expected");
2611 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002612 } else if (!DB) {
2613 TokError("invalid barrier option name");
2614 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002615 }
2616
Tim Northovere6ae6762016-07-05 21:23:04 +00002617 Operands.push_back(AArch64Operand::CreateBarrier(
2618 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002619 Parser.Lex(); // Consume the option
2620
2621 return MatchOperand_Success;
2622}
2623
Alex Bradbury58eba092016-11-01 16:32:05 +00002624OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002625AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002626 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002627 const AsmToken &Tok = Parser.getTok();
2628
2629 if (Tok.isNot(AsmToken::Identifier))
2630 return MatchOperand_NoMatch;
2631
Tim Northovere6ae6762016-07-05 21:23:04 +00002632 int MRSReg, MSRReg;
2633 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2634 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2635 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2636 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2637 } else
2638 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002639
Tim Northovere6ae6762016-07-05 21:23:04 +00002640 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2641 unsigned PStateImm = -1;
2642 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2643 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002644
Tim Northovere6ae6762016-07-05 21:23:04 +00002645 Operands.push_back(
2646 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2647 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002648 Parser.Lex(); // Eat identifier
2649
2650 return MatchOperand_Success;
2651}
2652
Florian Hahnc4422242017-11-07 13:07:50 +00002653/// tryParseNeonVectorRegister - Parse a vector register operand.
2654bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002655 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002656 if (Parser.getTok().isNot(AsmToken::Identifier))
2657 return true;
2658
2659 SMLoc S = getLoc();
2660 // Check for a vector register specifier first.
2661 StringRef Kind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002662 int Reg = -1;
2663 OperandMatchResultTy Res =
2664 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2665 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002666 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002667
2668 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2669 if (!KindRes)
2670 return true;
2671
2672 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002673 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002674 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2675 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002676
Tim Northover3b0846e2014-05-24 12:50:23 +00002677 // If there was an explicit qualifier, that goes on as a literal text
2678 // operand.
2679 if (!Kind.empty())
2680 Operands.push_back(
2681 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2682
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002683 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2684}
2685
2686OperandMatchResultTy
2687AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002688 SMLoc SIdx = getLoc();
2689 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002690 const MCExpr *ImmVal;
2691 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002692 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002693 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2694 if (!MCE) {
2695 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002696 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002697 }
2698
2699 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002700
Nirav Davee833c6c2016-11-08 18:31:04 +00002701 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002702 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002703
2704 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2705 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002706 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002707 }
2708
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002709 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002710}
2711
Sander de Smalen73937b72018-04-11 07:36:10 +00002712// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002713// optional kind specifier. If it is a register specifier, eat the token
2714// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002715OperandMatchResultTy
Sander de Smalen73937b72018-04-11 07:36:10 +00002716AArch64AsmParser::tryParseVectorRegister(int &Reg, StringRef &Kind,
2717 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002718 MCAsmParser &Parser = getParser();
2719 const AsmToken &Tok = Parser.getTok();
2720
Florian Hahn91f11e52017-11-07 16:45:48 +00002721 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002722 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002723
2724 StringRef Name = Tok.getString();
2725 // If there is a kind specifier, it's separated from the register name by
2726 // a '.'.
2727 size_t Start = 0, Next = Name.find('.');
2728 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002729 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002730
2731 if (RegNum) {
2732 if (Next != StringRef::npos) {
2733 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002734 if (!isValidVectorKind(Kind, MatchKind)) {
2735 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002736 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002737 }
2738 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002739 Parser.Lex(); // Eat the register token.
2740
2741 Reg = RegNum;
2742 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002743 }
2744
Sander de Smalen8e607342017-11-15 15:44:43 +00002745 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002746}
2747
Sander de Smalencd6be962017-12-20 11:02:42 +00002748/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2749OperandMatchResultTy
2750AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2751 // Check for a SVE predicate register specifier first.
2752 const SMLoc S = getLoc();
2753 StringRef Kind;
2754 int RegNum = -1;
Sander de Smalen73937b72018-04-11 07:36:10 +00002755 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002756 if (Res != MatchOperand_Success)
2757 return Res;
2758
Sander de Smalen73937b72018-04-11 07:36:10 +00002759 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2760 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002761 return MatchOperand_NoMatch;
2762
Sander de Smalen73937b72018-04-11 07:36:10 +00002763 unsigned ElementWidth = KindRes->second;
2764 Operands.push_back(AArch64Operand::CreateVectorReg(
2765 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2766 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002767
Sander de Smalen7868e742018-01-09 11:17:06 +00002768 // Not all predicates are followed by a '/m' or '/z'.
2769 MCAsmParser &Parser = getParser();
2770 if (Parser.getTok().isNot(AsmToken::Slash))
2771 return MatchOperand_Success;
2772
2773 // But when they do they shouldn't have an element type suffix.
2774 if (!Kind.empty()) {
2775 Error(S, "not expecting size suffix");
2776 return MatchOperand_ParseFail;
2777 }
2778
2779 // Add a literal slash as operand
2780 Operands.push_back(
2781 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2782
2783 Parser.Lex(); // Eat the slash.
2784
2785 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002786 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002787 if (Pred != "z" && Pred != "m") {
2788 Error(getLoc(), "expecting 'm' or 'z' predication");
2789 return MatchOperand_ParseFail;
2790 }
2791
2792 // Add zero/merge token.
2793 const char *ZM = Pred == "z" ? "z" : "m";
2794 Operands.push_back(
2795 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2796
2797 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002798 return MatchOperand_Success;
2799}
2800
Tim Northover3b0846e2014-05-24 12:50:23 +00002801/// parseRegister - Parse a non-vector register operand.
2802bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2803 SMLoc S = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00002804 // Try for a vector (neon) register.
2805 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002806 return false;
2807
2808 // Try for a scalar register.
2809 int64_t Reg = tryParseRegister();
2810 if (Reg == -1)
2811 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002812 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2813 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002814
Tim Northover3b0846e2014-05-24 12:50:23 +00002815 return false;
2816}
2817
2818bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002819 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002820 bool HasELFModifier = false;
2821 AArch64MCExpr::VariantKind RefKind;
2822
Nirav Davee833c6c2016-11-08 18:31:04 +00002823 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002824 HasELFModifier = true;
2825
Nirav Davee833c6c2016-11-08 18:31:04 +00002826 if (Parser.getTok().isNot(AsmToken::Identifier))
2827 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002828
2829 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2830 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2831 .Case("lo12", AArch64MCExpr::VK_LO12)
2832 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2833 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2834 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2835 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2836 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2837 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2838 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2839 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2840 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2841 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2842 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2843 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2844 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2845 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2846 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2847 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2848 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2849 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2850 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2851 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2852 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2853 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2854 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2855 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2856 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2857 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2858 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2859 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2860 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2861 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2862 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2863 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2864 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2865 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002866 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2867 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002868 .Default(AArch64MCExpr::VK_INVALID);
2869
Nirav Davee833c6c2016-11-08 18:31:04 +00002870 if (RefKind == AArch64MCExpr::VK_INVALID)
2871 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002872
2873 Parser.Lex(); // Eat identifier
2874
Nirav Davee833c6c2016-11-08 18:31:04 +00002875 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002876 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002877 }
2878
2879 if (getParser().parseExpression(ImmVal))
2880 return true;
2881
2882 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002883 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002884
2885 return false;
2886}
2887
Sander de Smalen650234b2018-04-12 11:40:52 +00002888template <RegKind VectorKind>
2889OperandMatchResultTy
2890AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
2891 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002892 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00002893 if (!Parser.getTok().is(AsmToken::LCurly))
2894 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002895
2896 // Wrapper around parse function
Sander de Smalen650234b2018-04-12 11:40:52 +00002897 auto ParseVector = [this, &Parser](int &Reg, StringRef &Kind, SMLoc Loc,
2898 bool NoMatchIsError) {
2899 auto RegTok = Parser.getTok();
2900 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
2901 if (ParseRes == MatchOperand_Success) {
Sander de Smalen73937b72018-04-11 07:36:10 +00002902 if (parseVectorKind(Kind, RegKind::NeonVector))
Sander de Smalen650234b2018-04-12 11:40:52 +00002903 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002904 llvm_unreachable("Expected a valid vector kind");
2905 }
2906
Sander de Smalen650234b2018-04-12 11:40:52 +00002907 if (RegTok.isNot(AsmToken::Identifier) ||
2908 ParseRes == MatchOperand_ParseFail ||
2909 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
2910 Error(Loc, "vector register expected");
2911 return MatchOperand_ParseFail;
2912 }
2913
2914 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002915 };
2916
Tim Northover3b0846e2014-05-24 12:50:23 +00002917 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00002918 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00002919 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00002920
Tim Northover3b0846e2014-05-24 12:50:23 +00002921 StringRef Kind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002922 int FirstReg = -1;
Sander de Smalen650234b2018-04-12 11:40:52 +00002923 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
2924
2925 // Put back the original left bracket if there was no match, so that
2926 // different types of list-operands can be matched (e.g. SVE, Neon).
2927 if (ParseRes == MatchOperand_NoMatch)
2928 Parser.getLexer().UnLex(LCurly);
2929
2930 if (ParseRes != MatchOperand_Success)
2931 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002932
Tim Northover3b0846e2014-05-24 12:50:23 +00002933 int64_t PrevReg = FirstReg;
2934 unsigned Count = 1;
2935
Nirav Davee833c6c2016-11-08 18:31:04 +00002936 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002937 SMLoc Loc = getLoc();
2938 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002939
2940 int Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002941 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2942 if (ParseRes != MatchOperand_Success)
2943 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002944
Tim Northover3b0846e2014-05-24 12:50:23 +00002945 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002946 if (Kind != NextKind) {
2947 Error(Loc, "mismatched register size suffix");
2948 return MatchOperand_ParseFail;
2949 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002950
2951 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2952
2953 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002954 Error(Loc, "invalid number of vectors");
2955 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002956 }
2957
2958 Count += Space;
2959 }
2960 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002961 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002962 SMLoc Loc = getLoc();
2963 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002964 int Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002965 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2966 if (ParseRes != MatchOperand_Success)
2967 return ParseRes;
2968
Tim Northover3b0846e2014-05-24 12:50:23 +00002969 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002970 if (Kind != NextKind) {
2971 Error(Loc, "mismatched register size suffix");
2972 return MatchOperand_ParseFail;
2973 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002974
2975 // Registers must be incremental (with wraparound at 31)
2976 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00002977 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
2978 Error(Loc, "registers must be sequential");
2979 return MatchOperand_ParseFail;
2980 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002981
2982 PrevReg = Reg;
2983 ++Count;
2984 }
2985 }
2986
Nirav Davee833c6c2016-11-08 18:31:04 +00002987 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00002988 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002989
Sander de Smalen650234b2018-04-12 11:40:52 +00002990 if (Count > 4) {
2991 Error(S, "invalid number of vectors");
2992 return MatchOperand_ParseFail;
2993 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002994
2995 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00002996 unsigned ElementWidth = 0;
2997 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002998 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00002999 std::tie(NumElements, ElementWidth) = *VK;
3000 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003001
3002 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003003 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3004 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003005
Sander de Smalen650234b2018-04-12 11:40:52 +00003006 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003007}
3008
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003009/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3010bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003011 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3012 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003013 return true;
3014
3015 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3016}
3017
Alex Bradbury58eba092016-11-01 16:32:05 +00003018OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003019AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003020 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003021 const AsmToken &Tok = Parser.getTok();
3022 if (!Tok.is(AsmToken::Identifier))
3023 return MatchOperand_NoMatch;
3024
Florian Hahnc4422242017-11-07 13:07:50 +00003025 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00003026
3027 MCContext &Ctx = getContext();
3028 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
3029 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
3030 return MatchOperand_NoMatch;
3031
3032 SMLoc S = getLoc();
3033 Parser.Lex(); // Eat register
3034
Nirav Davee833c6c2016-11-08 18:31:04 +00003035 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003036 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003037 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003038 return MatchOperand_Success;
3039 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003040
Nirav Davee833c6c2016-11-08 18:31:04 +00003041 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003042
3043 if (Parser.getTok().isNot(AsmToken::Integer)) {
3044 Error(getLoc(), "index must be absent or #0");
3045 return MatchOperand_ParseFail;
3046 }
3047
3048 const MCExpr *ImmVal;
3049 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3050 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3051 Error(getLoc(), "index must be absent or #0");
3052 return MatchOperand_ParseFail;
3053 }
3054
3055 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003056 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003057 return MatchOperand_Success;
3058}
3059
Sander de Smalen5c625982018-04-13 12:56:14 +00003060bool AArch64AsmParser::parseOptionalMulVl(OperandVector &Operands) {
3061 MCAsmParser &Parser = getParser();
3062
3063 // Some SVE instructions have a decoration after the immediate, i.e.
3064 // "mul vl". We parse them here and add tokens, which must be present in the
3065 // asm string in the tablegen instruction.
3066 if (!Parser.getTok().getString().equals_lower("mul") ||
3067 !Parser.getLexer().peekTok().getString().equals_lower("vl"))
3068 return true;
3069
3070 SMLoc S = getLoc();
3071 Operands.push_back(
3072 AArch64Operand::CreateToken("mul", false, S, getContext()));
3073 Parser.Lex(); // Eat the "mul"
3074
3075 S = getLoc();
3076 Operands.push_back(
3077 AArch64Operand::CreateToken("vl", false, S, getContext()));
3078 Parser.Lex(); // Eat the "vl"
3079
3080 return false;
3081}
3082
Tim Northover3b0846e2014-05-24 12:50:23 +00003083/// parseOperand - Parse a arm instruction operand. For now this parses the
3084/// operand regardless of the mnemonic.
3085bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3086 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003087 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003088
3089 OperandMatchResultTy ResTy =
3090 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3091
Tim Northover3b0846e2014-05-24 12:50:23 +00003092 // Check if the current operand has a custom associated parser, if so, try to
3093 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003094 if (ResTy == MatchOperand_Success)
3095 return false;
3096 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3097 // there was a match, but an error occurred, in which case, just return that
3098 // the operand parsing failed.
3099 if (ResTy == MatchOperand_ParseFail)
3100 return true;
3101
3102 // Nothing custom, so do general case parsing.
3103 SMLoc S, E;
3104 switch (getLexer().getKind()) {
3105 default: {
3106 SMLoc S = getLoc();
3107 const MCExpr *Expr;
3108 if (parseSymbolicImmVal(Expr))
3109 return Error(S, "invalid operand");
3110
3111 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3112 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3113 return false;
3114 }
3115 case AsmToken::LBrac: {
3116 SMLoc Loc = Parser.getTok().getLoc();
3117 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3118 getContext()));
3119 Parser.Lex(); // Eat '['
3120
3121 // There's no comma after a '[', so we can parse the next operand
3122 // immediately.
3123 return parseOperand(Operands, false, false);
3124 }
3125 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003126 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003127 case AsmToken::Identifier: {
3128 // If we're expecting a Condition Code operand, then just parse that.
3129 if (isCondCode)
3130 return parseCondCode(Operands, invertCondCode);
3131
3132 // If it's a register name, parse it.
3133 if (!parseRegister(Operands))
3134 return false;
3135
Sander de Smalen5c625982018-04-13 12:56:14 +00003136 // See if this is a "mul vl" decoration used by SVE instructions.
3137 if (!parseOptionalMulVl(Operands))
3138 return false;
3139
Tim Northover3b0846e2014-05-24 12:50:23 +00003140 // This could be an optional "shift" or "extend" operand.
3141 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3142 // We can only continue if no tokens were eaten.
3143 if (GotShift != MatchOperand_NoMatch)
3144 return GotShift;
3145
3146 // This was not a register so parse other operands that start with an
3147 // identifier (like labels) as expressions and create them as immediates.
3148 const MCExpr *IdVal;
3149 S = getLoc();
3150 if (getParser().parseExpression(IdVal))
3151 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003152 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3153 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3154 return false;
3155 }
3156 case AsmToken::Integer:
3157 case AsmToken::Real:
3158 case AsmToken::Hash: {
3159 // #42 -> immediate.
3160 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003161
3162 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003163
3164 // Parse a negative sign
3165 bool isNegative = false;
3166 if (Parser.getTok().is(AsmToken::Minus)) {
3167 isNegative = true;
3168 // We need to consume this token only when we have a Real, otherwise
3169 // we let parseSymbolicImmVal take care of it
3170 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3171 Parser.Lex();
3172 }
3173
3174 // The only Real that should come through here is a literal #0.0 for
3175 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3176 // so convert the value.
3177 const AsmToken &Tok = Parser.getTok();
3178 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003179 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003180 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3181 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3182 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3183 Mnemonic != "fcmlt")
3184 return TokError("unexpected floating point literal");
3185 else if (IntVal != 0 || isNegative)
3186 return TokError("expected floating-point constant #0.0");
3187 Parser.Lex(); // Eat the token.
3188
3189 Operands.push_back(
3190 AArch64Operand::CreateToken("#0", false, S, getContext()));
3191 Operands.push_back(
3192 AArch64Operand::CreateToken(".0", false, S, getContext()));
3193 return false;
3194 }
3195
3196 const MCExpr *ImmVal;
3197 if (parseSymbolicImmVal(ImmVal))
3198 return true;
3199
3200 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3201 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3202 return false;
3203 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003204 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003205 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003206 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003207 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003208 Parser.Lex(); // Eat '='
3209 const MCExpr *SubExprVal;
3210 if (getParser().parseExpression(SubExprVal))
3211 return true;
3212
David Peixottoae5ba762014-07-18 16:05:14 +00003213 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003214 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003215 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003216
3217 bool IsXReg =
3218 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3219 Operands[1]->getReg());
3220
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003221 MCContext& Ctx = getContext();
3222 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3223 // 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 +00003224 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003225 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3226 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3227 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3228 ShiftAmt += 16;
3229 Imm >>= 16;
3230 }
3231 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3232 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3233 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003234 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003235 if (ShiftAmt)
3236 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3237 ShiftAmt, true, S, E, Ctx));
3238 return false;
3239 }
David Peixottoae5ba762014-07-18 16:05:14 +00003240 APInt Simm = APInt(64, Imm << ShiftAmt);
3241 // check if the immediate is an unsigned or signed 32-bit int for W regs
3242 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3243 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003244 }
3245 // 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 +00003246 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003247 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003248 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3249 return false;
3250 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003251 }
3252}
3253
3254/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3255/// operands.
3256bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3257 StringRef Name, SMLoc NameLoc,
3258 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003259 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003260 Name = StringSwitch<StringRef>(Name.lower())
3261 .Case("beq", "b.eq")
3262 .Case("bne", "b.ne")
3263 .Case("bhs", "b.hs")
3264 .Case("bcs", "b.cs")
3265 .Case("blo", "b.lo")
3266 .Case("bcc", "b.cc")
3267 .Case("bmi", "b.mi")
3268 .Case("bpl", "b.pl")
3269 .Case("bvs", "b.vs")
3270 .Case("bvc", "b.vc")
3271 .Case("bhi", "b.hi")
3272 .Case("bls", "b.ls")
3273 .Case("bge", "b.ge")
3274 .Case("blt", "b.lt")
3275 .Case("bgt", "b.gt")
3276 .Case("ble", "b.le")
3277 .Case("bal", "b.al")
3278 .Case("bnv", "b.nv")
3279 .Default(Name);
3280
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003281 // First check for the AArch64-specific .req directive.
3282 if (Parser.getTok().is(AsmToken::Identifier) &&
3283 Parser.getTok().getIdentifier() == ".req") {
3284 parseDirectiveReq(Name, NameLoc);
3285 // We always return 'error' for this, as we're done with this
3286 // statement and don't need to match the 'instruction."
3287 return true;
3288 }
3289
Tim Northover3b0846e2014-05-24 12:50:23 +00003290 // Create the leading tokens for the mnemonic, split by '.' characters.
3291 size_t Start = 0, Next = Name.find('.');
3292 StringRef Head = Name.slice(Start, Next);
3293
3294 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003295 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3296 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003297
3298 Operands.push_back(
3299 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3300 Mnemonic = Head;
3301
3302 // Handle condition codes for a branch mnemonic
3303 if (Head == "b" && Next != StringRef::npos) {
3304 Start = Next;
3305 Next = Name.find('.', Start + 1);
3306 Head = Name.slice(Start + 1, Next);
3307
3308 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3309 (Head.data() - Name.data()));
3310 AArch64CC::CondCode CC = parseCondCodeString(Head);
3311 if (CC == AArch64CC::Invalid)
3312 return Error(SuffixLoc, "invalid condition code");
3313 Operands.push_back(
3314 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3315 Operands.push_back(
3316 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3317 }
3318
3319 // Add the remaining tokens in the mnemonic.
3320 while (Next != StringRef::npos) {
3321 Start = Next;
3322 Next = Name.find('.', Start + 1);
3323 Head = Name.slice(Start, Next);
3324 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3325 (Head.data() - Name.data()) + 1);
3326 Operands.push_back(
3327 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3328 }
3329
3330 // Conditional compare instructions have a Condition Code operand, which needs
3331 // to be parsed and an immediate operand created.
3332 bool condCodeFourthOperand =
3333 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3334 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3335 Head == "csinc" || Head == "csinv" || Head == "csneg");
3336
3337 // These instructions are aliases to some of the conditional select
3338 // instructions. However, the condition code is inverted in the aliased
3339 // instruction.
3340 //
3341 // FIXME: Is this the correct way to handle these? Or should the parser
3342 // generate the aliased instructions directly?
3343 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3344 bool condCodeThirdOperand =
3345 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3346
3347 // Read the remaining operands.
3348 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3349 // Read the first operand.
3350 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003351 return true;
3352 }
3353
3354 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003355 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003356 // Parse and remember the operand.
3357 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3358 (N == 3 && condCodeThirdOperand) ||
3359 (N == 2 && condCodeSecondOperand),
3360 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003361 return true;
3362 }
3363
3364 // After successfully parsing some operands there are two special cases to
3365 // consider (i.e. notional operands not separated by commas). Both are due
3366 // to memory specifiers:
3367 // + An RBrac will end an address for load/store/prefetch
3368 // + An '!' will indicate a pre-indexed operation.
3369 //
3370 // It's someone else's responsibility to make sure these tokens are sane
3371 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003372
Nirav Davee833c6c2016-11-08 18:31:04 +00003373 SMLoc RLoc = Parser.getTok().getLoc();
3374 if (parseOptionalToken(AsmToken::RBrac))
3375 Operands.push_back(
3376 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3377 SMLoc ELoc = Parser.getTok().getLoc();
3378 if (parseOptionalToken(AsmToken::Exclaim))
3379 Operands.push_back(
3380 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003381
3382 ++N;
3383 }
3384 }
3385
Nirav Davee833c6c2016-11-08 18:31:04 +00003386 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3387 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003388
Tim Northover3b0846e2014-05-24 12:50:23 +00003389 return false;
3390}
3391
3392// FIXME: This entire function is a giant hack to provide us with decent
3393// operand range validation/diagnostics until TableGen/MC can be extended
3394// to support autogeneration of this kind of validation.
3395bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3396 SmallVectorImpl<SMLoc> &Loc) {
3397 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3398 // Check for indexed addressing modes w/ the base register being the
3399 // same as a destination/source register or pair load where
3400 // the Rt == Rt2. All of those are undefined behaviour.
3401 switch (Inst.getOpcode()) {
3402 case AArch64::LDPSWpre:
3403 case AArch64::LDPWpost:
3404 case AArch64::LDPWpre:
3405 case AArch64::LDPXpost:
3406 case AArch64::LDPXpre: {
3407 unsigned Rt = Inst.getOperand(1).getReg();
3408 unsigned Rt2 = Inst.getOperand(2).getReg();
3409 unsigned Rn = Inst.getOperand(3).getReg();
3410 if (RI->isSubRegisterEq(Rn, Rt))
3411 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3412 "is also a destination");
3413 if (RI->isSubRegisterEq(Rn, Rt2))
3414 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3415 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003416 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003417 }
3418 case AArch64::LDPDi:
3419 case AArch64::LDPQi:
3420 case AArch64::LDPSi:
3421 case AArch64::LDPSWi:
3422 case AArch64::LDPWi:
3423 case AArch64::LDPXi: {
3424 unsigned Rt = Inst.getOperand(0).getReg();
3425 unsigned Rt2 = Inst.getOperand(1).getReg();
3426 if (Rt == Rt2)
3427 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3428 break;
3429 }
3430 case AArch64::LDPDpost:
3431 case AArch64::LDPDpre:
3432 case AArch64::LDPQpost:
3433 case AArch64::LDPQpre:
3434 case AArch64::LDPSpost:
3435 case AArch64::LDPSpre:
3436 case AArch64::LDPSWpost: {
3437 unsigned Rt = Inst.getOperand(1).getReg();
3438 unsigned Rt2 = Inst.getOperand(2).getReg();
3439 if (Rt == Rt2)
3440 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3441 break;
3442 }
3443 case AArch64::STPDpost:
3444 case AArch64::STPDpre:
3445 case AArch64::STPQpost:
3446 case AArch64::STPQpre:
3447 case AArch64::STPSpost:
3448 case AArch64::STPSpre:
3449 case AArch64::STPWpost:
3450 case AArch64::STPWpre:
3451 case AArch64::STPXpost:
3452 case AArch64::STPXpre: {
3453 unsigned Rt = Inst.getOperand(1).getReg();
3454 unsigned Rt2 = Inst.getOperand(2).getReg();
3455 unsigned Rn = Inst.getOperand(3).getReg();
3456 if (RI->isSubRegisterEq(Rn, Rt))
3457 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3458 "is also a source");
3459 if (RI->isSubRegisterEq(Rn, Rt2))
3460 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3461 "is also a source");
3462 break;
3463 }
3464 case AArch64::LDRBBpre:
3465 case AArch64::LDRBpre:
3466 case AArch64::LDRHHpre:
3467 case AArch64::LDRHpre:
3468 case AArch64::LDRSBWpre:
3469 case AArch64::LDRSBXpre:
3470 case AArch64::LDRSHWpre:
3471 case AArch64::LDRSHXpre:
3472 case AArch64::LDRSWpre:
3473 case AArch64::LDRWpre:
3474 case AArch64::LDRXpre:
3475 case AArch64::LDRBBpost:
3476 case AArch64::LDRBpost:
3477 case AArch64::LDRHHpost:
3478 case AArch64::LDRHpost:
3479 case AArch64::LDRSBWpost:
3480 case AArch64::LDRSBXpost:
3481 case AArch64::LDRSHWpost:
3482 case AArch64::LDRSHXpost:
3483 case AArch64::LDRSWpost:
3484 case AArch64::LDRWpost:
3485 case AArch64::LDRXpost: {
3486 unsigned Rt = Inst.getOperand(1).getReg();
3487 unsigned Rn = Inst.getOperand(2).getReg();
3488 if (RI->isSubRegisterEq(Rn, Rt))
3489 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3490 "is also a source");
3491 break;
3492 }
3493 case AArch64::STRBBpost:
3494 case AArch64::STRBpost:
3495 case AArch64::STRHHpost:
3496 case AArch64::STRHpost:
3497 case AArch64::STRWpost:
3498 case AArch64::STRXpost:
3499 case AArch64::STRBBpre:
3500 case AArch64::STRBpre:
3501 case AArch64::STRHHpre:
3502 case AArch64::STRHpre:
3503 case AArch64::STRWpre:
3504 case AArch64::STRXpre: {
3505 unsigned Rt = Inst.getOperand(1).getReg();
3506 unsigned Rn = Inst.getOperand(2).getReg();
3507 if (RI->isSubRegisterEq(Rn, Rt))
3508 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3509 "is also a source");
3510 break;
3511 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003512 case AArch64::STXRB:
3513 case AArch64::STXRH:
3514 case AArch64::STXRW:
3515 case AArch64::STXRX:
3516 case AArch64::STLXRB:
3517 case AArch64::STLXRH:
3518 case AArch64::STLXRW:
3519 case AArch64::STLXRX: {
3520 unsigned Rs = Inst.getOperand(0).getReg();
3521 unsigned Rt = Inst.getOperand(1).getReg();
3522 unsigned Rn = Inst.getOperand(2).getReg();
3523 if (RI->isSubRegisterEq(Rt, Rs) ||
3524 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3525 return Error(Loc[0],
3526 "unpredictable STXR instruction, status is also a source");
3527 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003528 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003529 case AArch64::STXPW:
3530 case AArch64::STXPX:
3531 case AArch64::STLXPW:
3532 case AArch64::STLXPX: {
3533 unsigned Rs = Inst.getOperand(0).getReg();
3534 unsigned Rt1 = Inst.getOperand(1).getReg();
3535 unsigned Rt2 = Inst.getOperand(2).getReg();
3536 unsigned Rn = Inst.getOperand(3).getReg();
3537 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3538 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3539 return Error(Loc[0],
3540 "unpredictable STXP instruction, status is also a source");
3541 break;
3542 }
3543 }
3544
Tim Northover3b0846e2014-05-24 12:50:23 +00003545
3546 // Now check immediate ranges. Separate from the above as there is overlap
3547 // in the instructions being checked and this keeps the nested conditionals
3548 // to a minimum.
3549 switch (Inst.getOpcode()) {
3550 case AArch64::ADDSWri:
3551 case AArch64::ADDSXri:
3552 case AArch64::ADDWri:
3553 case AArch64::ADDXri:
3554 case AArch64::SUBSWri:
3555 case AArch64::SUBSXri:
3556 case AArch64::SUBWri:
3557 case AArch64::SUBXri: {
3558 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3559 // some slight duplication here.
3560 if (Inst.getOperand(2).isExpr()) {
3561 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3562 AArch64MCExpr::VariantKind ELFRefKind;
3563 MCSymbolRefExpr::VariantKind DarwinRefKind;
3564 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003565 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3566
3567 // Only allow these with ADDXri.
3568 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3569 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3570 Inst.getOpcode() == AArch64::ADDXri)
3571 return false;
3572
3573 // Only allow these with ADDXri/ADDWri
3574 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3575 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3576 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3577 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3578 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3579 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3580 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003581 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3582 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3583 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003584 (Inst.getOpcode() == AArch64::ADDXri ||
3585 Inst.getOpcode() == AArch64::ADDWri))
3586 return false;
3587
3588 // Don't allow symbol refs in the immediate field otherwise
3589 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3590 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3591 // 'cmp w0, 'borked')
3592 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003593 }
Diana Picusc93518d2016-10-11 09:17:47 +00003594 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003595 }
3596 return false;
3597 }
3598 default:
3599 return false;
3600 }
3601}
3602
Craig Topper05515562017-10-26 06:46:41 +00003603static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3604 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003605
3606bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3607 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003608 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003609 case Match_InvalidTiedOperand:
3610 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003611 case Match_MissingFeature:
3612 return Error(Loc,
3613 "instruction requires a CPU feature not currently enabled");
3614 case Match_InvalidOperand:
3615 return Error(Loc, "invalid operand for instruction");
3616 case Match_InvalidSuffix:
3617 return Error(Loc, "invalid type suffix for instruction");
3618 case Match_InvalidCondCode:
3619 return Error(Loc, "expected AArch64 condition code");
3620 case Match_AddSubRegExtendSmall:
3621 return Error(Loc,
3622 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3623 case Match_AddSubRegExtendLarge:
3624 return Error(Loc,
3625 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3626 case Match_AddSubSecondSource:
3627 return Error(Loc,
3628 "expected compatible register, symbol or integer in range [0, 4095]");
3629 case Match_LogicalSecondSource:
3630 return Error(Loc, "expected compatible register or logical immediate");
3631 case Match_InvalidMovImm32Shift:
3632 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3633 case Match_InvalidMovImm64Shift:
3634 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3635 case Match_AddSubRegShift32:
3636 return Error(Loc,
3637 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3638 case Match_AddSubRegShift64:
3639 return Error(Loc,
3640 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3641 case Match_InvalidFPImm:
3642 return Error(Loc,
3643 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003644 case Match_InvalidMemoryIndexedSImm6:
3645 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003646 case Match_InvalidMemoryIndexedSImm5:
3647 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003648 case Match_InvalidMemoryIndexed1SImm4:
3649 return Error(Loc, "index must be an integer in range [-8, 7].");
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:
Tim Northover3b0846e2014-05-24 12:50:23 +00004165 case Match_InvalidMemoryIndexed4SImm7:
4166 case Match_InvalidMemoryIndexed8SImm7:
4167 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen5c625982018-04-13 12:56:14 +00004168 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004169 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004170 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004171 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004172 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004173 case Match_InvalidImm0_7:
4174 case Match_InvalidImm0_15:
4175 case Match_InvalidImm0_31:
4176 case Match_InvalidImm0_63:
4177 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004178 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004179 case Match_InvalidImm0_65535:
4180 case Match_InvalidImm1_8:
4181 case Match_InvalidImm1_16:
4182 case Match_InvalidImm1_32:
4183 case Match_InvalidImm1_64:
4184 case Match_InvalidIndex1:
4185 case Match_InvalidIndexB:
4186 case Match_InvalidIndexH:
4187 case Match_InvalidIndexS:
4188 case Match_InvalidIndexD:
4189 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004190 case Match_InvalidComplexRotationEven:
4191 case Match_InvalidComplexRotationOdd:
Sander de Smalencd6be962017-12-20 11:02:42 +00004192 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004193 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004194 case Match_InvalidSVEPredicateBReg:
4195 case Match_InvalidSVEPredicateHReg:
4196 case Match_InvalidSVEPredicateSReg:
4197 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004198 case Match_InvalidSVEPredicate3bAnyReg:
4199 case Match_InvalidSVEPredicate3bBReg:
4200 case Match_InvalidSVEPredicate3bHReg:
4201 case Match_InvalidSVEPredicate3bSReg:
4202 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004203 case Match_MSR:
4204 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004205 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004206 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004207 // Any time we get here, there's nothing fancy to do. Just get the
4208 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004209 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004210 if (ErrorLoc == SMLoc())
4211 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004212 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004213 }
4214 }
4215
4216 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004217}
4218
4219/// ParseDirective parses the arm specific directives
4220bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004221 const MCObjectFileInfo::Environment Format =
4222 getContext().getObjectFileInfo()->getObjectFileType();
4223 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4224 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004225
Tim Northover3b0846e2014-05-24 12:50:23 +00004226 StringRef IDVal = DirectiveID.getIdentifier();
4227 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004228 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004229 parseDirectiveArch(Loc);
4230 else if (IDVal == ".cpu")
4231 parseDirectiveCPU(Loc);
4232 else if (IDVal == ".hword")
4233 parseDirectiveWord(2, Loc);
4234 else if (IDVal == ".word")
4235 parseDirectiveWord(4, Loc);
4236 else if (IDVal == ".xword")
4237 parseDirectiveWord(8, Loc);
4238 else if (IDVal == ".tlsdesccall")
4239 parseDirectiveTLSDescCall(Loc);
4240 else if (IDVal == ".ltorg" || IDVal == ".pool")
4241 parseDirectiveLtorg(Loc);
4242 else if (IDVal == ".unreq")
4243 parseDirectiveUnreq(Loc);
4244 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004245 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004246 parseDirectiveInst(Loc);
4247 else
4248 return true;
4249 } else if (IDVal == MCLOHDirectiveName())
4250 parseDirectiveLOH(IDVal, Loc);
4251 else
4252 return true;
4253 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004254}
4255
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004256static const struct {
4257 const char *Name;
4258 const FeatureBitset Features;
4259} ExtensionMap[] = {
4260 { "crc", {AArch64::FeatureCRC} },
4261 { "crypto", {AArch64::FeatureCrypto} },
4262 { "fp", {AArch64::FeatureFPARMv8} },
4263 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004264 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004265 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004266
4267 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004268 { "pan", {} },
4269 { "lor", {} },
4270 { "rdma", {} },
4271 { "profile", {} },
4272};
4273
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004274/// parseDirectiveArch
4275/// ::= .arch token
4276bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4277 SMLoc ArchLoc = getLoc();
4278
4279 StringRef Arch, ExtensionString;
4280 std::tie(Arch, ExtensionString) =
4281 getParser().parseStringToEndOfStatement().trim().split('+');
4282
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004283 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4284 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004285 return Error(ArchLoc, "unknown arch name");
4286
4287 if (parseToken(AsmToken::EndOfStatement))
4288 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004289
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004290 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004291 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004292 AArch64::getArchFeatures(ID, AArch64Features);
4293 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4294 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004295
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004296 MCSubtargetInfo &STI = copySTI();
4297 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4298 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4299
4300 SmallVector<StringRef, 4> RequestedExtensions;
4301 if (!ExtensionString.empty())
4302 ExtensionString.split(RequestedExtensions, '+');
4303
4304 FeatureBitset Features = STI.getFeatureBits();
4305 for (auto Name : RequestedExtensions) {
4306 bool EnableFeature = true;
4307
4308 if (Name.startswith_lower("no")) {
4309 EnableFeature = false;
4310 Name = Name.substr(2);
4311 }
4312
4313 for (const auto &Extension : ExtensionMap) {
4314 if (Extension.Name != Name)
4315 continue;
4316
4317 if (Extension.Features.none())
4318 report_fatal_error("unsupported architectural extension: " + Name);
4319
4320 FeatureBitset ToggleFeatures = EnableFeature
4321 ? (~Features & Extension.Features)
4322 : ( Features & Extension.Features);
4323 uint64_t Features =
4324 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4325 setAvailableFeatures(Features);
4326 break;
4327 }
4328 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004329 return false;
4330}
4331
Tim Northover8b96c7e2017-05-15 19:42:15 +00004332static SMLoc incrementLoc(SMLoc L, int Offset) {
4333 return SMLoc::getFromPointer(L.getPointer() + Offset);
4334}
4335
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004336/// parseDirectiveCPU
4337/// ::= .cpu id
4338bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004339 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004340
4341 StringRef CPU, ExtensionString;
4342 std::tie(CPU, ExtensionString) =
4343 getParser().parseStringToEndOfStatement().trim().split('+');
4344
Nirav Davee833c6c2016-11-08 18:31:04 +00004345 if (parseToken(AsmToken::EndOfStatement))
4346 return true;
4347
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004348 SmallVector<StringRef, 4> RequestedExtensions;
4349 if (!ExtensionString.empty())
4350 ExtensionString.split(RequestedExtensions, '+');
4351
4352 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4353 // once that is tablegen'ed
4354 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004355 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004356 return false;
4357 }
4358
4359 MCSubtargetInfo &STI = copySTI();
4360 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004361 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004362
4363 FeatureBitset Features = STI.getFeatureBits();
4364 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004365 // Advance source location past '+'.
4366 CurLoc = incrementLoc(CurLoc, 1);
4367
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004368 bool EnableFeature = true;
4369
4370 if (Name.startswith_lower("no")) {
4371 EnableFeature = false;
4372 Name = Name.substr(2);
4373 }
4374
Tim Northover8b96c7e2017-05-15 19:42:15 +00004375 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004376 for (const auto &Extension : ExtensionMap) {
4377 if (Extension.Name != Name)
4378 continue;
4379
4380 if (Extension.Features.none())
4381 report_fatal_error("unsupported architectural extension: " + Name);
4382
4383 FeatureBitset ToggleFeatures = EnableFeature
4384 ? (~Features & Extension.Features)
4385 : ( Features & Extension.Features);
4386 uint64_t Features =
4387 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4388 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004389 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004390
4391 break;
4392 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004393
4394 if (!FoundExtension)
4395 Error(CurLoc, "unsupported architectural extension");
4396
4397 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004398 }
4399 return false;
4400}
4401
Tim Northover3b0846e2014-05-24 12:50:23 +00004402/// parseDirectiveWord
4403/// ::= .word [ expression (, expression)* ]
4404bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004405 auto parseOp = [&]() -> bool {
4406 const MCExpr *Value;
4407 if (getParser().parseExpression(Value))
4408 return true;
4409 getParser().getStreamer().EmitValue(Value, Size, L);
4410 return false;
4411 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004412
Nirav Davee833c6c2016-11-08 18:31:04 +00004413 if (parseMany(parseOp))
4414 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004415 return false;
4416}
4417
Chad Rosierdcd2a302014-10-22 20:35:57 +00004418/// parseDirectiveInst
4419/// ::= .inst opcode [, ...]
4420bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004421 if (getLexer().is(AsmToken::EndOfStatement))
4422 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004423
Nirav Davee833c6c2016-11-08 18:31:04 +00004424 auto parseOp = [&]() -> bool {
4425 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004426 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004427 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4428 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004429 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004430 if (check(!Value, L, "expected constant expression"))
4431 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004432 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004433 return false;
4434 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004435
Nirav Davee833c6c2016-11-08 18:31:04 +00004436 if (parseMany(parseOp))
4437 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004438 return false;
4439}
4440
Tim Northover3b0846e2014-05-24 12:50:23 +00004441// parseDirectiveTLSDescCall:
4442// ::= .tlsdesccall symbol
4443bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4444 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004445 if (check(getParser().parseIdentifier(Name), L,
4446 "expected symbol after directive") ||
4447 parseToken(AsmToken::EndOfStatement))
4448 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004449
Jim Grosbach6f482002015-05-18 18:43:14 +00004450 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004451 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4452 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004453
4454 MCInst Inst;
4455 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004456 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004457
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004458 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004459 return false;
4460}
4461
4462/// ::= .loh <lohName | lohId> label1, ..., labelN
4463/// The number of arguments depends on the loh identifier.
4464bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004465 MCLOHType Kind;
4466 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4467 if (getParser().getTok().isNot(AsmToken::Integer))
4468 return TokError("expected an identifier or a number in directive");
4469 // We successfully get a numeric value for the identifier.
4470 // Check if it is valid.
4471 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004472 if (Id <= -1U && !isValidMCLOHType(Id))
4473 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004474 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004475 } else {
4476 StringRef Name = getTok().getIdentifier();
4477 // We successfully parse an identifier.
4478 // Check if it is a recognized one.
4479 int Id = MCLOHNameToId(Name);
4480
4481 if (Id == -1)
4482 return TokError("invalid identifier in directive");
4483 Kind = (MCLOHType)Id;
4484 }
4485 // Consume the identifier.
4486 Lex();
4487 // Get the number of arguments of this LOH.
4488 int NbArgs = MCLOHIdToNbArgs(Kind);
4489
4490 assert(NbArgs != -1 && "Invalid number of arguments");
4491
4492 SmallVector<MCSymbol *, 3> Args;
4493 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4494 StringRef Name;
4495 if (getParser().parseIdentifier(Name))
4496 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004497 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004498
4499 if (Idx + 1 == NbArgs)
4500 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004501 if (parseToken(AsmToken::Comma,
4502 "unexpected token in '" + Twine(IDVal) + "' directive"))
4503 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004504 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004505 if (parseToken(AsmToken::EndOfStatement,
4506 "unexpected token in '" + Twine(IDVal) + "' directive"))
4507 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004508
4509 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4510 return false;
4511}
4512
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004513/// parseDirectiveLtorg
4514/// ::= .ltorg | .pool
4515bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004516 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4517 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004518 getTargetStreamer().emitCurrentConstantPool();
4519 return false;
4520}
4521
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004522/// parseDirectiveReq
4523/// ::= name .req registername
4524bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004525 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004526 Parser.Lex(); // Eat the '.req' token.
4527 SMLoc SRegLoc = getLoc();
Sander de Smalen8e607342017-11-15 15:44:43 +00004528 int RegNum = tryParseRegister();
Florian Hahnc4422242017-11-07 13:07:50 +00004529 RegKind RegisterKind = RegKind::Scalar;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004530
Sander de Smalen8e607342017-11-15 15:44:43 +00004531 if (RegNum == -1) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004532 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004533 RegisterKind = RegKind::NeonVector;
Sander de Smalen73937b72018-04-11 07:36:10 +00004534 OperandMatchResultTy Res =
4535 tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
4536
4537 if (Res == MatchOperand_ParseFail)
4538 return true;
4539
4540 if (Res == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004541 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004542 }
4543
Sander de Smalen8e607342017-11-15 15:44:43 +00004544 if (RegNum == -1) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004545 StringRef Kind;
4546 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen8e607342017-11-15 15:44:43 +00004547 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004548 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004549
4550 if (Res == MatchOperand_ParseFail)
4551 return true;
4552
4553 if (Res == MatchOperand_Success && !Kind.empty())
4554 return Error(SRegLoc,
4555 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004556 }
4557
Sander de Smalencd6be962017-12-20 11:02:42 +00004558 if (RegNum == -1) {
4559 StringRef Kind;
4560 RegisterKind = RegKind::SVEPredicateVector;
4561 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004562 tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004563
4564 if (Res == MatchOperand_ParseFail)
4565 return true;
4566
4567 if (Res == MatchOperand_Success && !Kind.empty())
4568 return Error(SRegLoc,
4569 "sve predicate register without type specifier expected");
4570 }
4571
Sander de Smalen8e607342017-11-15 15:44:43 +00004572 if (RegNum == -1)
Nirav Dave2364748a2016-09-16 18:30:20 +00004573 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004574
4575 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004576 if (parseToken(AsmToken::EndOfStatement,
4577 "unexpected input in .req directive"))
4578 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004579
Sander de Smalen8e607342017-11-15 15:44:43 +00004580 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004581 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004582 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4583
Nirav Dave2364748a2016-09-16 18:30:20 +00004584 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004585}
4586
4587/// parseDirectiveUneq
4588/// ::= .unreq registername
4589bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004590 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004591 if (getTok().isNot(AsmToken::Identifier))
4592 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004593 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4594 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004595 if (parseToken(AsmToken::EndOfStatement))
4596 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004597 return false;
4598}
4599
Tim Northover3b0846e2014-05-24 12:50:23 +00004600bool
4601AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4602 AArch64MCExpr::VariantKind &ELFRefKind,
4603 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4604 int64_t &Addend) {
4605 ELFRefKind = AArch64MCExpr::VK_INVALID;
4606 DarwinRefKind = MCSymbolRefExpr::VK_None;
4607 Addend = 0;
4608
4609 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4610 ELFRefKind = AE->getKind();
4611 Expr = AE->getSubExpr();
4612 }
4613
4614 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4615 if (SE) {
4616 // It's a simple symbol reference with no addend.
4617 DarwinRefKind = SE->getKind();
4618 return true;
4619 }
4620
4621 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4622 if (!BE)
4623 return false;
4624
4625 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4626 if (!SE)
4627 return false;
4628 DarwinRefKind = SE->getKind();
4629
4630 if (BE->getOpcode() != MCBinaryExpr::Add &&
4631 BE->getOpcode() != MCBinaryExpr::Sub)
4632 return false;
4633
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004634 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004635 // on here than we can deal with.
4636 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4637 if (!AddendExpr)
4638 return false;
4639
4640 Addend = AddendExpr->getValue();
4641 if (BE->getOpcode() == MCBinaryExpr::Sub)
4642 Addend = -Addend;
4643
4644 // It's some symbol reference + a constant addend, but really
4645 // shouldn't use both Darwin and ELF syntax.
4646 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4647 DarwinRefKind == MCSymbolRefExpr::VK_None;
4648}
4649
4650/// Force static initialization.
4651extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004652 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4653 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4654 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004655}
4656
4657#define GET_REGISTER_MATCHER
4658#define GET_SUBTARGET_FEATURE_NAME
4659#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004660#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004661#include "AArch64GenAsmMatcher.inc"
4662
4663// Define this matcher function after the auto-generated include so we
4664// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004665unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004666 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004667 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004668 // If the kind is a token for a literal immediate, check if our asm
4669 // operand matches. This is for InstAliases which have a fixed-value
4670 // immediate in the syntax.
4671 int64_t ExpectedVal;
4672 switch (Kind) {
4673 default:
4674 return Match_InvalidOperand;
4675 case MCK__35_0:
4676 ExpectedVal = 0;
4677 break;
4678 case MCK__35_1:
4679 ExpectedVal = 1;
4680 break;
4681 case MCK__35_12:
4682 ExpectedVal = 12;
4683 break;
4684 case MCK__35_16:
4685 ExpectedVal = 16;
4686 break;
4687 case MCK__35_2:
4688 ExpectedVal = 2;
4689 break;
4690 case MCK__35_24:
4691 ExpectedVal = 24;
4692 break;
4693 case MCK__35_3:
4694 ExpectedVal = 3;
4695 break;
4696 case MCK__35_32:
4697 ExpectedVal = 32;
4698 break;
4699 case MCK__35_4:
4700 ExpectedVal = 4;
4701 break;
4702 case MCK__35_48:
4703 ExpectedVal = 48;
4704 break;
4705 case MCK__35_6:
4706 ExpectedVal = 6;
4707 break;
4708 case MCK__35_64:
4709 ExpectedVal = 64;
4710 break;
4711 case MCK__35_8:
4712 ExpectedVal = 8;
4713 break;
4714 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004715 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004716 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004717 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004718 if (!CE)
4719 return Match_InvalidOperand;
4720 if (CE->getValue() == ExpectedVal)
4721 return Match_Success;
4722 return Match_InvalidOperand;
4723}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004724
Alex Bradbury58eba092016-11-01 16:32:05 +00004725OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004726AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4727
4728 SMLoc S = getLoc();
4729
4730 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4731 Error(S, "expected register");
4732 return MatchOperand_ParseFail;
4733 }
4734
4735 int FirstReg = tryParseRegister();
4736 if (FirstReg == -1) {
4737 return MatchOperand_ParseFail;
4738 }
4739 const MCRegisterClass &WRegClass =
4740 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4741 const MCRegisterClass &XRegClass =
4742 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4743
4744 bool isXReg = XRegClass.contains(FirstReg),
4745 isWReg = WRegClass.contains(FirstReg);
4746 if (!isXReg && !isWReg) {
4747 Error(S, "expected first even register of a "
4748 "consecutive same-size even/odd register pair");
4749 return MatchOperand_ParseFail;
4750 }
4751
4752 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4753 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4754
4755 if (FirstEncoding & 0x1) {
4756 Error(S, "expected first even register of a "
4757 "consecutive same-size even/odd register pair");
4758 return MatchOperand_ParseFail;
4759 }
4760
4761 SMLoc M = getLoc();
4762 if (getParser().getTok().isNot(AsmToken::Comma)) {
4763 Error(M, "expected comma");
4764 return MatchOperand_ParseFail;
4765 }
4766 // Eat the comma
4767 getParser().Lex();
4768
4769 SMLoc E = getLoc();
4770 int SecondReg = tryParseRegister();
4771 if (SecondReg ==-1) {
4772 return MatchOperand_ParseFail;
4773 }
4774
Eugene Zelenko049b0172017-01-06 00:30:53 +00004775 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004776 (isXReg && !XRegClass.contains(SecondReg)) ||
4777 (isWReg && !WRegClass.contains(SecondReg))) {
4778 Error(E,"expected second odd register of a "
4779 "consecutive same-size even/odd register pair");
4780 return MatchOperand_ParseFail;
4781 }
Joel Jones504bf332016-10-24 13:37:13 +00004782
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004783 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004784 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004785 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4786 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4787 } else {
4788 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4789 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4790 }
4791
Florian Hahnc4422242017-11-07 13:07:50 +00004792 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4793 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004794
4795 return MatchOperand_Success;
4796}
Florian Hahn91f11e52017-11-07 16:45:48 +00004797
4798template <bool ParseSuffix>
4799OperandMatchResultTy
4800AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004801 const SMLoc S = getLoc();
4802 // Check for a SVE vector register specifier first.
Sander de Smalen8e607342017-11-15 15:44:43 +00004803 int RegNum = -1;
Florian Hahn91f11e52017-11-07 16:45:48 +00004804 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004805
Sander de Smalen8e607342017-11-15 15:44:43 +00004806 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004807 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004808
4809 if (Res != MatchOperand_Success)
4810 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004811
4812 if (ParseSuffix && Kind.empty())
4813 return MatchOperand_NoMatch;
4814
Sander de Smalen73937b72018-04-11 07:36:10 +00004815 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
4816 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00004817 return MatchOperand_NoMatch;
4818
Sander de Smalen73937b72018-04-11 07:36:10 +00004819 unsigned ElementWidth = KindRes->second;
4820 Operands.push_back(AArch64Operand::CreateVectorReg(
4821 RegNum, RegKind::SVEDataVector, ElementWidth, S, S,
4822 getContext()));
Florian Hahn91f11e52017-11-07 16:45:48 +00004823
4824 return MatchOperand_Success;
4825}
Sander de Smalen245e0e62018-01-22 10:46:00 +00004826
4827OperandMatchResultTy
4828AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
4829 MCAsmParser &Parser = getParser();
4830
4831 SMLoc SS = getLoc();
4832 const AsmToken &TokE = Parser.getTok();
4833 bool IsHash = TokE.is(AsmToken::Hash);
4834
4835 if (!IsHash && TokE.isNot(AsmToken::Identifier))
4836 return MatchOperand_NoMatch;
4837
4838 int64_t Pattern;
4839 if (IsHash) {
4840 Parser.Lex(); // Eat hash
4841
4842 // Parse the immediate operand.
4843 const MCExpr *ImmVal;
4844 SS = getLoc();
4845 if (Parser.parseExpression(ImmVal))
4846 return MatchOperand_ParseFail;
4847
4848 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4849 if (!MCE)
4850 return MatchOperand_ParseFail;
4851
4852 Pattern = MCE->getValue();
4853 } else {
4854 // Parse the pattern
4855 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
4856 if (!Pat)
4857 return MatchOperand_NoMatch;
4858
4859 Parser.Lex();
4860 Pattern = Pat->Encoding;
4861 assert(Pattern >= 0 && Pattern < 32);
4862 }
4863
4864 Operands.push_back(
4865 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
4866 SS, getLoc(), getContext()));
4867
4868 return MatchOperand_Success;
4869}