blob: b5d819a3b9977686790bc37f97262dab32c3dada [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/AArch64AddressingModes.h"
11#include "MCTargetDesc/AArch64MCExpr.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000012#include "MCTargetDesc/AArch64MCTargetDesc.h"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000013#include "MCTargetDesc/AArch64TargetStreamer.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000014#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000015#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000016#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000017#include "llvm/ADT/ArrayRef.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000018#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "llvm/ADT/SmallVector.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000020#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000021#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000023#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000025#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000028#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000029#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000030#include "llvm/MC/MCParser/MCAsmLexer.h"
31#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000032#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000033#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000034#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000035#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSubtargetInfo.h"
38#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000039#include "llvm/MC/MCTargetOptions.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000043#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000044#include "llvm/Support/MathExtras.h"
45#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000046#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000047#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000049#include <cassert>
50#include <cctype>
51#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000052#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000053#include <string>
54#include <tuple>
55#include <utility>
56#include <vector>
57
Tim Northover3b0846e2014-05-24 12:50:23 +000058using namespace llvm;
59
60namespace {
61
Sander de Smalencd6be962017-12-20 11:02:42 +000062enum class RegKind {
63 Scalar,
64 NeonVector,
65 SVEDataVector,
66 SVEPredicateVector
67};
Florian Hahnc4422242017-11-07 13:07:50 +000068
Tim Northover3b0846e2014-05-24 12:50:23 +000069class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000070private:
71 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000072
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000073 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000074 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000075
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000076 AArch64TargetStreamer &getTargetStreamer() {
77 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
78 return static_cast<AArch64TargetStreamer &>(TS);
79 }
80
Rafael Espindola961d4692014-11-11 05:18:41 +000081 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000082
83 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +000084 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +000085 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
86 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +000087 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +000088 bool parseRegister(OperandVector &Operands);
89 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
Sander de Smalenc88f9a12018-04-11 14:10:37 +000090 bool parseNeonVectorList(OperandVector &Operands);
Sander de Smalen5c625982018-04-13 12:56:14 +000091 bool parseOptionalMulVl(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000092 bool parseOperand(OperandVector &Operands, bool isCondCode,
93 bool invertCondCode);
94
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +000095 bool showMatchError(SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000096
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000097 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000098 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +000099 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +0000100 bool parseDirectiveInst(SMLoc L);
101
Tim Northover3b0846e2014-05-24 12:50:23 +0000102 bool parseDirectiveTLSDescCall(SMLoc L);
103
104 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000105 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000106
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000107 bool parseDirectiveReq(StringRef Name, SMLoc L);
108 bool parseDirectiveUnreq(SMLoc L);
109
Tim Northover3b0846e2014-05-24 12:50:23 +0000110 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
111 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
112 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000113 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000114 bool MatchingInlineAsm) override;
115/// @name Auto-generated Match Functions
116/// {
117
118#define GET_ASSEMBLER_HEADER
119#include "AArch64GenAsmMatcher.inc"
120
121 /// }
122
Sander de Smalen50d87022018-04-19 07:35:08 +0000123 OperandMatchResultTy tryParseScalarRegister(unsigned &Reg);
124 OperandMatchResultTy tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +0000125 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000126 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
127 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
128 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
129 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
130 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
131 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000132 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000133 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
134 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
135 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
136 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
137 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000138 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000139 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000140 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Sander de Smalen149916d2018-04-20 07:24:20 +0000141 template <bool ParseShiftExtend>
142 OperandMatchResultTy tryParseGPROperand(OperandVector &Operands);
Florian Hahn91f11e52017-11-07 16:45:48 +0000143 template <bool ParseSuffix>
144 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000145 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000146 template <RegKind VectorKind>
147 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
148 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000149 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000150
151public:
152 enum AArch64MatchResultTy {
153 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
154#define GET_OPERAND_DIAGNOSTIC_TYPES
155#include "AArch64GenAsmMatcher.inc"
156 };
Joel Jones504bf332016-10-24 13:37:13 +0000157 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000158
Akira Hatanakab11ef082015-11-14 06:35:56 +0000159 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000160 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000161 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000162 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000163 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000164 MCStreamer &S = getParser().getStreamer();
165 if (S.getTargetStreamer() == nullptr)
166 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000167
168 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000169 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000170 }
171
172 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
173 SMLoc NameLoc, OperandVector &Operands) override;
174 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
175 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000176 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000177 unsigned Kind) override;
178
179 static bool classifySymbolRef(const MCExpr *Expr,
180 AArch64MCExpr::VariantKind &ELFRefKind,
181 MCSymbolRefExpr::VariantKind &DarwinRefKind,
182 int64_t &Addend);
183};
Tim Northover3b0846e2014-05-24 12:50:23 +0000184
185/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
186/// instruction.
187class AArch64Operand : public MCParsedAsmOperand {
188private:
189 enum KindTy {
190 k_Immediate,
191 k_ShiftedImm,
192 k_CondCode,
193 k_Register,
194 k_VectorList,
195 k_VectorIndex,
196 k_Token,
197 k_SysReg,
198 k_SysCR,
199 k_Prefetch,
200 k_ShiftExtend,
201 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000202 k_Barrier,
203 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000204 } Kind;
205
206 SMLoc StartLoc, EndLoc;
207
208 struct TokOp {
209 const char *Data;
210 unsigned Length;
211 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
212 };
213
Sander de Smalen149916d2018-04-20 07:24:20 +0000214 // Separate shift/extend operand.
215 struct ShiftExtendOp {
216 AArch64_AM::ShiftExtendType Type;
217 unsigned Amount;
218 bool HasExplicitAmount;
219 };
220
Tim Northover3b0846e2014-05-24 12:50:23 +0000221 struct RegOp {
222 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000223 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000224 int ElementWidth;
Sander de Smalen149916d2018-04-20 07:24:20 +0000225
226 // In some cases the shift/extend needs to be explicitly parsed together
227 // with the register, rather than as a separate operand. This is needed
228 // for addressing modes where the instruction as a whole dictates the
229 // scaling/extend, rather than specific bits in the instruction.
230 // By parsing them as a single operand, we avoid the need to pass an
231 // extra operand in all CodeGen patterns (because all operands need to
232 // have an associated value), and we avoid the need to update TableGen to
233 // accept operands that have no associated bits in the instruction.
234 //
235 // An added benefit of parsing them together is that the assembler
236 // can give a sensible diagnostic if the scaling is not correct.
237 //
238 // The default is 'lsl #0' (HasExplicitAmount = false) if no
239 // ShiftExtend is specified.
240 ShiftExtendOp ShiftExtend;
Tim Northover3b0846e2014-05-24 12:50:23 +0000241 };
242
243 struct VectorListOp {
244 unsigned RegNum;
245 unsigned Count;
246 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000247 unsigned ElementWidth;
248 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000249 };
250
251 struct VectorIndexOp {
252 unsigned Val;
253 };
254
255 struct ImmOp {
256 const MCExpr *Val;
257 };
258
259 struct ShiftedImmOp {
260 const MCExpr *Val;
261 unsigned ShiftAmount;
262 };
263
264 struct CondCodeOp {
265 AArch64CC::CondCode Code;
266 };
267
268 struct FPImmOp {
269 unsigned Val; // Encoded 8-bit representation.
270 };
271
272 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000273 const char *Data;
274 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000275 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000276 };
277
278 struct SysRegOp {
279 const char *Data;
280 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000281 uint32_t MRSReg;
282 uint32_t MSRReg;
283 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000284 };
285
286 struct SysCRImmOp {
287 unsigned Val;
288 };
289
290 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000291 const char *Data;
292 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000293 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000294 };
295
Oliver Stannarda34e4702015-12-01 10:48:51 +0000296 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000297 const char *Data;
298 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000299 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000300 };
301
Tim Northover3b0846e2014-05-24 12:50:23 +0000302 struct ExtendOp {
303 unsigned Val;
304 };
305
306 union {
307 struct TokOp Tok;
308 struct RegOp Reg;
309 struct VectorListOp VectorList;
310 struct VectorIndexOp VectorIndex;
311 struct ImmOp Imm;
312 struct ShiftedImmOp ShiftedImm;
313 struct CondCodeOp CondCode;
314 struct FPImmOp FPImm;
315 struct BarrierOp Barrier;
316 struct SysRegOp SysReg;
317 struct SysCRImmOp SysCRImm;
318 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000319 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000320 struct ShiftExtendOp ShiftExtend;
321 };
322
323 // Keep the MCContext around as the MCExprs may need manipulated during
324 // the add<>Operands() calls.
325 MCContext &Ctx;
326
David Blaikie960ea3f2014-06-08 16:18:35 +0000327public:
David Blaikie9f380a32015-03-16 18:06:57 +0000328 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000329
Tim Northover3b0846e2014-05-24 12:50:23 +0000330 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
331 Kind = o.Kind;
332 StartLoc = o.StartLoc;
333 EndLoc = o.EndLoc;
334 switch (Kind) {
335 case k_Token:
336 Tok = o.Tok;
337 break;
338 case k_Immediate:
339 Imm = o.Imm;
340 break;
341 case k_ShiftedImm:
342 ShiftedImm = o.ShiftedImm;
343 break;
344 case k_CondCode:
345 CondCode = o.CondCode;
346 break;
347 case k_FPImm:
348 FPImm = o.FPImm;
349 break;
350 case k_Barrier:
351 Barrier = o.Barrier;
352 break;
353 case k_Register:
354 Reg = o.Reg;
355 break;
356 case k_VectorList:
357 VectorList = o.VectorList;
358 break;
359 case k_VectorIndex:
360 VectorIndex = o.VectorIndex;
361 break;
362 case k_SysReg:
363 SysReg = o.SysReg;
364 break;
365 case k_SysCR:
366 SysCRImm = o.SysCRImm;
367 break;
368 case k_Prefetch:
369 Prefetch = o.Prefetch;
370 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000371 case k_PSBHint:
372 PSBHint = o.PSBHint;
373 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000374 case k_ShiftExtend:
375 ShiftExtend = o.ShiftExtend;
376 break;
377 }
378 }
379
380 /// getStartLoc - Get the location of the first token of this operand.
381 SMLoc getStartLoc() const override { return StartLoc; }
382 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000383 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000384
385 StringRef getToken() const {
386 assert(Kind == k_Token && "Invalid access!");
387 return StringRef(Tok.Data, Tok.Length);
388 }
389
390 bool isTokenSuffix() const {
391 assert(Kind == k_Token && "Invalid access!");
392 return Tok.IsSuffix;
393 }
394
395 const MCExpr *getImm() const {
396 assert(Kind == k_Immediate && "Invalid access!");
397 return Imm.Val;
398 }
399
400 const MCExpr *getShiftedImmVal() const {
401 assert(Kind == k_ShiftedImm && "Invalid access!");
402 return ShiftedImm.Val;
403 }
404
405 unsigned getShiftedImmShift() const {
406 assert(Kind == k_ShiftedImm && "Invalid access!");
407 return ShiftedImm.ShiftAmount;
408 }
409
410 AArch64CC::CondCode getCondCode() const {
411 assert(Kind == k_CondCode && "Invalid access!");
412 return CondCode.Code;
413 }
414
415 unsigned getFPImm() const {
416 assert(Kind == k_FPImm && "Invalid access!");
417 return FPImm.Val;
418 }
419
420 unsigned getBarrier() const {
421 assert(Kind == k_Barrier && "Invalid access!");
422 return Barrier.Val;
423 }
424
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000425 StringRef getBarrierName() const {
426 assert(Kind == k_Barrier && "Invalid access!");
427 return StringRef(Barrier.Data, Barrier.Length);
428 }
429
Tim Northover3b0846e2014-05-24 12:50:23 +0000430 unsigned getReg() const override {
431 assert(Kind == k_Register && "Invalid access!");
432 return Reg.RegNum;
433 }
434
435 unsigned getVectorListStart() const {
436 assert(Kind == k_VectorList && "Invalid access!");
437 return VectorList.RegNum;
438 }
439
440 unsigned getVectorListCount() const {
441 assert(Kind == k_VectorList && "Invalid access!");
442 return VectorList.Count;
443 }
444
445 unsigned getVectorIndex() const {
446 assert(Kind == k_VectorIndex && "Invalid access!");
447 return VectorIndex.Val;
448 }
449
450 StringRef getSysReg() const {
451 assert(Kind == k_SysReg && "Invalid access!");
452 return StringRef(SysReg.Data, SysReg.Length);
453 }
454
Tim Northover3b0846e2014-05-24 12:50:23 +0000455 unsigned getSysCR() const {
456 assert(Kind == k_SysCR && "Invalid access!");
457 return SysCRImm.Val;
458 }
459
460 unsigned getPrefetch() const {
461 assert(Kind == k_Prefetch && "Invalid access!");
462 return Prefetch.Val;
463 }
464
Oliver Stannarda34e4702015-12-01 10:48:51 +0000465 unsigned getPSBHint() const {
466 assert(Kind == k_PSBHint && "Invalid access!");
467 return PSBHint.Val;
468 }
469
470 StringRef getPSBHintName() const {
471 assert(Kind == k_PSBHint && "Invalid access!");
472 return StringRef(PSBHint.Data, PSBHint.Length);
473 }
474
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000475 StringRef getPrefetchName() const {
476 assert(Kind == k_Prefetch && "Invalid access!");
477 return StringRef(Prefetch.Data, Prefetch.Length);
478 }
479
Tim Northover3b0846e2014-05-24 12:50:23 +0000480 AArch64_AM::ShiftExtendType getShiftExtendType() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000481 if (Kind == k_ShiftExtend)
482 return ShiftExtend.Type;
483 if (Kind == k_Register)
484 return Reg.ShiftExtend.Type;
485 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000486 }
487
488 unsigned getShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000489 if (Kind == k_ShiftExtend)
490 return ShiftExtend.Amount;
491 if (Kind == k_Register)
492 return Reg.ShiftExtend.Amount;
493 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000494 }
495
496 bool hasShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000497 if (Kind == k_ShiftExtend)
498 return ShiftExtend.HasExplicitAmount;
499 if (Kind == k_Register)
500 return Reg.ShiftExtend.HasExplicitAmount;
501 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000502 }
503
504 bool isImm() const override { return Kind == k_Immediate; }
505 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000506
507 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
508
509 template <int Bits, int Scale> bool isSImmScaled() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000510 if (!isImm())
511 return false;
512 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
513 if (!MCE)
514 return false;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000515
516 int64_t Shift = Bits - 1;
517 int64_t MinVal = (int64_t(1) << Shift) * -Scale;
518 int64_t MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
519
Tim Northover3b0846e2014-05-24 12:50:23 +0000520 int64_t Val = MCE->getValue();
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000521 return Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0;
Tim Northover3b0846e2014-05-24 12:50:23 +0000522 }
523
Sander de Smalen245e0e62018-01-22 10:46:00 +0000524 bool isSVEPattern() const {
525 if (!isImm())
526 return false;
527 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
528 if (!MCE)
529 return false;
530 int64_t Val = MCE->getValue();
531 return Val >= 0 && Val < 32;
532 }
533
Tim Northover3b0846e2014-05-24 12:50:23 +0000534 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
535 AArch64MCExpr::VariantKind ELFRefKind;
536 MCSymbolRefExpr::VariantKind DarwinRefKind;
537 int64_t Addend;
538 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
539 Addend)) {
540 // If we don't understand the expression, assume the best and
541 // let the fixup and relocation code deal with it.
542 return true;
543 }
544
545 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
546 ELFRefKind == AArch64MCExpr::VK_LO12 ||
547 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
548 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
549 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
550 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
551 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
552 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000553 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
554 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
555 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000556 // Note that we don't range-check the addend. It's adjusted modulo page
557 // size when converted, so there is no "out of range" condition when using
558 // @pageoff.
559 return Addend >= 0 && (Addend % Scale) == 0;
560 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
561 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
562 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
563 return Addend == 0;
564 }
565
566 return false;
567 }
568
569 template <int Scale> bool isUImm12Offset() const {
570 if (!isImm())
571 return false;
572
573 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
574 if (!MCE)
575 return isSymbolicUImm12Offset(getImm(), Scale);
576
577 int64_t Val = MCE->getValue();
578 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
579 }
580
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000581 template <int N, int M>
582 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000583 if (!isImm())
584 return false;
585 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
586 if (!MCE)
587 return false;
588 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000589 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000590 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000591
Sander de Smalena1c259c2018-01-29 13:05:38 +0000592 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
593 // a logical immediate can always be represented when inverted.
594 template <typename T>
595 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000596 if (!isImm())
597 return false;
598 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
599 if (!MCE)
600 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000601
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000602 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000603 int64_t SVal = typename std::make_signed<T>::type(Val);
604 int64_t UVal = typename std::make_unsigned<T>::type(Val);
605 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000606 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000607
Sander de Smalena1c259c2018-01-29 13:05:38 +0000608 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000609 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000610
Tim Northover3b0846e2014-05-24 12:50:23 +0000611 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000612
Tim Northover3b0846e2014-05-24 12:50:23 +0000613 bool isAddSubImm() const {
614 if (!isShiftedImm() && !isImm())
615 return false;
616
617 const MCExpr *Expr;
618
619 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
620 if (isShiftedImm()) {
621 unsigned Shift = ShiftedImm.ShiftAmount;
622 Expr = ShiftedImm.Val;
623 if (Shift != 0 && Shift != 12)
624 return false;
625 } else {
626 Expr = getImm();
627 }
628
629 AArch64MCExpr::VariantKind ELFRefKind;
630 MCSymbolRefExpr::VariantKind DarwinRefKind;
631 int64_t Addend;
632 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
633 DarwinRefKind, Addend)) {
634 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
635 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
636 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
637 || ELFRefKind == AArch64MCExpr::VK_LO12
638 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
639 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
640 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
641 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
642 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
643 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000644 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
645 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
646 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000647 }
648
Diana Picusc93518d2016-10-11 09:17:47 +0000649 // If it's a constant, it should be a real immediate in range:
650 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
651 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
652
653 // If it's an expression, we hope for the best and let the fixup/relocation
654 // code deal with it.
655 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000656 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000657
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000658 bool isAddSubImmNeg() const {
659 if (!isShiftedImm() && !isImm())
660 return false;
661
662 const MCExpr *Expr;
663
664 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
665 if (isShiftedImm()) {
666 unsigned Shift = ShiftedImm.ShiftAmount;
667 Expr = ShiftedImm.Val;
668 if (Shift != 0 && Shift != 12)
669 return false;
670 } else
671 Expr = getImm();
672
673 // Otherwise it should be a real negative immediate in range:
674 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
675 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
676 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000677
Tim Northover3b0846e2014-05-24 12:50:23 +0000678 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000679
Tim Northover3b0846e2014-05-24 12:50:23 +0000680 bool isSIMDImmType10() const {
681 if (!isImm())
682 return false;
683 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
684 if (!MCE)
685 return false;
686 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
687 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000688
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000689 template<int N>
690 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000691 if (!isImm())
692 return false;
693 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
694 if (!MCE)
695 return true;
696 int64_t Val = MCE->getValue();
697 if (Val & 0x3)
698 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000699 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
700 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000701 }
702
703 bool
704 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
705 if (!isImm())
706 return false;
707
708 AArch64MCExpr::VariantKind ELFRefKind;
709 MCSymbolRefExpr::VariantKind DarwinRefKind;
710 int64_t Addend;
711 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
712 DarwinRefKind, Addend)) {
713 return false;
714 }
715 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
716 return false;
717
718 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
719 if (ELFRefKind == AllowedModifiers[i])
720 return Addend == 0;
721 }
722
723 return false;
724 }
725
726 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000727 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000728 }
729
730 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000731 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
732 AArch64MCExpr::VK_TPREL_G2,
733 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000734 }
735
736 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000737 return isMovWSymbol({
738 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000739 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
740 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000741 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000742 }
743
744 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000745 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
746 AArch64MCExpr::VK_TPREL_G0,
747 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000748 }
749
750 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000751 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000752 }
753
754 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000755 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000756 }
757
758 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000759 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
760 AArch64MCExpr::VK_TPREL_G1_NC,
761 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000762 }
763
764 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000765 return isMovWSymbol(
766 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
767 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000768 }
769
770 template<int RegWidth, int Shift>
771 bool isMOVZMovAlias() const {
772 if (!isImm()) return false;
773
774 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
775 if (!CE) return false;
776 uint64_t Value = CE->getValue();
777
Tim Northoverdaa1c012016-06-16 01:42:25 +0000778 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000779 }
780
781 template<int RegWidth, int Shift>
782 bool isMOVNMovAlias() const {
783 if (!isImm()) return false;
784
785 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
786 if (!CE) return false;
787 uint64_t Value = CE->getValue();
788
Tim Northoverdaa1c012016-06-16 01:42:25 +0000789 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000790 }
791
792 bool isFPImm() const { return Kind == k_FPImm; }
793 bool isBarrier() const { return Kind == k_Barrier; }
794 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000795
Tim Northover3b0846e2014-05-24 12:50:23 +0000796 bool isMRSSystemRegister() const {
797 if (!isSysReg()) return false;
798
Tim Northover7cd58932015-01-22 17:23:04 +0000799 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000800 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000801
Tim Northover3b0846e2014-05-24 12:50:23 +0000802 bool isMSRSystemRegister() const {
803 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000804 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000805 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000806
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000807 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000808 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000809 return (SysReg.PStateField == AArch64PState::PAN ||
810 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000811 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000812
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000813 bool isSystemPStateFieldWithImm0_15() const {
814 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000815 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000816 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000817
Florian Hahnc4422242017-11-07 13:07:50 +0000818 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000819 return Kind == k_Register;
820 }
821
822 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000823 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
824 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000825
Florian Hahnc4422242017-11-07 13:07:50 +0000826 bool isNeonVectorReg() const {
827 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
828 }
829
830 bool isNeonVectorRegLo() const {
831 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000832 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
833 Reg.RegNum);
834 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000835
Sander de Smalencd6be962017-12-20 11:02:42 +0000836 template <unsigned Class> bool isSVEVectorReg() const {
837 RegKind RK;
838 switch (Class) {
839 case AArch64::ZPRRegClassID:
840 RK = RegKind::SVEDataVector;
841 break;
842 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000843 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000844 RK = RegKind::SVEPredicateVector;
845 break;
846 default:
847 llvm_unreachable("Unsupport register class");
848 }
849
850 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000851 AArch64MCRegisterClasses[Class].contains(getReg());
852 }
853
Sander de Smalencd6be962017-12-20 11:02:42 +0000854 template <int ElementWidth, unsigned Class>
855 bool isSVEVectorRegOfWidth() const {
856 return isSVEVectorReg<Class>() &&
Sander de Smalen73937b72018-04-11 07:36:10 +0000857 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth);
Florian Hahn91f11e52017-11-07 16:45:48 +0000858 }
859
Tim Northover3b0846e2014-05-24 12:50:23 +0000860 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000861 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000862 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
863 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000864
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000865 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000866 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000867 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
868 Reg.RegNum);
869 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000870
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000871 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000872 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000873 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
874 Reg.RegNum);
875 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000876
Sam Parker5f934642017-08-31 09:27:04 +0000877 template<int64_t Angle, int64_t Remainder>
878 bool isComplexRotation() const {
879 if (!isImm()) return false;
880
881 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
882 if (!CE) return false;
883 uint64_t Value = CE->getValue();
884
885 return (Value % Angle == Remainder && Value <= 270);
886 }
887
Sander de Smalen149916d2018-04-20 07:24:20 +0000888 template <unsigned RegClassID> bool isGPR64() const {
889 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
890 AArch64MCRegisterClasses[RegClassID].contains(getReg());
891 }
892
893 template <unsigned RegClassID, int ExtWidth>
894 bool isGPR64WithShiftExtend() const {
895 if (!isGPR64<RegClassID>())
896 return false;
897
898 return getShiftExtendType() == AArch64_AM::LSL &&
899 getShiftExtendAmount() == Log2_32(ExtWidth / 8);
900 }
901
Tim Northover3b0846e2014-05-24 12:50:23 +0000902 /// Is this a vector list with the type implicit (presumably attached to the
903 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +0000904 template <RegKind VectorKind, unsigned NumRegs>
905 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000906 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +0000907 VectorList.NumElements == 0 &&
908 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000909 }
910
Sander de Smalen650234b2018-04-12 11:40:52 +0000911 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
912 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +0000913 bool isTypedVectorList() const {
914 if (Kind != k_VectorList)
915 return false;
916 if (VectorList.Count != NumRegs)
917 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +0000918 if (VectorList.RegisterKind != VectorKind)
919 return false;
920 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +0000921 return false;
922 return VectorList.NumElements == NumElements;
923 }
924
925 bool isVectorIndex1() const {
926 return Kind == k_VectorIndex && VectorIndex.Val == 1;
927 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000928
Tim Northover3b0846e2014-05-24 12:50:23 +0000929 bool isVectorIndexB() const {
930 return Kind == k_VectorIndex && VectorIndex.Val < 16;
931 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000932
Tim Northover3b0846e2014-05-24 12:50:23 +0000933 bool isVectorIndexH() const {
934 return Kind == k_VectorIndex && VectorIndex.Val < 8;
935 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000936
Tim Northover3b0846e2014-05-24 12:50:23 +0000937 bool isVectorIndexS() const {
938 return Kind == k_VectorIndex && VectorIndex.Val < 4;
939 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000940
Tim Northover3b0846e2014-05-24 12:50:23 +0000941 bool isVectorIndexD() const {
942 return Kind == k_VectorIndex && VectorIndex.Val < 2;
943 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000944
Tim Northover3b0846e2014-05-24 12:50:23 +0000945 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000946
Tim Northover3b0846e2014-05-24 12:50:23 +0000947 bool isTokenEqual(StringRef Str) const {
948 return Kind == k_Token && getToken() == Str;
949 }
950 bool isSysCR() const { return Kind == k_SysCR; }
951 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000952 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000953 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
954 bool isShifter() const {
955 if (!isShiftExtend())
956 return false;
957
958 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
959 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
960 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
961 ST == AArch64_AM::MSL);
962 }
963 bool isExtend() const {
964 if (!isShiftExtend())
965 return false;
966
967 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
968 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
969 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
970 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
971 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
972 ET == AArch64_AM::LSL) &&
973 getShiftExtendAmount() <= 4;
974 }
975
976 bool isExtend64() const {
977 if (!isExtend())
978 return false;
979 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
980 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
981 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
982 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000983
Tim Northover3b0846e2014-05-24 12:50:23 +0000984 bool isExtendLSL64() const {
985 if (!isExtend())
986 return false;
987 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
988 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
989 ET == AArch64_AM::LSL) &&
990 getShiftExtendAmount() <= 4;
991 }
992
993 template<int Width> bool isMemXExtend() const {
994 if (!isExtend())
995 return false;
996 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
997 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
998 (getShiftExtendAmount() == Log2_32(Width / 8) ||
999 getShiftExtendAmount() == 0);
1000 }
1001
1002 template<int Width> bool isMemWExtend() const {
1003 if (!isExtend())
1004 return false;
1005 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1006 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1007 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1008 getShiftExtendAmount() == 0);
1009 }
1010
1011 template <unsigned width>
1012 bool isArithmeticShifter() const {
1013 if (!isShifter())
1014 return false;
1015
1016 // An arithmetic shifter is LSL, LSR, or ASR.
1017 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1018 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1019 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1020 }
1021
1022 template <unsigned width>
1023 bool isLogicalShifter() const {
1024 if (!isShifter())
1025 return false;
1026
1027 // A logical shifter is LSL, LSR, ASR or ROR.
1028 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1029 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1030 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1031 getShiftExtendAmount() < width;
1032 }
1033
1034 bool isMovImm32Shifter() const {
1035 if (!isShifter())
1036 return false;
1037
1038 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1039 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1040 if (ST != AArch64_AM::LSL)
1041 return false;
1042 uint64_t Val = getShiftExtendAmount();
1043 return (Val == 0 || Val == 16);
1044 }
1045
1046 bool isMovImm64Shifter() const {
1047 if (!isShifter())
1048 return false;
1049
1050 // A MOVi shifter is LSL of 0 or 16.
1051 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1052 if (ST != AArch64_AM::LSL)
1053 return false;
1054 uint64_t Val = getShiftExtendAmount();
1055 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1056 }
1057
1058 bool isLogicalVecShifter() const {
1059 if (!isShifter())
1060 return false;
1061
1062 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1063 unsigned Shift = getShiftExtendAmount();
1064 return getShiftExtendType() == AArch64_AM::LSL &&
1065 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1066 }
1067
1068 bool isLogicalVecHalfWordShifter() const {
1069 if (!isLogicalVecShifter())
1070 return false;
1071
1072 // A logical vector shifter is a left shift by 0 or 8.
1073 unsigned Shift = getShiftExtendAmount();
1074 return getShiftExtendType() == AArch64_AM::LSL &&
1075 (Shift == 0 || Shift == 8);
1076 }
1077
1078 bool isMoveVecShifter() const {
1079 if (!isShiftExtend())
1080 return false;
1081
1082 // A logical vector shifter is a left shift by 8 or 16.
1083 unsigned Shift = getShiftExtendAmount();
1084 return getShiftExtendType() == AArch64_AM::MSL &&
1085 (Shift == 8 || Shift == 16);
1086 }
1087
1088 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1089 // to LDUR/STUR when the offset is not legal for the former but is for
1090 // the latter. As such, in addition to checking for being a legal unscaled
1091 // address, also check that it is not a legal scaled address. This avoids
1092 // ambiguity in the matcher.
1093 template<int Width>
1094 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001095 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001096 }
1097
1098 bool isAdrpLabel() const {
1099 // Validation was handled during parsing, so we just sanity check that
1100 // something didn't go haywire.
1101 if (!isImm())
1102 return false;
1103
1104 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1105 int64_t Val = CE->getValue();
1106 int64_t Min = - (4096 * (1LL << (21 - 1)));
1107 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1108 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1109 }
1110
1111 return true;
1112 }
1113
1114 bool isAdrLabel() const {
1115 // Validation was handled during parsing, so we just sanity check that
1116 // something didn't go haywire.
1117 if (!isImm())
1118 return false;
1119
1120 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1121 int64_t Val = CE->getValue();
1122 int64_t Min = - (1LL << (21 - 1));
1123 int64_t Max = ((1LL << (21 - 1)) - 1);
1124 return Val >= Min && Val <= Max;
1125 }
1126
1127 return true;
1128 }
1129
1130 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1131 // Add as immediates when possible. Null MCExpr = 0.
1132 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001133 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001134 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001135 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001136 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001137 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001138 }
1139
1140 void addRegOperands(MCInst &Inst, unsigned N) const {
1141 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001142 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001143 }
1144
1145 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1146 assert(N == 1 && "Invalid number of operands!");
1147 assert(
1148 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1149
1150 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1151 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1152 RI->getEncodingValue(getReg()));
1153
Jim Grosbache9119e42015-05-13 18:37:00 +00001154 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001155 }
1156
1157 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1158 assert(N == 1 && "Invalid number of operands!");
1159 assert(
1160 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001161 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001162 }
1163
1164 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1165 assert(N == 1 && "Invalid number of operands!");
1166 assert(
1167 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001168 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001169 }
1170
1171 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1172 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001173 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001174 }
1175
Sander de Smalen525e3222018-04-12 13:19:32 +00001176 enum VecListIndexType {
1177 VecListIdx_DReg = 0,
1178 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001179 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001180 };
1181
1182 template <VecListIndexType RegTy, unsigned NumRegs>
1183 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001184 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001185 static const unsigned FirstRegs[][5] = {
1186 /* DReg */ { AArch64::Q0,
1187 AArch64::D0, AArch64::D0_D1,
1188 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1189 /* QReg */ { AArch64::Q0,
1190 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001191 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1192 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001193 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001194 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001195 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001196
Sander de Smalen7a210db2018-04-16 10:46:18 +00001197 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1198 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001199
Sander de Smalen525e3222018-04-12 13:19:32 +00001200 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1201 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1202 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001203 }
1204
1205 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1206 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001207 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001208 }
1209
1210 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1211 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001212 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001213 }
1214
1215 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1216 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001217 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001218 }
1219
1220 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1221 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001222 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001223 }
1224
1225 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1226 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001227 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001228 }
1229
1230 void addImmOperands(MCInst &Inst, unsigned N) const {
1231 assert(N == 1 && "Invalid number of operands!");
1232 // If this is a pageoff symrefexpr with an addend, adjust the addend
1233 // to be only the page-offset portion. Otherwise, just add the expr
1234 // as-is.
1235 addExpr(Inst, getImm());
1236 }
1237
1238 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1239 assert(N == 2 && "Invalid number of operands!");
1240 if (isShiftedImm()) {
1241 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001242 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001243 } else {
1244 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001245 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001246 }
1247 }
1248
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001249 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1250 assert(N == 2 && "Invalid number of operands!");
1251
1252 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1253 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1254 int64_t Val = -CE->getValue();
1255 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1256
1257 Inst.addOperand(MCOperand::createImm(Val));
1258 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1259 }
1260
Tim Northover3b0846e2014-05-24 12:50:23 +00001261 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1262 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001263 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001264 }
1265
1266 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1267 assert(N == 1 && "Invalid number of operands!");
1268 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1269 if (!MCE)
1270 addExpr(Inst, getImm());
1271 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001272 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001273 }
1274
1275 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1276 addImmOperands(Inst, N);
1277 }
1278
1279 template<int Scale>
1280 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1281 assert(N == 1 && "Invalid number of operands!");
1282 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1283
1284 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001285 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001286 return;
1287 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001288 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001289 }
1290
1291 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1292 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001293 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001294 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001295 }
1296
Sam Parker6d42de72017-08-11 13:14:00 +00001297 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1298 assert(N == 1 && "Invalid number of operands!");
1299 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1300 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1301 }
1302
Tim Northover3b0846e2014-05-24 12:50:23 +00001303 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1304 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001305 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001306 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001307 }
1308
1309 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1310 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001311 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001312 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001313 }
1314
1315 void addSImm7s16Operands(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() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001319 }
1320
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001321 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1322 assert(N == 1 && "Invalid number of operands!");
1323 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1324 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1325 }
1326
Tim Northover3b0846e2014-05-24 12:50:23 +00001327 void addImm0_7Operands(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 addImm1_8Operands(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 addImm0_15Operands(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_16Operands(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());
Tim Northover3b0846e2014-05-24 12:50:23 +00001348 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001349 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001350 }
1351
1352 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1353 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001354 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001355 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001356 }
1357
1358 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1359 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001360 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001361 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001362 }
1363
1364 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1365 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001366 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001367 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001368 }
1369
1370 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1371 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001372 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001373 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001374 }
1375
1376 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1377 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001378 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001379 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001380 }
1381
1382 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1383 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001384 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001385 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001386 }
1387
1388 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1389 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001390 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001391 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001392 }
1393
1394 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1395 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001396 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001397 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001398 }
1399
1400 void addImm0_65535Operands(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());
Jim Grosbache9119e42015-05-13 18:37:00 +00001403 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001404 }
1405
1406 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1407 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001408 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001409 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001410 }
1411
Sander de Smalen5c625982018-04-13 12:56:14 +00001412 template <int Scale>
1413 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1414 assert(N == 1 && "Invalid number of operands!");
1415 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1416 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1417 }
1418
Sander de Smalena1c259c2018-01-29 13:05:38 +00001419 template <typename T>
1420 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001421 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001422 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001423 typename std::make_unsigned<T>::type Val = MCE->getValue();
1424 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001425 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001426 }
1427
Sander de Smalena1c259c2018-01-29 13:05:38 +00001428 template <typename T>
1429 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001430 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001431 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001432 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1433 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001434 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001435 }
1436
Tim Northover3b0846e2014-05-24 12:50:23 +00001437 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1438 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001439 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001440 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001441 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001442 }
1443
1444 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1445 // Branch operands don't encode the low bits, so shift them off
1446 // here. If it's a label, however, just put it on directly as there's
1447 // not enough information now to do anything.
1448 assert(N == 1 && "Invalid number of operands!");
1449 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1450 if (!MCE) {
1451 addExpr(Inst, getImm());
1452 return;
1453 }
1454 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001455 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001456 }
1457
1458 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1459 // Branch operands don't encode the low bits, so shift them off
1460 // here. If it's a label, however, just put it on directly as there's
1461 // not enough information now to do anything.
1462 assert(N == 1 && "Invalid number of operands!");
1463 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1464 if (!MCE) {
1465 addExpr(Inst, getImm());
1466 return;
1467 }
1468 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001469 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001470 }
1471
1472 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1473 // Branch operands don't encode the low bits, so shift them off
1474 // here. If it's a label, however, just put it on directly as there's
1475 // not enough information now to do anything.
1476 assert(N == 1 && "Invalid number of operands!");
1477 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1478 if (!MCE) {
1479 addExpr(Inst, getImm());
1480 return;
1481 }
1482 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001483 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001484 }
1485
1486 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1487 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001488 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001489 }
1490
1491 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1492 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001493 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001494 }
1495
1496 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1497 assert(N == 1 && "Invalid number of operands!");
1498
Jim Grosbache9119e42015-05-13 18:37:00 +00001499 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001500 }
1501
1502 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1503 assert(N == 1 && "Invalid number of operands!");
1504
Jim Grosbache9119e42015-05-13 18:37:00 +00001505 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001506 }
1507
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001508 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1509 assert(N == 1 && "Invalid number of operands!");
1510
1511 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1512 }
1513
1514 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001515 assert(N == 1 && "Invalid number of operands!");
1516
Jim Grosbache9119e42015-05-13 18:37:00 +00001517 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001518 }
1519
1520 void addSysCROperands(MCInst &Inst, unsigned N) const {
1521 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001522 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001523 }
1524
1525 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1526 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001527 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001528 }
1529
Oliver Stannarda34e4702015-12-01 10:48:51 +00001530 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1531 assert(N == 1 && "Invalid number of operands!");
1532 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1533 }
1534
Tim Northover3b0846e2014-05-24 12:50:23 +00001535 void addShifterOperands(MCInst &Inst, unsigned N) const {
1536 assert(N == 1 && "Invalid number of operands!");
1537 unsigned Imm =
1538 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001539 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001540 }
1541
1542 void addExtendOperands(MCInst &Inst, unsigned N) const {
1543 assert(N == 1 && "Invalid number of operands!");
1544 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1545 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1546 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001547 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001548 }
1549
1550 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1551 assert(N == 1 && "Invalid number of operands!");
1552 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1553 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1554 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001555 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001556 }
1557
1558 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1559 assert(N == 2 && "Invalid number of operands!");
1560 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1561 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001562 Inst.addOperand(MCOperand::createImm(IsSigned));
1563 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001564 }
1565
1566 // For 8-bit load/store instructions with a register offset, both the
1567 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1568 // they're disambiguated by whether the shift was explicit or implicit rather
1569 // than its size.
1570 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1571 assert(N == 2 && "Invalid number of operands!");
1572 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1573 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001574 Inst.addOperand(MCOperand::createImm(IsSigned));
1575 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001576 }
1577
1578 template<int Shift>
1579 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1580 assert(N == 1 && "Invalid number of operands!");
1581
1582 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1583 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001584 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001585 }
1586
1587 template<int Shift>
1588 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1589 assert(N == 1 && "Invalid number of operands!");
1590
1591 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1592 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001593 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001594 }
1595
Sam Parker5f934642017-08-31 09:27:04 +00001596 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1597 assert(N == 1 && "Invalid number of operands!");
1598 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1599 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1600 }
1601
1602 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1603 assert(N == 1 && "Invalid number of operands!");
1604 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1605 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1606 }
1607
Tim Northover3b0846e2014-05-24 12:50:23 +00001608 void print(raw_ostream &OS) const override;
1609
David Blaikie960ea3f2014-06-08 16:18:35 +00001610 static std::unique_ptr<AArch64Operand>
1611 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1612 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001613 Op->Tok.Data = Str.data();
1614 Op->Tok.Length = Str.size();
1615 Op->Tok.IsSuffix = IsSuffix;
1616 Op->StartLoc = S;
1617 Op->EndLoc = S;
1618 return Op;
1619 }
1620
David Blaikie960ea3f2014-06-08 16:18:35 +00001621 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001622 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
1623 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1624 unsigned ShiftAmount = 0,
1625 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001626 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001627 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001628 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001629 Op->Reg.ElementWidth = 0;
1630 Op->Reg.ShiftExtend.Type = ExtTy;
1631 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1632 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001633 Op->StartLoc = S;
1634 Op->EndLoc = E;
1635 return Op;
1636 }
1637
David Blaikie960ea3f2014-06-08 16:18:35 +00001638 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001639 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001640 SMLoc S, SMLoc E, MCContext &Ctx,
1641 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1642 unsigned ShiftAmount = 0,
1643 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001644 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1645 Kind == RegKind::SVEPredicateVector) &&
1646 "Invalid vector kind");
Sander de Smalen149916d2018-04-20 07:24:20 +00001647 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, ExtTy, ShiftAmount,
1648 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001649 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001650 return Op;
1651 }
1652
1653 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001654 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001655 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1656 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001657 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001658 Op->VectorList.RegNum = RegNum;
1659 Op->VectorList.Count = Count;
1660 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001661 Op->VectorList.ElementWidth = ElementWidth;
1662 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001663 Op->StartLoc = S;
1664 Op->EndLoc = E;
1665 return Op;
1666 }
1667
David Blaikie960ea3f2014-06-08 16:18:35 +00001668 static std::unique_ptr<AArch64Operand>
1669 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1670 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001671 Op->VectorIndex.Val = Idx;
1672 Op->StartLoc = S;
1673 Op->EndLoc = E;
1674 return Op;
1675 }
1676
David Blaikie960ea3f2014-06-08 16:18:35 +00001677 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1678 SMLoc E, MCContext &Ctx) {
1679 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001680 Op->Imm.Val = Val;
1681 Op->StartLoc = S;
1682 Op->EndLoc = E;
1683 return Op;
1684 }
1685
David Blaikie960ea3f2014-06-08 16:18:35 +00001686 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1687 unsigned ShiftAmount,
1688 SMLoc S, SMLoc E,
1689 MCContext &Ctx) {
1690 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001691 Op->ShiftedImm .Val = Val;
1692 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1693 Op->StartLoc = S;
1694 Op->EndLoc = E;
1695 return Op;
1696 }
1697
David Blaikie960ea3f2014-06-08 16:18:35 +00001698 static std::unique_ptr<AArch64Operand>
1699 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1700 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001701 Op->CondCode.Code = Code;
1702 Op->StartLoc = S;
1703 Op->EndLoc = E;
1704 return Op;
1705 }
1706
David Blaikie960ea3f2014-06-08 16:18:35 +00001707 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1708 MCContext &Ctx) {
1709 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001710 Op->FPImm.Val = Val;
1711 Op->StartLoc = S;
1712 Op->EndLoc = S;
1713 return Op;
1714 }
1715
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001716 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1717 StringRef Str,
1718 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001719 MCContext &Ctx) {
1720 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001721 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001722 Op->Barrier.Data = Str.data();
1723 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001724 Op->StartLoc = S;
1725 Op->EndLoc = S;
1726 return Op;
1727 }
1728
Tim Northover7cd58932015-01-22 17:23:04 +00001729 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1730 uint32_t MRSReg,
1731 uint32_t MSRReg,
1732 uint32_t PStateField,
1733 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001734 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001735 Op->SysReg.Data = Str.data();
1736 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001737 Op->SysReg.MRSReg = MRSReg;
1738 Op->SysReg.MSRReg = MSRReg;
1739 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001740 Op->StartLoc = S;
1741 Op->EndLoc = S;
1742 return Op;
1743 }
1744
David Blaikie960ea3f2014-06-08 16:18:35 +00001745 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1746 SMLoc E, MCContext &Ctx) {
1747 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001748 Op->SysCRImm.Val = Val;
1749 Op->StartLoc = S;
1750 Op->EndLoc = E;
1751 return Op;
1752 }
1753
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001754 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1755 StringRef Str,
1756 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001757 MCContext &Ctx) {
1758 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001759 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001760 Op->Barrier.Data = Str.data();
1761 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001762 Op->StartLoc = S;
1763 Op->EndLoc = S;
1764 return Op;
1765 }
1766
Oliver Stannarda34e4702015-12-01 10:48:51 +00001767 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1768 StringRef Str,
1769 SMLoc S,
1770 MCContext &Ctx) {
1771 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1772 Op->PSBHint.Val = Val;
1773 Op->PSBHint.Data = Str.data();
1774 Op->PSBHint.Length = Str.size();
1775 Op->StartLoc = S;
1776 Op->EndLoc = S;
1777 return Op;
1778 }
1779
David Blaikie960ea3f2014-06-08 16:18:35 +00001780 static std::unique_ptr<AArch64Operand>
1781 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1782 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1783 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001784 Op->ShiftExtend.Type = ShOp;
1785 Op->ShiftExtend.Amount = Val;
1786 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1787 Op->StartLoc = S;
1788 Op->EndLoc = E;
1789 return Op;
1790 }
1791};
1792
1793} // end anonymous namespace.
1794
1795void AArch64Operand::print(raw_ostream &OS) const {
1796 switch (Kind) {
1797 case k_FPImm:
1798 OS << "<fpimm " << getFPImm() << "("
1799 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1800 break;
1801 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001802 StringRef Name = getBarrierName();
1803 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001804 OS << "<barrier " << Name << ">";
1805 else
1806 OS << "<barrier invalid #" << getBarrier() << ">";
1807 break;
1808 }
1809 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001810 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001811 break;
1812 case k_ShiftedImm: {
1813 unsigned Shift = getShiftedImmShift();
1814 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001815 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001816 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1817 break;
1818 }
1819 case k_CondCode:
1820 OS << "<condcode " << getCondCode() << ">";
1821 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001822 case k_VectorList: {
1823 OS << "<vectorlist ";
1824 unsigned Reg = getVectorListStart();
1825 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1826 OS << Reg + i << " ";
1827 OS << ">";
1828 break;
1829 }
1830 case k_VectorIndex:
1831 OS << "<vectorindex " << getVectorIndex() << ">";
1832 break;
1833 case k_SysReg:
1834 OS << "<sysreg: " << getSysReg() << '>';
1835 break;
1836 case k_Token:
1837 OS << "'" << getToken() << "'";
1838 break;
1839 case k_SysCR:
1840 OS << "c" << getSysCR();
1841 break;
1842 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001843 StringRef Name = getPrefetchName();
1844 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001845 OS << "<prfop " << Name << ">";
1846 else
1847 OS << "<prfop invalid #" << getPrefetch() << ">";
1848 break;
1849 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001850 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001851 OS << getPSBHintName();
1852 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00001853 case k_Register:
1854 OS << "<register " << getReg() << ">";
1855 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
1856 break;
1857 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001858 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001859 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1860 << getShiftExtendAmount();
1861 if (!hasShiftExtendAmount())
1862 OS << "<imp>";
1863 OS << '>';
1864 break;
1865 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001866}
1867
1868/// @name Auto-generated Match Functions
1869/// {
1870
1871static unsigned MatchRegisterName(StringRef Name);
1872
1873/// }
1874
Florian Hahnc4422242017-11-07 13:07:50 +00001875static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001876 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001877 .Case("v0", AArch64::Q0)
1878 .Case("v1", AArch64::Q1)
1879 .Case("v2", AArch64::Q2)
1880 .Case("v3", AArch64::Q3)
1881 .Case("v4", AArch64::Q4)
1882 .Case("v5", AArch64::Q5)
1883 .Case("v6", AArch64::Q6)
1884 .Case("v7", AArch64::Q7)
1885 .Case("v8", AArch64::Q8)
1886 .Case("v9", AArch64::Q9)
1887 .Case("v10", AArch64::Q10)
1888 .Case("v11", AArch64::Q11)
1889 .Case("v12", AArch64::Q12)
1890 .Case("v13", AArch64::Q13)
1891 .Case("v14", AArch64::Q14)
1892 .Case("v15", AArch64::Q15)
1893 .Case("v16", AArch64::Q16)
1894 .Case("v17", AArch64::Q17)
1895 .Case("v18", AArch64::Q18)
1896 .Case("v19", AArch64::Q19)
1897 .Case("v20", AArch64::Q20)
1898 .Case("v21", AArch64::Q21)
1899 .Case("v22", AArch64::Q22)
1900 .Case("v23", AArch64::Q23)
1901 .Case("v24", AArch64::Q24)
1902 .Case("v25", AArch64::Q25)
1903 .Case("v26", AArch64::Q26)
1904 .Case("v27", AArch64::Q27)
1905 .Case("v28", AArch64::Q28)
1906 .Case("v29", AArch64::Q29)
1907 .Case("v30", AArch64::Q30)
1908 .Case("v31", AArch64::Q31)
1909 .Default(0);
1910}
1911
Sander de Smalen73937b72018-04-11 07:36:10 +00001912/// Returns an optional pair of (#elements, element-width) if Suffix
1913/// is a valid vector kind. Where the number of elements in a vector
1914/// or the vector width is implicit or explicitly unknown (but still a
1915/// valid suffix kind), 0 is used.
1916static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1917 RegKind VectorKind) {
1918 std::pair<int, int> Res = {-1, -1};
1919
1920 switch (VectorKind) {
1921 case RegKind::NeonVector:
1922 Res =
1923 StringSwitch<std::pair<int, int>>(Suffix.lower())
1924 .Case("", {0, 0})
1925 .Case(".1d", {1, 64})
1926 .Case(".1q", {1, 128})
1927 // '.2h' needed for fp16 scalar pairwise reductions
1928 .Case(".2h", {2, 16})
1929 .Case(".2s", {2, 32})
1930 .Case(".2d", {2, 64})
1931 // '.4b' is another special case for the ARMv8.2a dot product
1932 // operand
1933 .Case(".4b", {4, 8})
1934 .Case(".4h", {4, 16})
1935 .Case(".4s", {4, 32})
1936 .Case(".8b", {8, 8})
1937 .Case(".8h", {8, 16})
1938 .Case(".16b", {16, 8})
1939 // Accept the width neutral ones, too, for verbose syntax. If those
1940 // aren't used in the right places, the token operand won't match so
1941 // all will work out.
1942 .Case(".b", {0, 8})
1943 .Case(".h", {0, 16})
1944 .Case(".s", {0, 32})
1945 .Case(".d", {0, 64})
1946 .Default({-1, -1});
1947 break;
1948 case RegKind::SVEPredicateVector:
1949 case RegKind::SVEDataVector:
1950 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1951 .Case("", {0, 0})
1952 .Case(".b", {0, 8})
1953 .Case(".h", {0, 16})
1954 .Case(".s", {0, 32})
1955 .Case(".d", {0, 64})
1956 .Case(".q", {0, 128})
1957 .Default({-1, -1});
1958 break;
1959 default:
1960 llvm_unreachable("Unsupported RegKind");
1961 }
1962
1963 if (Res == std::make_pair(-1, -1))
1964 return Optional<std::pair<int, int>>();
1965
1966 return Optional<std::pair<int, int>>(Res);
1967}
1968
1969static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1970 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001971}
1972
Florian Hahn91f11e52017-11-07 16:45:48 +00001973static unsigned matchSVEDataVectorRegName(StringRef Name) {
1974 return StringSwitch<unsigned>(Name.lower())
1975 .Case("z0", AArch64::Z0)
1976 .Case("z1", AArch64::Z1)
1977 .Case("z2", AArch64::Z2)
1978 .Case("z3", AArch64::Z3)
1979 .Case("z4", AArch64::Z4)
1980 .Case("z5", AArch64::Z5)
1981 .Case("z6", AArch64::Z6)
1982 .Case("z7", AArch64::Z7)
1983 .Case("z8", AArch64::Z8)
1984 .Case("z9", AArch64::Z9)
1985 .Case("z10", AArch64::Z10)
1986 .Case("z11", AArch64::Z11)
1987 .Case("z12", AArch64::Z12)
1988 .Case("z13", AArch64::Z13)
1989 .Case("z14", AArch64::Z14)
1990 .Case("z15", AArch64::Z15)
1991 .Case("z16", AArch64::Z16)
1992 .Case("z17", AArch64::Z17)
1993 .Case("z18", AArch64::Z18)
1994 .Case("z19", AArch64::Z19)
1995 .Case("z20", AArch64::Z20)
1996 .Case("z21", AArch64::Z21)
1997 .Case("z22", AArch64::Z22)
1998 .Case("z23", AArch64::Z23)
1999 .Case("z24", AArch64::Z24)
2000 .Case("z25", AArch64::Z25)
2001 .Case("z26", AArch64::Z26)
2002 .Case("z27", AArch64::Z27)
2003 .Case("z28", AArch64::Z28)
2004 .Case("z29", AArch64::Z29)
2005 .Case("z30", AArch64::Z30)
2006 .Case("z31", AArch64::Z31)
2007 .Default(0);
2008}
2009
Sander de Smalencd6be962017-12-20 11:02:42 +00002010static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2011 return StringSwitch<unsigned>(Name.lower())
2012 .Case("p0", AArch64::P0)
2013 .Case("p1", AArch64::P1)
2014 .Case("p2", AArch64::P2)
2015 .Case("p3", AArch64::P3)
2016 .Case("p4", AArch64::P4)
2017 .Case("p5", AArch64::P5)
2018 .Case("p6", AArch64::P6)
2019 .Case("p7", AArch64::P7)
2020 .Case("p8", AArch64::P8)
2021 .Case("p9", AArch64::P9)
2022 .Case("p10", AArch64::P10)
2023 .Case("p11", AArch64::P11)
2024 .Case("p12", AArch64::P12)
2025 .Case("p13", AArch64::P13)
2026 .Case("p14", AArch64::P14)
2027 .Case("p15", AArch64::P15)
2028 .Default(0);
2029}
2030
Tim Northover3b0846e2014-05-24 12:50:23 +00002031bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2032 SMLoc &EndLoc) {
2033 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002034 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002035 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002036 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002037}
2038
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002039// Matches a register name or register alias previously defined by '.req'
2040unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002041 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002042 unsigned RegNum = 0;
2043 if ((RegNum = matchSVEDataVectorRegName(Name)))
2044 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2045
Sander de Smalencd6be962017-12-20 11:02:42 +00002046 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2047 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2048
Sander de Smalenc067c302017-12-20 09:45:45 +00002049 if ((RegNum = MatchNeonVectorRegName(Name)))
2050 return Kind == RegKind::NeonVector ? RegNum : 0;
2051
2052 // The parsed register must be of RegKind Scalar
2053 if ((RegNum = MatchRegisterName(Name)))
2054 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002055
Florian Hahnc4422242017-11-07 13:07:50 +00002056 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002057 // Handle a few common aliases of registers.
2058 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2059 .Case("fp", AArch64::FP)
2060 .Case("lr", AArch64::LR)
2061 .Case("x31", AArch64::XZR)
2062 .Case("w31", AArch64::WZR)
2063 .Default(0))
2064 return Kind == RegKind::Scalar ? RegNum : 0;
2065
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002066 // Check for aliases registered via .req. Canonicalize to lower case.
2067 // That's more consistent since register names are case insensitive, and
2068 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2069 auto Entry = RegisterReqs.find(Name.lower());
2070 if (Entry == RegisterReqs.end())
2071 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002072
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002073 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002074 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002075 RegNum = Entry->getValue().second;
2076 }
2077 return RegNum;
2078}
2079
Sander de Smalen50d87022018-04-19 07:35:08 +00002080/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002081/// Identifier when called, and if it is a register name the token is eaten and
2082/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002083OperandMatchResultTy
2084AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002085 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002086 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002087 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002088 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002089
2090 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002091 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2092 if (Reg == 0)
2093 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002094
Sander de Smalen50d87022018-04-19 07:35:08 +00002095 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002096 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002097 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002098}
2099
Tim Northover3b0846e2014-05-24 12:50:23 +00002100/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002101OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002102AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002103 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002104 SMLoc S = getLoc();
2105
2106 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2107 Error(S, "Expected cN operand where 0 <= N <= 15");
2108 return MatchOperand_ParseFail;
2109 }
2110
2111 StringRef Tok = Parser.getTok().getIdentifier();
2112 if (Tok[0] != 'c' && Tok[0] != 'C') {
2113 Error(S, "Expected cN operand where 0 <= N <= 15");
2114 return MatchOperand_ParseFail;
2115 }
2116
2117 uint32_t CRNum;
2118 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2119 if (BadNum || CRNum > 15) {
2120 Error(S, "Expected cN operand where 0 <= N <= 15");
2121 return MatchOperand_ParseFail;
2122 }
2123
2124 Parser.Lex(); // Eat identifier token.
2125 Operands.push_back(
2126 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2127 return MatchOperand_Success;
2128}
2129
2130/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002131OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002132AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002133 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002134 SMLoc S = getLoc();
2135 const AsmToken &Tok = Parser.getTok();
2136 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002137 // Eat optional hash.
2138 if (parseOptionalToken(AsmToken::Hash) ||
2139 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002140 const MCExpr *ImmVal;
2141 if (getParser().parseExpression(ImmVal))
2142 return MatchOperand_ParseFail;
2143
2144 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2145 if (!MCE) {
2146 TokError("immediate value expected for prefetch operand");
2147 return MatchOperand_ParseFail;
2148 }
2149 unsigned prfop = MCE->getValue();
2150 if (prfop > 31) {
2151 TokError("prefetch operand out of range, [0,31] expected");
2152 return MatchOperand_ParseFail;
2153 }
2154
Tim Northovere6ae6762016-07-05 21:23:04 +00002155 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2156 Operands.push_back(AArch64Operand::CreatePrefetch(
2157 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002158 return MatchOperand_Success;
2159 }
2160
2161 if (Tok.isNot(AsmToken::Identifier)) {
2162 TokError("pre-fetch hint expected");
2163 return MatchOperand_ParseFail;
2164 }
2165
Tim Northovere6ae6762016-07-05 21:23:04 +00002166 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2167 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002168 TokError("pre-fetch hint expected");
2169 return MatchOperand_ParseFail;
2170 }
2171
2172 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002173 Operands.push_back(AArch64Operand::CreatePrefetch(
2174 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002175 return MatchOperand_Success;
2176}
2177
Oliver Stannarda34e4702015-12-01 10:48:51 +00002178/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002179OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002180AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2181 MCAsmParser &Parser = getParser();
2182 SMLoc S = getLoc();
2183 const AsmToken &Tok = Parser.getTok();
2184 if (Tok.isNot(AsmToken::Identifier)) {
2185 TokError("invalid operand for instruction");
2186 return MatchOperand_ParseFail;
2187 }
2188
Tim Northovere6ae6762016-07-05 21:23:04 +00002189 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2190 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002191 TokError("invalid operand for instruction");
2192 return MatchOperand_ParseFail;
2193 }
2194
2195 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002196 Operands.push_back(AArch64Operand::CreatePSBHint(
2197 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002198 return MatchOperand_Success;
2199}
2200
Tim Northover3b0846e2014-05-24 12:50:23 +00002201/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2202/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002203OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002204AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002205 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002206 SMLoc S = getLoc();
2207 const MCExpr *Expr;
2208
2209 if (Parser.getTok().is(AsmToken::Hash)) {
2210 Parser.Lex(); // Eat hash token.
2211 }
2212
2213 if (parseSymbolicImmVal(Expr))
2214 return MatchOperand_ParseFail;
2215
2216 AArch64MCExpr::VariantKind ELFRefKind;
2217 MCSymbolRefExpr::VariantKind DarwinRefKind;
2218 int64_t Addend;
2219 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2220 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2221 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2222 // No modifier was specified at all; this is the syntax for an ELF basic
2223 // ADRP relocation (unfortunately).
2224 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002225 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002226 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2227 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2228 Addend != 0) {
2229 Error(S, "gotpage label reference not allowed an addend");
2230 return MatchOperand_ParseFail;
2231 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2232 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2233 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2234 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2235 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2236 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2237 // The operand must be an @page or @gotpage qualified symbolref.
2238 Error(S, "page or gotpage label reference expected");
2239 return MatchOperand_ParseFail;
2240 }
2241 }
2242
2243 // We have either a label reference possibly with addend or an immediate. The
2244 // addend is a raw value here. The linker will adjust it to only reference the
2245 // page.
2246 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2247 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2248
2249 return MatchOperand_Success;
2250}
2251
2252/// tryParseAdrLabel - Parse and validate a source label for the ADR
2253/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002254OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002255AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2256 SMLoc S = getLoc();
2257 const MCExpr *Expr;
2258
Nirav Davee833c6c2016-11-08 18:31:04 +00002259 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002260 if (getParser().parseExpression(Expr))
2261 return MatchOperand_ParseFail;
2262
2263 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2264 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2265
2266 return MatchOperand_Success;
2267}
2268
2269/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002270OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002271AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002272 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002273 SMLoc S = getLoc();
2274
Nirav Davee833c6c2016-11-08 18:31:04 +00002275 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002276
2277 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002278 bool isNegative = parseOptionalToken(AsmToken::Minus);
2279
Tim Northover3b0846e2014-05-24 12:50:23 +00002280 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002281 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002282 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002283 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002284 Val = Tok.getIntVal();
2285 if (Val > 255 || Val < 0) {
2286 TokError("encoded floating point value out of range");
2287 return MatchOperand_ParseFail;
2288 }
2289 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002290 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002291 if (isNegative)
2292 RealVal.changeSign();
2293
Tim Northover3b0846e2014-05-24 12:50:23 +00002294 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002295 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002296
John Brawn5ca5daa2017-04-20 10:13:54 +00002297 // Check for out of range values. As an exception we let Zero through,
2298 // but as tokens instead of an FPImm so that it can be matched by the
2299 // appropriate alias if one exists.
2300 if (RealVal.isPosZero()) {
2301 Parser.Lex(); // Eat the token.
2302 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2303 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2304 return MatchOperand_Success;
2305 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002306 TokError("expected compatible register or floating-point constant");
2307 return MatchOperand_ParseFail;
2308 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002309 }
2310 Parser.Lex(); // Eat the token.
2311 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2312 return MatchOperand_Success;
2313 }
2314
2315 if (!Hash)
2316 return MatchOperand_NoMatch;
2317
2318 TokError("invalid floating point immediate");
2319 return MatchOperand_ParseFail;
2320}
2321
2322/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002323OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002324AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002325 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002326 SMLoc S = getLoc();
2327
2328 if (Parser.getTok().is(AsmToken::Hash))
2329 Parser.Lex(); // Eat '#'
2330 else if (Parser.getTok().isNot(AsmToken::Integer))
2331 // Operand should start from # or should be integer, emit error otherwise.
2332 return MatchOperand_NoMatch;
2333
2334 const MCExpr *Imm;
2335 if (parseSymbolicImmVal(Imm))
2336 return MatchOperand_ParseFail;
2337 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2338 uint64_t ShiftAmount = 0;
2339 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2340 if (MCE) {
2341 int64_t Val = MCE->getValue();
2342 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002343 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002344 ShiftAmount = 12;
2345 }
2346 }
2347 SMLoc E = Parser.getTok().getLoc();
2348 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2349 getContext()));
2350 return MatchOperand_Success;
2351 }
2352
2353 // Eat ','
2354 Parser.Lex();
2355
2356 // The optional operand must be "lsl #N" where N is non-negative.
2357 if (!Parser.getTok().is(AsmToken::Identifier) ||
2358 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2359 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2360 return MatchOperand_ParseFail;
2361 }
2362
2363 // Eat 'lsl'
2364 Parser.Lex();
2365
Nirav Davee833c6c2016-11-08 18:31:04 +00002366 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002367
2368 if (Parser.getTok().isNot(AsmToken::Integer)) {
2369 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2370 return MatchOperand_ParseFail;
2371 }
2372
2373 int64_t ShiftAmount = Parser.getTok().getIntVal();
2374
2375 if (ShiftAmount < 0) {
2376 Error(Parser.getTok().getLoc(), "positive shift amount required");
2377 return MatchOperand_ParseFail;
2378 }
2379 Parser.Lex(); // Eat the number
2380
2381 SMLoc E = Parser.getTok().getLoc();
2382 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2383 S, E, getContext()));
2384 return MatchOperand_Success;
2385}
2386
2387/// parseCondCodeString - Parse a Condition Code string.
2388AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2389 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2390 .Case("eq", AArch64CC::EQ)
2391 .Case("ne", AArch64CC::NE)
2392 .Case("cs", AArch64CC::HS)
2393 .Case("hs", AArch64CC::HS)
2394 .Case("cc", AArch64CC::LO)
2395 .Case("lo", AArch64CC::LO)
2396 .Case("mi", AArch64CC::MI)
2397 .Case("pl", AArch64CC::PL)
2398 .Case("vs", AArch64CC::VS)
2399 .Case("vc", AArch64CC::VC)
2400 .Case("hi", AArch64CC::HI)
2401 .Case("ls", AArch64CC::LS)
2402 .Case("ge", AArch64CC::GE)
2403 .Case("lt", AArch64CC::LT)
2404 .Case("gt", AArch64CC::GT)
2405 .Case("le", AArch64CC::LE)
2406 .Case("al", AArch64CC::AL)
2407 .Case("nv", AArch64CC::NV)
2408 .Default(AArch64CC::Invalid);
2409 return CC;
2410}
2411
2412/// parseCondCode - Parse a Condition Code operand.
2413bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2414 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002415 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002416 SMLoc S = getLoc();
2417 const AsmToken &Tok = Parser.getTok();
2418 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2419
2420 StringRef Cond = Tok.getString();
2421 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2422 if (CC == AArch64CC::Invalid)
2423 return TokError("invalid condition code");
2424 Parser.Lex(); // Eat identifier token.
2425
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002426 if (invertCondCode) {
2427 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2428 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002429 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002430 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002431
2432 Operands.push_back(
2433 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2434 return false;
2435}
2436
2437/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2438/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002439OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002440AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002441 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002442 const AsmToken &Tok = Parser.getTok();
2443 std::string LowerID = Tok.getString().lower();
2444 AArch64_AM::ShiftExtendType ShOp =
2445 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2446 .Case("lsl", AArch64_AM::LSL)
2447 .Case("lsr", AArch64_AM::LSR)
2448 .Case("asr", AArch64_AM::ASR)
2449 .Case("ror", AArch64_AM::ROR)
2450 .Case("msl", AArch64_AM::MSL)
2451 .Case("uxtb", AArch64_AM::UXTB)
2452 .Case("uxth", AArch64_AM::UXTH)
2453 .Case("uxtw", AArch64_AM::UXTW)
2454 .Case("uxtx", AArch64_AM::UXTX)
2455 .Case("sxtb", AArch64_AM::SXTB)
2456 .Case("sxth", AArch64_AM::SXTH)
2457 .Case("sxtw", AArch64_AM::SXTW)
2458 .Case("sxtx", AArch64_AM::SXTX)
2459 .Default(AArch64_AM::InvalidShiftExtend);
2460
2461 if (ShOp == AArch64_AM::InvalidShiftExtend)
2462 return MatchOperand_NoMatch;
2463
2464 SMLoc S = Tok.getLoc();
2465 Parser.Lex();
2466
Nirav Davee833c6c2016-11-08 18:31:04 +00002467 bool Hash = parseOptionalToken(AsmToken::Hash);
2468
Tim Northover3b0846e2014-05-24 12:50:23 +00002469 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2470 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2471 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2472 ShOp == AArch64_AM::MSL) {
2473 // We expect a number here.
2474 TokError("expected #imm after shift specifier");
2475 return MatchOperand_ParseFail;
2476 }
2477
Chad Rosier2ff37b82016-12-27 16:58:09 +00002478 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002479 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2480 Operands.push_back(
2481 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2482 return MatchOperand_Success;
2483 }
2484
Chad Rosier2ff37b82016-12-27 16:58:09 +00002485 // Make sure we do actually have a number, identifier or a parenthesized
2486 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002487 SMLoc E = Parser.getTok().getLoc();
2488 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002489 !Parser.getTok().is(AsmToken::LParen) &&
2490 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002491 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002492 return MatchOperand_ParseFail;
2493 }
2494
2495 const MCExpr *ImmVal;
2496 if (getParser().parseExpression(ImmVal))
2497 return MatchOperand_ParseFail;
2498
2499 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2500 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002501 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002502 return MatchOperand_ParseFail;
2503 }
2504
Jim Grosbach57fd2622014-09-23 22:16:02 +00002505 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002506 Operands.push_back(AArch64Operand::CreateShiftExtend(
2507 ShOp, MCE->getValue(), true, S, E, getContext()));
2508 return MatchOperand_Success;
2509}
2510
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002511static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2512 if (FBS[AArch64::HasV8_1aOps])
2513 Str += "ARMv8.1a";
2514 else if (FBS[AArch64::HasV8_2aOps])
2515 Str += "ARMv8.2a";
2516 else
2517 Str += "(unknown)";
2518}
2519
2520void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2521 SMLoc S) {
2522 const uint16_t Op2 = Encoding & 7;
2523 const uint16_t Cm = (Encoding & 0x78) >> 3;
2524 const uint16_t Cn = (Encoding & 0x780) >> 7;
2525 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2526
2527 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2528
2529 Operands.push_back(
2530 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2531 Operands.push_back(
2532 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2533 Operands.push_back(
2534 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2535 Expr = MCConstantExpr::create(Op2, getContext());
2536 Operands.push_back(
2537 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2538}
2539
Tim Northover3b0846e2014-05-24 12:50:23 +00002540/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2541/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2542bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2543 OperandVector &Operands) {
2544 if (Name.find('.') != StringRef::npos)
2545 return TokError("invalid operand");
2546
2547 Mnemonic = Name;
2548 Operands.push_back(
2549 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2550
Rafael Espindola961d4692014-11-11 05:18:41 +00002551 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002552 const AsmToken &Tok = Parser.getTok();
2553 StringRef Op = Tok.getString();
2554 SMLoc S = Tok.getLoc();
2555
Tim Northover3b0846e2014-05-24 12:50:23 +00002556 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002557 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2558 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002559 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002560 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2561 std::string Str("IC " + std::string(IC->Name) + " requires ");
2562 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2563 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002564 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002565 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002566 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002567 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2568 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002569 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002570 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2571 std::string Str("DC " + std::string(DC->Name) + " requires ");
2572 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2573 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002574 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002575 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002576 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002577 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2578 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002579 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002580 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2581 std::string Str("AT " + std::string(AT->Name) + " requires ");
2582 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2583 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002584 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002585 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002586 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002587 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2588 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002589 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002590 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2591 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2592 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2593 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002594 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002595 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002596 }
2597
Tim Northover3b0846e2014-05-24 12:50:23 +00002598 Parser.Lex(); // Eat operand.
2599
2600 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2601 bool HasRegister = false;
2602
2603 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002604 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002605 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2606 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002607 HasRegister = true;
2608 }
2609
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002610 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002611 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002612 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002613 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002614
Nirav Davee833c6c2016-11-08 18:31:04 +00002615 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2616 return true;
2617
Tim Northover3b0846e2014-05-24 12:50:23 +00002618 return false;
2619}
2620
Alex Bradbury58eba092016-11-01 16:32:05 +00002621OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002622AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002623 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002624 const AsmToken &Tok = Parser.getTok();
2625
2626 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002627 if (parseOptionalToken(AsmToken::Hash) ||
2628 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002629 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002630 const MCExpr *ImmVal;
2631 SMLoc ExprLoc = getLoc();
2632 if (getParser().parseExpression(ImmVal))
2633 return MatchOperand_ParseFail;
2634 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2635 if (!MCE) {
2636 Error(ExprLoc, "immediate value expected for barrier operand");
2637 return MatchOperand_ParseFail;
2638 }
2639 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2640 Error(ExprLoc, "barrier operand out of range");
2641 return MatchOperand_ParseFail;
2642 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002643 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2644 Operands.push_back(AArch64Operand::CreateBarrier(
2645 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002646 return MatchOperand_Success;
2647 }
2648
2649 if (Tok.isNot(AsmToken::Identifier)) {
2650 TokError("invalid operand for instruction");
2651 return MatchOperand_ParseFail;
2652 }
2653
Tim Northover3b0846e2014-05-24 12:50:23 +00002654 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002655 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2656 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002657 TokError("'sy' or #imm operand expected");
2658 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002659 } else if (!DB) {
2660 TokError("invalid barrier option name");
2661 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002662 }
2663
Tim Northovere6ae6762016-07-05 21:23:04 +00002664 Operands.push_back(AArch64Operand::CreateBarrier(
2665 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002666 Parser.Lex(); // Consume the option
2667
2668 return MatchOperand_Success;
2669}
2670
Alex Bradbury58eba092016-11-01 16:32:05 +00002671OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002672AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002673 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002674 const AsmToken &Tok = Parser.getTok();
2675
2676 if (Tok.isNot(AsmToken::Identifier))
2677 return MatchOperand_NoMatch;
2678
Tim Northovere6ae6762016-07-05 21:23:04 +00002679 int MRSReg, MSRReg;
2680 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2681 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2682 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2683 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2684 } else
2685 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002686
Tim Northovere6ae6762016-07-05 21:23:04 +00002687 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2688 unsigned PStateImm = -1;
2689 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2690 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002691
Tim Northovere6ae6762016-07-05 21:23:04 +00002692 Operands.push_back(
2693 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2694 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002695 Parser.Lex(); // Eat identifier
2696
2697 return MatchOperand_Success;
2698}
2699
Florian Hahnc4422242017-11-07 13:07:50 +00002700/// tryParseNeonVectorRegister - Parse a vector register operand.
2701bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002702 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002703 if (Parser.getTok().isNot(AsmToken::Identifier))
2704 return true;
2705
2706 SMLoc S = getLoc();
2707 // Check for a vector register specifier first.
2708 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002709 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002710 OperandMatchResultTy Res =
2711 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2712 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002713 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002714
2715 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2716 if (!KindRes)
2717 return true;
2718
2719 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002720 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002721 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2722 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002723
Tim Northover3b0846e2014-05-24 12:50:23 +00002724 // If there was an explicit qualifier, that goes on as a literal text
2725 // operand.
2726 if (!Kind.empty())
2727 Operands.push_back(
2728 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2729
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002730 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2731}
2732
2733OperandMatchResultTy
2734AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002735 SMLoc SIdx = getLoc();
2736 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002737 const MCExpr *ImmVal;
2738 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002739 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002740 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2741 if (!MCE) {
2742 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002743 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002744 }
2745
2746 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002747
Nirav Davee833c6c2016-11-08 18:31:04 +00002748 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002749 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002750
2751 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2752 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002753 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002754 }
2755
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002756 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002757}
2758
Sander de Smalen73937b72018-04-11 07:36:10 +00002759// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002760// optional kind specifier. If it is a register specifier, eat the token
2761// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002762OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002763AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002764 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002765 MCAsmParser &Parser = getParser();
2766 const AsmToken &Tok = Parser.getTok();
2767
Florian Hahn91f11e52017-11-07 16:45:48 +00002768 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002769 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002770
2771 StringRef Name = Tok.getString();
2772 // If there is a kind specifier, it's separated from the register name by
2773 // a '.'.
2774 size_t Start = 0, Next = Name.find('.');
2775 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002776 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002777
2778 if (RegNum) {
2779 if (Next != StringRef::npos) {
2780 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002781 if (!isValidVectorKind(Kind, MatchKind)) {
2782 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002783 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002784 }
2785 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002786 Parser.Lex(); // Eat the register token.
2787
2788 Reg = RegNum;
2789 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002790 }
2791
Sander de Smalen8e607342017-11-15 15:44:43 +00002792 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002793}
2794
Sander de Smalencd6be962017-12-20 11:02:42 +00002795/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2796OperandMatchResultTy
2797AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2798 // Check for a SVE predicate register specifier first.
2799 const SMLoc S = getLoc();
2800 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002801 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002802 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002803 if (Res != MatchOperand_Success)
2804 return Res;
2805
Sander de Smalen73937b72018-04-11 07:36:10 +00002806 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2807 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002808 return MatchOperand_NoMatch;
2809
Sander de Smalen73937b72018-04-11 07:36:10 +00002810 unsigned ElementWidth = KindRes->second;
2811 Operands.push_back(AArch64Operand::CreateVectorReg(
2812 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2813 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002814
Sander de Smalen7868e742018-01-09 11:17:06 +00002815 // Not all predicates are followed by a '/m' or '/z'.
2816 MCAsmParser &Parser = getParser();
2817 if (Parser.getTok().isNot(AsmToken::Slash))
2818 return MatchOperand_Success;
2819
2820 // But when they do they shouldn't have an element type suffix.
2821 if (!Kind.empty()) {
2822 Error(S, "not expecting size suffix");
2823 return MatchOperand_ParseFail;
2824 }
2825
2826 // Add a literal slash as operand
2827 Operands.push_back(
2828 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2829
2830 Parser.Lex(); // Eat the slash.
2831
2832 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002833 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002834 if (Pred != "z" && Pred != "m") {
2835 Error(getLoc(), "expecting 'm' or 'z' predication");
2836 return MatchOperand_ParseFail;
2837 }
2838
2839 // Add zero/merge token.
2840 const char *ZM = Pred == "z" ? "z" : "m";
2841 Operands.push_back(
2842 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2843
2844 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002845 return MatchOperand_Success;
2846}
2847
Sander de Smalen50d87022018-04-19 07:35:08 +00002848/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002849bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002850 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002851 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002852 return false;
2853
Sander de Smalen149916d2018-04-20 07:24:20 +00002854 // Otherwise try for a scalar register.
2855 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
2856 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002857
Sander de Smalen149916d2018-04-20 07:24:20 +00002858 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002859}
2860
2861bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002862 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002863 bool HasELFModifier = false;
2864 AArch64MCExpr::VariantKind RefKind;
2865
Nirav Davee833c6c2016-11-08 18:31:04 +00002866 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002867 HasELFModifier = true;
2868
Nirav Davee833c6c2016-11-08 18:31:04 +00002869 if (Parser.getTok().isNot(AsmToken::Identifier))
2870 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002871
2872 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2873 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2874 .Case("lo12", AArch64MCExpr::VK_LO12)
2875 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2876 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2877 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2878 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2879 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2880 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2881 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2882 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2883 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2884 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2885 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2886 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2887 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2888 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2889 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2890 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2891 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2892 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2893 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2894 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2895 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2896 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2897 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2898 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2899 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2900 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2901 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2902 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2903 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2904 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2905 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2906 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2907 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2908 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002909 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2910 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002911 .Default(AArch64MCExpr::VK_INVALID);
2912
Nirav Davee833c6c2016-11-08 18:31:04 +00002913 if (RefKind == AArch64MCExpr::VK_INVALID)
2914 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002915
2916 Parser.Lex(); // Eat identifier
2917
Nirav Davee833c6c2016-11-08 18:31:04 +00002918 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002919 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002920 }
2921
2922 if (getParser().parseExpression(ImmVal))
2923 return true;
2924
2925 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002926 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002927
2928 return false;
2929}
2930
Sander de Smalen650234b2018-04-12 11:40:52 +00002931template <RegKind VectorKind>
2932OperandMatchResultTy
2933AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
2934 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002935 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00002936 if (!Parser.getTok().is(AsmToken::LCurly))
2937 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002938
2939 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00002940 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00002941 bool NoMatchIsError) {
2942 auto RegTok = Parser.getTok();
2943 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
2944 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002945 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00002946 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002947 llvm_unreachable("Expected a valid vector kind");
2948 }
2949
Sander de Smalen650234b2018-04-12 11:40:52 +00002950 if (RegTok.isNot(AsmToken::Identifier) ||
2951 ParseRes == MatchOperand_ParseFail ||
2952 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
2953 Error(Loc, "vector register expected");
2954 return MatchOperand_ParseFail;
2955 }
2956
2957 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002958 };
2959
Tim Northover3b0846e2014-05-24 12:50:23 +00002960 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00002961 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00002962 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00002963
Tim Northover3b0846e2014-05-24 12:50:23 +00002964 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002965 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002966 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
2967
2968 // Put back the original left bracket if there was no match, so that
2969 // different types of list-operands can be matched (e.g. SVE, Neon).
2970 if (ParseRes == MatchOperand_NoMatch)
2971 Parser.getLexer().UnLex(LCurly);
2972
2973 if (ParseRes != MatchOperand_Success)
2974 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002975
Tim Northover3b0846e2014-05-24 12:50:23 +00002976 int64_t PrevReg = FirstReg;
2977 unsigned Count = 1;
2978
Nirav Davee833c6c2016-11-08 18:31:04 +00002979 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002980 SMLoc Loc = getLoc();
2981 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002982
Sander de Smalen50d87022018-04-19 07:35:08 +00002983 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002984 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2985 if (ParseRes != MatchOperand_Success)
2986 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002987
Tim Northover3b0846e2014-05-24 12:50:23 +00002988 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002989 if (Kind != NextKind) {
2990 Error(Loc, "mismatched register size suffix");
2991 return MatchOperand_ParseFail;
2992 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002993
2994 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2995
2996 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002997 Error(Loc, "invalid number of vectors");
2998 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002999 }
3000
3001 Count += Space;
3002 }
3003 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003004 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003005 SMLoc Loc = getLoc();
3006 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003007 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003008 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3009 if (ParseRes != MatchOperand_Success)
3010 return ParseRes;
3011
Tim Northover3b0846e2014-05-24 12:50:23 +00003012 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003013 if (Kind != NextKind) {
3014 Error(Loc, "mismatched register size suffix");
3015 return MatchOperand_ParseFail;
3016 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003017
3018 // Registers must be incremental (with wraparound at 31)
3019 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003020 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3021 Error(Loc, "registers must be sequential");
3022 return MatchOperand_ParseFail;
3023 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003024
3025 PrevReg = Reg;
3026 ++Count;
3027 }
3028 }
3029
Nirav Davee833c6c2016-11-08 18:31:04 +00003030 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003031 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003032
Sander de Smalen650234b2018-04-12 11:40:52 +00003033 if (Count > 4) {
3034 Error(S, "invalid number of vectors");
3035 return MatchOperand_ParseFail;
3036 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003037
3038 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003039 unsigned ElementWidth = 0;
3040 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003041 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003042 std::tie(NumElements, ElementWidth) = *VK;
3043 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003044
3045 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003046 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3047 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003048
Sander de Smalen650234b2018-04-12 11:40:52 +00003049 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003050}
3051
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003052/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3053bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003054 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3055 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003056 return true;
3057
3058 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3059}
3060
Alex Bradbury58eba092016-11-01 16:32:05 +00003061OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003062AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003063 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003064
Sander de Smalen50d87022018-04-19 07:35:08 +00003065 unsigned RegNum;
3066 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3067 if (Res != MatchOperand_Success)
3068 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003069
Nirav Davee833c6c2016-11-08 18:31:04 +00003070 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003071 Operands.push_back(AArch64Operand::CreateReg(
3072 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003073 return MatchOperand_Success;
3074 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003075
Nirav Davee833c6c2016-11-08 18:31:04 +00003076 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003077
Sander de Smalen50d87022018-04-19 07:35:08 +00003078 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003079 Error(getLoc(), "index must be absent or #0");
3080 return MatchOperand_ParseFail;
3081 }
3082
3083 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003084 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003085 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3086 Error(getLoc(), "index must be absent or #0");
3087 return MatchOperand_ParseFail;
3088 }
3089
Sander de Smalen50d87022018-04-19 07:35:08 +00003090 Operands.push_back(AArch64Operand::CreateReg(
3091 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003092 return MatchOperand_Success;
3093}
3094
Sander de Smalen149916d2018-04-20 07:24:20 +00003095template <bool ParseShiftExtend>
3096OperandMatchResultTy
3097AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3098 SMLoc StartLoc = getLoc();
3099
3100 unsigned RegNum;
3101 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3102 if (Res != MatchOperand_Success)
3103 return Res;
3104
3105 // No shift/extend is the default.
3106 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3107 Operands.push_back(AArch64Operand::CreateReg(
3108 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
3109 return MatchOperand_Success;
3110 }
3111
3112 // Eat the comma
3113 getParser().Lex();
3114
3115 // Match the shift
3116 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3117 Res = tryParseOptionalShiftExtend(ExtOpnd);
3118 if (Res != MatchOperand_Success)
3119 return Res;
3120
3121 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
3122 Operands.push_back(AArch64Operand::CreateReg(RegNum, RegKind::Scalar,
3123 StartLoc, Ext->getEndLoc(), getContext(),
3124 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3125 Ext->hasShiftExtendAmount()));
3126
3127 return MatchOperand_Success;
3128}
3129
Sander de Smalen5c625982018-04-13 12:56:14 +00003130bool AArch64AsmParser::parseOptionalMulVl(OperandVector &Operands) {
3131 MCAsmParser &Parser = getParser();
3132
3133 // Some SVE instructions have a decoration after the immediate, i.e.
3134 // "mul vl". We parse them here and add tokens, which must be present in the
3135 // asm string in the tablegen instruction.
3136 if (!Parser.getTok().getString().equals_lower("mul") ||
3137 !Parser.getLexer().peekTok().getString().equals_lower("vl"))
3138 return true;
3139
3140 SMLoc S = getLoc();
3141 Operands.push_back(
3142 AArch64Operand::CreateToken("mul", false, S, getContext()));
3143 Parser.Lex(); // Eat the "mul"
3144
3145 S = getLoc();
3146 Operands.push_back(
3147 AArch64Operand::CreateToken("vl", false, S, getContext()));
3148 Parser.Lex(); // Eat the "vl"
3149
3150 return false;
3151}
3152
Tim Northover3b0846e2014-05-24 12:50:23 +00003153/// parseOperand - Parse a arm instruction operand. For now this parses the
3154/// operand regardless of the mnemonic.
3155bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3156 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003157 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003158
3159 OperandMatchResultTy ResTy =
3160 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3161
Tim Northover3b0846e2014-05-24 12:50:23 +00003162 // Check if the current operand has a custom associated parser, if so, try to
3163 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003164 if (ResTy == MatchOperand_Success)
3165 return false;
3166 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3167 // there was a match, but an error occurred, in which case, just return that
3168 // the operand parsing failed.
3169 if (ResTy == MatchOperand_ParseFail)
3170 return true;
3171
3172 // Nothing custom, so do general case parsing.
3173 SMLoc S, E;
3174 switch (getLexer().getKind()) {
3175 default: {
3176 SMLoc S = getLoc();
3177 const MCExpr *Expr;
3178 if (parseSymbolicImmVal(Expr))
3179 return Error(S, "invalid operand");
3180
3181 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3182 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3183 return false;
3184 }
3185 case AsmToken::LBrac: {
3186 SMLoc Loc = Parser.getTok().getLoc();
3187 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3188 getContext()));
3189 Parser.Lex(); // Eat '['
3190
3191 // There's no comma after a '[', so we can parse the next operand
3192 // immediately.
3193 return parseOperand(Operands, false, false);
3194 }
3195 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003196 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003197 case AsmToken::Identifier: {
3198 // If we're expecting a Condition Code operand, then just parse that.
3199 if (isCondCode)
3200 return parseCondCode(Operands, invertCondCode);
3201
3202 // If it's a register name, parse it.
3203 if (!parseRegister(Operands))
3204 return false;
3205
Sander de Smalen5c625982018-04-13 12:56:14 +00003206 // See if this is a "mul vl" decoration used by SVE instructions.
3207 if (!parseOptionalMulVl(Operands))
3208 return false;
3209
Tim Northover3b0846e2014-05-24 12:50:23 +00003210 // This could be an optional "shift" or "extend" operand.
3211 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3212 // We can only continue if no tokens were eaten.
3213 if (GotShift != MatchOperand_NoMatch)
3214 return GotShift;
3215
3216 // This was not a register so parse other operands that start with an
3217 // identifier (like labels) as expressions and create them as immediates.
3218 const MCExpr *IdVal;
3219 S = getLoc();
3220 if (getParser().parseExpression(IdVal))
3221 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003222 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3223 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3224 return false;
3225 }
3226 case AsmToken::Integer:
3227 case AsmToken::Real:
3228 case AsmToken::Hash: {
3229 // #42 -> immediate.
3230 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003231
3232 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003233
3234 // Parse a negative sign
3235 bool isNegative = false;
3236 if (Parser.getTok().is(AsmToken::Minus)) {
3237 isNegative = true;
3238 // We need to consume this token only when we have a Real, otherwise
3239 // we let parseSymbolicImmVal take care of it
3240 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3241 Parser.Lex();
3242 }
3243
3244 // The only Real that should come through here is a literal #0.0 for
3245 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3246 // so convert the value.
3247 const AsmToken &Tok = Parser.getTok();
3248 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003249 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003250 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3251 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3252 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3253 Mnemonic != "fcmlt")
3254 return TokError("unexpected floating point literal");
3255 else if (IntVal != 0 || isNegative)
3256 return TokError("expected floating-point constant #0.0");
3257 Parser.Lex(); // Eat the token.
3258
3259 Operands.push_back(
3260 AArch64Operand::CreateToken("#0", false, S, getContext()));
3261 Operands.push_back(
3262 AArch64Operand::CreateToken(".0", false, S, getContext()));
3263 return false;
3264 }
3265
3266 const MCExpr *ImmVal;
3267 if (parseSymbolicImmVal(ImmVal))
3268 return true;
3269
3270 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3271 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3272 return false;
3273 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003274 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003275 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003276 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003277 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003278 Parser.Lex(); // Eat '='
3279 const MCExpr *SubExprVal;
3280 if (getParser().parseExpression(SubExprVal))
3281 return true;
3282
David Peixottoae5ba762014-07-18 16:05:14 +00003283 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003284 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003285 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003286
3287 bool IsXReg =
3288 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3289 Operands[1]->getReg());
3290
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003291 MCContext& Ctx = getContext();
3292 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3293 // 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 +00003294 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003295 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3296 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3297 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3298 ShiftAmt += 16;
3299 Imm >>= 16;
3300 }
3301 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3302 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3303 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003304 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003305 if (ShiftAmt)
3306 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3307 ShiftAmt, true, S, E, Ctx));
3308 return false;
3309 }
David Peixottoae5ba762014-07-18 16:05:14 +00003310 APInt Simm = APInt(64, Imm << ShiftAmt);
3311 // check if the immediate is an unsigned or signed 32-bit int for W regs
3312 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3313 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003314 }
3315 // 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 +00003316 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003317 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003318 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3319 return false;
3320 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003321 }
3322}
3323
3324/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3325/// operands.
3326bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3327 StringRef Name, SMLoc NameLoc,
3328 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003329 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003330 Name = StringSwitch<StringRef>(Name.lower())
3331 .Case("beq", "b.eq")
3332 .Case("bne", "b.ne")
3333 .Case("bhs", "b.hs")
3334 .Case("bcs", "b.cs")
3335 .Case("blo", "b.lo")
3336 .Case("bcc", "b.cc")
3337 .Case("bmi", "b.mi")
3338 .Case("bpl", "b.pl")
3339 .Case("bvs", "b.vs")
3340 .Case("bvc", "b.vc")
3341 .Case("bhi", "b.hi")
3342 .Case("bls", "b.ls")
3343 .Case("bge", "b.ge")
3344 .Case("blt", "b.lt")
3345 .Case("bgt", "b.gt")
3346 .Case("ble", "b.le")
3347 .Case("bal", "b.al")
3348 .Case("bnv", "b.nv")
3349 .Default(Name);
3350
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003351 // First check for the AArch64-specific .req directive.
3352 if (Parser.getTok().is(AsmToken::Identifier) &&
3353 Parser.getTok().getIdentifier() == ".req") {
3354 parseDirectiveReq(Name, NameLoc);
3355 // We always return 'error' for this, as we're done with this
3356 // statement and don't need to match the 'instruction."
3357 return true;
3358 }
3359
Tim Northover3b0846e2014-05-24 12:50:23 +00003360 // Create the leading tokens for the mnemonic, split by '.' characters.
3361 size_t Start = 0, Next = Name.find('.');
3362 StringRef Head = Name.slice(Start, Next);
3363
3364 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003365 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3366 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003367
3368 Operands.push_back(
3369 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3370 Mnemonic = Head;
3371
3372 // Handle condition codes for a branch mnemonic
3373 if (Head == "b" && Next != StringRef::npos) {
3374 Start = Next;
3375 Next = Name.find('.', Start + 1);
3376 Head = Name.slice(Start + 1, Next);
3377
3378 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3379 (Head.data() - Name.data()));
3380 AArch64CC::CondCode CC = parseCondCodeString(Head);
3381 if (CC == AArch64CC::Invalid)
3382 return Error(SuffixLoc, "invalid condition code");
3383 Operands.push_back(
3384 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3385 Operands.push_back(
3386 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3387 }
3388
3389 // Add the remaining tokens in the mnemonic.
3390 while (Next != StringRef::npos) {
3391 Start = Next;
3392 Next = Name.find('.', Start + 1);
3393 Head = Name.slice(Start, Next);
3394 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3395 (Head.data() - Name.data()) + 1);
3396 Operands.push_back(
3397 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3398 }
3399
3400 // Conditional compare instructions have a Condition Code operand, which needs
3401 // to be parsed and an immediate operand created.
3402 bool condCodeFourthOperand =
3403 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3404 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3405 Head == "csinc" || Head == "csinv" || Head == "csneg");
3406
3407 // These instructions are aliases to some of the conditional select
3408 // instructions. However, the condition code is inverted in the aliased
3409 // instruction.
3410 //
3411 // FIXME: Is this the correct way to handle these? Or should the parser
3412 // generate the aliased instructions directly?
3413 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3414 bool condCodeThirdOperand =
3415 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3416
3417 // Read the remaining operands.
3418 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3419 // Read the first operand.
3420 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003421 return true;
3422 }
3423
3424 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003425 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003426 // Parse and remember the operand.
3427 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3428 (N == 3 && condCodeThirdOperand) ||
3429 (N == 2 && condCodeSecondOperand),
3430 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003431 return true;
3432 }
3433
3434 // After successfully parsing some operands there are two special cases to
3435 // consider (i.e. notional operands not separated by commas). Both are due
3436 // to memory specifiers:
3437 // + An RBrac will end an address for load/store/prefetch
3438 // + An '!' will indicate a pre-indexed operation.
3439 //
3440 // It's someone else's responsibility to make sure these tokens are sane
3441 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003442
Nirav Davee833c6c2016-11-08 18:31:04 +00003443 SMLoc RLoc = Parser.getTok().getLoc();
3444 if (parseOptionalToken(AsmToken::RBrac))
3445 Operands.push_back(
3446 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3447 SMLoc ELoc = Parser.getTok().getLoc();
3448 if (parseOptionalToken(AsmToken::Exclaim))
3449 Operands.push_back(
3450 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003451
3452 ++N;
3453 }
3454 }
3455
Nirav Davee833c6c2016-11-08 18:31:04 +00003456 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3457 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003458
Tim Northover3b0846e2014-05-24 12:50:23 +00003459 return false;
3460}
3461
3462// FIXME: This entire function is a giant hack to provide us with decent
3463// operand range validation/diagnostics until TableGen/MC can be extended
3464// to support autogeneration of this kind of validation.
3465bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3466 SmallVectorImpl<SMLoc> &Loc) {
3467 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3468 // Check for indexed addressing modes w/ the base register being the
3469 // same as a destination/source register or pair load where
3470 // the Rt == Rt2. All of those are undefined behaviour.
3471 switch (Inst.getOpcode()) {
3472 case AArch64::LDPSWpre:
3473 case AArch64::LDPWpost:
3474 case AArch64::LDPWpre:
3475 case AArch64::LDPXpost:
3476 case AArch64::LDPXpre: {
3477 unsigned Rt = Inst.getOperand(1).getReg();
3478 unsigned Rt2 = Inst.getOperand(2).getReg();
3479 unsigned Rn = Inst.getOperand(3).getReg();
3480 if (RI->isSubRegisterEq(Rn, Rt))
3481 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3482 "is also a destination");
3483 if (RI->isSubRegisterEq(Rn, Rt2))
3484 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3485 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003486 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003487 }
3488 case AArch64::LDPDi:
3489 case AArch64::LDPQi:
3490 case AArch64::LDPSi:
3491 case AArch64::LDPSWi:
3492 case AArch64::LDPWi:
3493 case AArch64::LDPXi: {
3494 unsigned Rt = Inst.getOperand(0).getReg();
3495 unsigned Rt2 = Inst.getOperand(1).getReg();
3496 if (Rt == Rt2)
3497 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3498 break;
3499 }
3500 case AArch64::LDPDpost:
3501 case AArch64::LDPDpre:
3502 case AArch64::LDPQpost:
3503 case AArch64::LDPQpre:
3504 case AArch64::LDPSpost:
3505 case AArch64::LDPSpre:
3506 case AArch64::LDPSWpost: {
3507 unsigned Rt = Inst.getOperand(1).getReg();
3508 unsigned Rt2 = Inst.getOperand(2).getReg();
3509 if (Rt == Rt2)
3510 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3511 break;
3512 }
3513 case AArch64::STPDpost:
3514 case AArch64::STPDpre:
3515 case AArch64::STPQpost:
3516 case AArch64::STPQpre:
3517 case AArch64::STPSpost:
3518 case AArch64::STPSpre:
3519 case AArch64::STPWpost:
3520 case AArch64::STPWpre:
3521 case AArch64::STPXpost:
3522 case AArch64::STPXpre: {
3523 unsigned Rt = Inst.getOperand(1).getReg();
3524 unsigned Rt2 = Inst.getOperand(2).getReg();
3525 unsigned Rn = Inst.getOperand(3).getReg();
3526 if (RI->isSubRegisterEq(Rn, Rt))
3527 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3528 "is also a source");
3529 if (RI->isSubRegisterEq(Rn, Rt2))
3530 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3531 "is also a source");
3532 break;
3533 }
3534 case AArch64::LDRBBpre:
3535 case AArch64::LDRBpre:
3536 case AArch64::LDRHHpre:
3537 case AArch64::LDRHpre:
3538 case AArch64::LDRSBWpre:
3539 case AArch64::LDRSBXpre:
3540 case AArch64::LDRSHWpre:
3541 case AArch64::LDRSHXpre:
3542 case AArch64::LDRSWpre:
3543 case AArch64::LDRWpre:
3544 case AArch64::LDRXpre:
3545 case AArch64::LDRBBpost:
3546 case AArch64::LDRBpost:
3547 case AArch64::LDRHHpost:
3548 case AArch64::LDRHpost:
3549 case AArch64::LDRSBWpost:
3550 case AArch64::LDRSBXpost:
3551 case AArch64::LDRSHWpost:
3552 case AArch64::LDRSHXpost:
3553 case AArch64::LDRSWpost:
3554 case AArch64::LDRWpost:
3555 case AArch64::LDRXpost: {
3556 unsigned Rt = Inst.getOperand(1).getReg();
3557 unsigned Rn = Inst.getOperand(2).getReg();
3558 if (RI->isSubRegisterEq(Rn, Rt))
3559 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3560 "is also a source");
3561 break;
3562 }
3563 case AArch64::STRBBpost:
3564 case AArch64::STRBpost:
3565 case AArch64::STRHHpost:
3566 case AArch64::STRHpost:
3567 case AArch64::STRWpost:
3568 case AArch64::STRXpost:
3569 case AArch64::STRBBpre:
3570 case AArch64::STRBpre:
3571 case AArch64::STRHHpre:
3572 case AArch64::STRHpre:
3573 case AArch64::STRWpre:
3574 case AArch64::STRXpre: {
3575 unsigned Rt = Inst.getOperand(1).getReg();
3576 unsigned Rn = Inst.getOperand(2).getReg();
3577 if (RI->isSubRegisterEq(Rn, Rt))
3578 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3579 "is also a source");
3580 break;
3581 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003582 case AArch64::STXRB:
3583 case AArch64::STXRH:
3584 case AArch64::STXRW:
3585 case AArch64::STXRX:
3586 case AArch64::STLXRB:
3587 case AArch64::STLXRH:
3588 case AArch64::STLXRW:
3589 case AArch64::STLXRX: {
3590 unsigned Rs = Inst.getOperand(0).getReg();
3591 unsigned Rt = Inst.getOperand(1).getReg();
3592 unsigned Rn = Inst.getOperand(2).getReg();
3593 if (RI->isSubRegisterEq(Rt, Rs) ||
3594 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3595 return Error(Loc[0],
3596 "unpredictable STXR instruction, status is also a source");
3597 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003598 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003599 case AArch64::STXPW:
3600 case AArch64::STXPX:
3601 case AArch64::STLXPW:
3602 case AArch64::STLXPX: {
3603 unsigned Rs = Inst.getOperand(0).getReg();
3604 unsigned Rt1 = Inst.getOperand(1).getReg();
3605 unsigned Rt2 = Inst.getOperand(2).getReg();
3606 unsigned Rn = Inst.getOperand(3).getReg();
3607 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3608 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3609 return Error(Loc[0],
3610 "unpredictable STXP instruction, status is also a source");
3611 break;
3612 }
3613 }
3614
Tim Northover3b0846e2014-05-24 12:50:23 +00003615
3616 // Now check immediate ranges. Separate from the above as there is overlap
3617 // in the instructions being checked and this keeps the nested conditionals
3618 // to a minimum.
3619 switch (Inst.getOpcode()) {
3620 case AArch64::ADDSWri:
3621 case AArch64::ADDSXri:
3622 case AArch64::ADDWri:
3623 case AArch64::ADDXri:
3624 case AArch64::SUBSWri:
3625 case AArch64::SUBSXri:
3626 case AArch64::SUBWri:
3627 case AArch64::SUBXri: {
3628 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3629 // some slight duplication here.
3630 if (Inst.getOperand(2).isExpr()) {
3631 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3632 AArch64MCExpr::VariantKind ELFRefKind;
3633 MCSymbolRefExpr::VariantKind DarwinRefKind;
3634 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003635 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3636
3637 // Only allow these with ADDXri.
3638 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3639 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3640 Inst.getOpcode() == AArch64::ADDXri)
3641 return false;
3642
3643 // Only allow these with ADDXri/ADDWri
3644 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3645 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3646 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3647 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3648 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3649 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3650 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003651 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3652 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3653 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003654 (Inst.getOpcode() == AArch64::ADDXri ||
3655 Inst.getOpcode() == AArch64::ADDWri))
3656 return false;
3657
3658 // Don't allow symbol refs in the immediate field otherwise
3659 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3660 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3661 // 'cmp w0, 'borked')
3662 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003663 }
Diana Picusc93518d2016-10-11 09:17:47 +00003664 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003665 }
3666 return false;
3667 }
3668 default:
3669 return false;
3670 }
3671}
3672
Craig Topper05515562017-10-26 06:46:41 +00003673static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3674 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003675
3676bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3677 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003678 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003679 case Match_InvalidTiedOperand:
3680 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003681 case Match_MissingFeature:
3682 return Error(Loc,
3683 "instruction requires a CPU feature not currently enabled");
3684 case Match_InvalidOperand:
3685 return Error(Loc, "invalid operand for instruction");
3686 case Match_InvalidSuffix:
3687 return Error(Loc, "invalid type suffix for instruction");
3688 case Match_InvalidCondCode:
3689 return Error(Loc, "expected AArch64 condition code");
3690 case Match_AddSubRegExtendSmall:
3691 return Error(Loc,
3692 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3693 case Match_AddSubRegExtendLarge:
3694 return Error(Loc,
3695 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3696 case Match_AddSubSecondSource:
3697 return Error(Loc,
3698 "expected compatible register, symbol or integer in range [0, 4095]");
3699 case Match_LogicalSecondSource:
3700 return Error(Loc, "expected compatible register or logical immediate");
3701 case Match_InvalidMovImm32Shift:
3702 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3703 case Match_InvalidMovImm64Shift:
3704 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3705 case Match_AddSubRegShift32:
3706 return Error(Loc,
3707 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3708 case Match_AddSubRegShift64:
3709 return Error(Loc,
3710 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3711 case Match_InvalidFPImm:
3712 return Error(Loc,
3713 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003714 case Match_InvalidMemoryIndexedSImm6:
3715 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003716 case Match_InvalidMemoryIndexedSImm5:
3717 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003718 case Match_InvalidMemoryIndexed1SImm4:
3719 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003720 case Match_InvalidMemoryIndexed2SImm4:
3721 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003722 case Match_InvalidMemoryIndexed3SImm4:
3723 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003724 case Match_InvalidMemoryIndexed4SImm4:
3725 return Error(Loc, "index must be a multiple of 3 in range [-32, 28].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003726 case Match_InvalidMemoryIndexedSImm9:
3727 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003728 case Match_InvalidMemoryIndexedSImm10:
3729 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003730 case Match_InvalidMemoryIndexed4SImm7:
3731 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3732 case Match_InvalidMemoryIndexed8SImm7:
3733 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3734 case Match_InvalidMemoryIndexed16SImm7:
3735 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3736 case Match_InvalidMemoryWExtend8:
3737 return Error(Loc,
3738 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3739 case Match_InvalidMemoryWExtend16:
3740 return Error(Loc,
3741 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3742 case Match_InvalidMemoryWExtend32:
3743 return Error(Loc,
3744 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3745 case Match_InvalidMemoryWExtend64:
3746 return Error(Loc,
3747 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3748 case Match_InvalidMemoryWExtend128:
3749 return Error(Loc,
3750 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3751 case Match_InvalidMemoryXExtend8:
3752 return Error(Loc,
3753 "expected 'lsl' or 'sxtx' with optional shift of #0");
3754 case Match_InvalidMemoryXExtend16:
3755 return Error(Loc,
3756 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3757 case Match_InvalidMemoryXExtend32:
3758 return Error(Loc,
3759 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3760 case Match_InvalidMemoryXExtend64:
3761 return Error(Loc,
3762 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3763 case Match_InvalidMemoryXExtend128:
3764 return Error(Loc,
3765 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3766 case Match_InvalidMemoryIndexed1:
3767 return Error(Loc, "index must be an integer in range [0, 4095].");
3768 case Match_InvalidMemoryIndexed2:
3769 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3770 case Match_InvalidMemoryIndexed4:
3771 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3772 case Match_InvalidMemoryIndexed8:
3773 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3774 case Match_InvalidMemoryIndexed16:
3775 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003776 case Match_InvalidImm0_1:
3777 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003778 case Match_InvalidImm0_7:
3779 return Error(Loc, "immediate must be an integer in range [0, 7].");
3780 case Match_InvalidImm0_15:
3781 return Error(Loc, "immediate must be an integer in range [0, 15].");
3782 case Match_InvalidImm0_31:
3783 return Error(Loc, "immediate must be an integer in range [0, 31].");
3784 case Match_InvalidImm0_63:
3785 return Error(Loc, "immediate must be an integer in range [0, 63].");
3786 case Match_InvalidImm0_127:
3787 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003788 case Match_InvalidImm0_255:
3789 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003790 case Match_InvalidImm0_65535:
3791 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3792 case Match_InvalidImm1_8:
3793 return Error(Loc, "immediate must be an integer in range [1, 8].");
3794 case Match_InvalidImm1_16:
3795 return Error(Loc, "immediate must be an integer in range [1, 16].");
3796 case Match_InvalidImm1_32:
3797 return Error(Loc, "immediate must be an integer in range [1, 32].");
3798 case Match_InvalidImm1_64:
3799 return Error(Loc, "immediate must be an integer in range [1, 64].");
3800 case Match_InvalidIndex1:
3801 return Error(Loc, "expected lane specifier '[1]'");
3802 case Match_InvalidIndexB:
3803 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3804 case Match_InvalidIndexH:
3805 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3806 case Match_InvalidIndexS:
3807 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3808 case Match_InvalidIndexD:
3809 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3810 case Match_InvalidLabel:
3811 return Error(Loc, "expected label or encodable integer pc offset");
3812 case Match_MRS:
3813 return Error(Loc, "expected readable system register");
3814 case Match_MSR:
3815 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003816 case Match_InvalidComplexRotationEven:
3817 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3818 case Match_InvalidComplexRotationOdd:
3819 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003820 case Match_MnemonicFail: {
3821 std::string Suggestion = AArch64MnemonicSpellCheck(
3822 ((AArch64Operand &)*Operands[0]).getToken(),
3823 ComputeAvailableFeatures(STI->getFeatureBits()));
3824 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3825 }
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003826 case Match_InvalidSVEPattern:
3827 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003828 case Match_InvalidSVEPredicateAnyReg:
3829 case Match_InvalidSVEPredicateBReg:
3830 case Match_InvalidSVEPredicateHReg:
3831 case Match_InvalidSVEPredicateSReg:
3832 case Match_InvalidSVEPredicateDReg:
3833 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003834 case Match_InvalidSVEPredicate3bAnyReg:
3835 case Match_InvalidSVEPredicate3bBReg:
3836 case Match_InvalidSVEPredicate3bHReg:
3837 case Match_InvalidSVEPredicate3bSReg:
3838 case Match_InvalidSVEPredicate3bDReg:
3839 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003840 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003841 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003842 }
3843}
3844
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003845static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003846
3847bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3848 OperandVector &Operands,
3849 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003850 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003851 bool MatchingInlineAsm) {
3852 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003853 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3854 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003855
David Blaikie960ea3f2014-06-08 16:18:35 +00003856 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003857 unsigned NumOperands = Operands.size();
3858
3859 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003860 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3861 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003862 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003863 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003864 if (Op3CE) {
3865 uint64_t Op3Val = Op3CE->getValue();
3866 uint64_t NewOp3Val = 0;
3867 uint64_t NewOp4Val = 0;
3868 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003869 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003870 NewOp3Val = (32 - Op3Val) & 0x1f;
3871 NewOp4Val = 31 - Op3Val;
3872 } else {
3873 NewOp3Val = (64 - Op3Val) & 0x3f;
3874 NewOp4Val = 63 - Op3Val;
3875 }
3876
Jim Grosbach13760bd2015-05-30 01:25:56 +00003877 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3878 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003879
3880 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003881 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003882 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003883 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3884 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3885 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003886 }
3887 }
Tim Northover03b99f62015-04-30 18:28:58 +00003888 } else if (NumOperands == 4 && Tok == "bfc") {
3889 // FIXME: Horrible hack to handle BFC->BFM alias.
3890 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3891 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3892 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3893
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003894 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003895 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3896 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3897
3898 if (LSBCE && WidthCE) {
3899 uint64_t LSB = LSBCE->getValue();
3900 uint64_t Width = WidthCE->getValue();
3901
3902 uint64_t RegWidth = 0;
3903 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3904 Op1.getReg()))
3905 RegWidth = 64;
3906 else
3907 RegWidth = 32;
3908
3909 if (LSB >= RegWidth)
3910 return Error(LSBOp.getStartLoc(),
3911 "expected integer in range [0, 31]");
3912 if (Width < 1 || Width > RegWidth)
3913 return Error(WidthOp.getStartLoc(),
3914 "expected integer in range [1, 32]");
3915
3916 uint64_t ImmR = 0;
3917 if (RegWidth == 32)
3918 ImmR = (32 - LSB) & 0x1f;
3919 else
3920 ImmR = (64 - LSB) & 0x3f;
3921
3922 uint64_t ImmS = Width - 1;
3923
3924 if (ImmR != 0 && ImmS >= ImmR)
3925 return Error(WidthOp.getStartLoc(),
3926 "requested insert overflows register");
3927
Jim Grosbach13760bd2015-05-30 01:25:56 +00003928 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3929 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003930 Operands[0] = AArch64Operand::CreateToken(
3931 "bfm", false, Op.getStartLoc(), getContext());
3932 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003933 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3934 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003935 Operands[3] = AArch64Operand::CreateImm(
3936 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3937 Operands.emplace_back(
3938 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3939 WidthOp.getEndLoc(), getContext()));
3940 }
3941 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003942 } else if (NumOperands == 5) {
3943 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3944 // UBFIZ -> UBFM aliases.
3945 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003946 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3947 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3948 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003949
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003950 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003951 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3952 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003953
3954 if (Op3CE && Op4CE) {
3955 uint64_t Op3Val = Op3CE->getValue();
3956 uint64_t Op4Val = Op4CE->getValue();
3957
3958 uint64_t RegWidth = 0;
3959 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003960 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003961 RegWidth = 64;
3962 else
3963 RegWidth = 32;
3964
3965 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003966 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003967 "expected integer in range [0, 31]");
3968 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003969 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003970 "expected integer in range [1, 32]");
3971
3972 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003973 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003974 NewOp3Val = (32 - Op3Val) & 0x1f;
3975 else
3976 NewOp3Val = (64 - Op3Val) & 0x3f;
3977
3978 uint64_t NewOp4Val = Op4Val - 1;
3979
3980 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003981 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003982 "requested insert overflows register");
3983
3984 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003985 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003986 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003987 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003988 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003989 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003990 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003991 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003992 if (Tok == "bfi")
3993 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003994 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003995 else if (Tok == "sbfiz")
3996 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003997 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003998 else if (Tok == "ubfiz")
3999 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004000 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004001 else
4002 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004003 }
4004 }
4005
4006 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4007 // UBFX -> UBFM aliases.
4008 } else if (NumOperands == 5 &&
4009 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004010 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4011 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4012 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004013
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004014 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004015 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4016 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004017
4018 if (Op3CE && Op4CE) {
4019 uint64_t Op3Val = Op3CE->getValue();
4020 uint64_t Op4Val = Op4CE->getValue();
4021
4022 uint64_t RegWidth = 0;
4023 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004024 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004025 RegWidth = 64;
4026 else
4027 RegWidth = 32;
4028
4029 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004030 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004031 "expected integer in range [0, 31]");
4032 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004033 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004034 "expected integer in range [1, 32]");
4035
4036 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4037
4038 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004039 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004040 "requested extract overflows register");
4041
4042 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004043 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004044 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004045 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004046 if (Tok == "bfxil")
4047 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004048 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004049 else if (Tok == "sbfx")
4050 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004051 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004052 else if (Tok == "ubfx")
4053 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004054 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004055 else
4056 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004057 }
4058 }
4059 }
4060 }
Tim Northover9097a072017-12-18 10:36:00 +00004061
4062 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4063 // instruction for FP registers correctly in some rare circumstances. Convert
4064 // it to a safe instruction and warn (because silently changing someone's
4065 // assembly is rude).
4066 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4067 NumOperands == 4 && Tok == "movi") {
4068 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4069 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4070 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4071 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4072 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4073 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4074 if (Suffix.lower() == ".2d" &&
4075 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4076 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4077 " correctly on this CPU, converting to equivalent movi.16b");
4078 // Switch the suffix to .16b.
4079 unsigned Idx = Op1.isToken() ? 1 : 2;
4080 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4081 getContext());
4082 }
4083 }
4084 }
4085
Tim Northover3b0846e2014-05-24 12:50:23 +00004086 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4087 // InstAlias can't quite handle this since the reg classes aren't
4088 // subclasses.
4089 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4090 // The source register can be Wn here, but the matcher expects a
4091 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004092 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004093 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004094 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004095 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4096 Op.getStartLoc(), Op.getEndLoc(),
4097 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004098 }
4099 }
4100 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4101 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004102 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004103 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004104 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004105 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004106 // The source register can be Wn here, but the matcher expects a
4107 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004108 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004109 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004110 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004111 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4112 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004113 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004114 }
4115 }
4116 }
4117 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4118 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004119 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004120 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004121 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004122 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004123 // The source register can be Wn here, but the matcher expects a
4124 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004125 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004126 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004127 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004128 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4129 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004130 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004131 }
4132 }
4133 }
4134
Tim Northover3b0846e2014-05-24 12:50:23 +00004135 MCInst Inst;
4136 // First try to match against the secondary set of tables containing the
4137 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4138 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004139 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004140
4141 // If that fails, try against the alternate table containing long-form NEON:
4142 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004143 if (MatchResult != Match_Success) {
4144 // But first, save the short-form match result: we can use it in case the
4145 // long-form match also fails.
4146 auto ShortFormNEONErrorInfo = ErrorInfo;
4147 auto ShortFormNEONMatchResult = MatchResult;
4148
Tim Northover3b0846e2014-05-24 12:50:23 +00004149 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004150 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004151
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004152 // Now, both matches failed, and the long-form match failed on the mnemonic
4153 // suffix token operand. The short-form match failure is probably more
4154 // relevant: use it instead.
4155 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004156 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004157 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4158 MatchResult = ShortFormNEONMatchResult;
4159 ErrorInfo = ShortFormNEONErrorInfo;
4160 }
4161 }
4162
Tim Northover3b0846e2014-05-24 12:50:23 +00004163 switch (MatchResult) {
4164 case Match_Success: {
4165 // Perform range checking and other semantic validations
4166 SmallVector<SMLoc, 8> OperandLocs;
4167 NumOperands = Operands.size();
4168 for (unsigned i = 1; i < NumOperands; ++i)
4169 OperandLocs.push_back(Operands[i]->getStartLoc());
4170 if (validateInstruction(Inst, OperandLocs))
4171 return true;
4172
4173 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004174 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004175 return false;
4176 }
4177 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004178 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004179 // Special case the error message for the very common case where only
4180 // a single subtarget feature is missing (neon, e.g.).
4181 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004182 uint64_t Mask = 1;
4183 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4184 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004185 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004186 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004187 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004188 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004189 }
4190 return Error(IDLoc, Msg);
4191 }
4192 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004193 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004194 case Match_InvalidOperand: {
4195 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004196
Tim Northover26bb14e2014-08-18 11:49:42 +00004197 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004198 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004199 return Error(IDLoc, "too few operands for instruction",
4200 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004201
David Blaikie960ea3f2014-06-08 16:18:35 +00004202 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004203 if (ErrorLoc == SMLoc())
4204 ErrorLoc = IDLoc;
4205 }
4206 // If the match failed on a suffix token operand, tweak the diagnostic
4207 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004208 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4209 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004210 MatchResult = Match_InvalidSuffix;
4211
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004212 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004213 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004214 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004215 case Match_InvalidMemoryIndexed1:
4216 case Match_InvalidMemoryIndexed2:
4217 case Match_InvalidMemoryIndexed4:
4218 case Match_InvalidMemoryIndexed8:
4219 case Match_InvalidMemoryIndexed16:
4220 case Match_InvalidCondCode:
4221 case Match_AddSubRegExtendSmall:
4222 case Match_AddSubRegExtendLarge:
4223 case Match_AddSubSecondSource:
4224 case Match_LogicalSecondSource:
4225 case Match_AddSubRegShift32:
4226 case Match_AddSubRegShift64:
4227 case Match_InvalidMovImm32Shift:
4228 case Match_InvalidMovImm64Shift:
4229 case Match_InvalidFPImm:
4230 case Match_InvalidMemoryWExtend8:
4231 case Match_InvalidMemoryWExtend16:
4232 case Match_InvalidMemoryWExtend32:
4233 case Match_InvalidMemoryWExtend64:
4234 case Match_InvalidMemoryWExtend128:
4235 case Match_InvalidMemoryXExtend8:
4236 case Match_InvalidMemoryXExtend16:
4237 case Match_InvalidMemoryXExtend32:
4238 case Match_InvalidMemoryXExtend64:
4239 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004240 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004241 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004242 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004243 case Match_InvalidMemoryIndexed4SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004244 case Match_InvalidMemoryIndexed4SImm7:
4245 case Match_InvalidMemoryIndexed8SImm7:
4246 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen5c625982018-04-13 12:56:14 +00004247 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004248 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004249 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004250 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004251 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004252 case Match_InvalidImm0_7:
4253 case Match_InvalidImm0_15:
4254 case Match_InvalidImm0_31:
4255 case Match_InvalidImm0_63:
4256 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004257 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004258 case Match_InvalidImm0_65535:
4259 case Match_InvalidImm1_8:
4260 case Match_InvalidImm1_16:
4261 case Match_InvalidImm1_32:
4262 case Match_InvalidImm1_64:
4263 case Match_InvalidIndex1:
4264 case Match_InvalidIndexB:
4265 case Match_InvalidIndexH:
4266 case Match_InvalidIndexS:
4267 case Match_InvalidIndexD:
4268 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004269 case Match_InvalidComplexRotationEven:
4270 case Match_InvalidComplexRotationOdd:
Sander de Smalencd6be962017-12-20 11:02:42 +00004271 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004272 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004273 case Match_InvalidSVEPredicateBReg:
4274 case Match_InvalidSVEPredicateHReg:
4275 case Match_InvalidSVEPredicateSReg:
4276 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004277 case Match_InvalidSVEPredicate3bAnyReg:
4278 case Match_InvalidSVEPredicate3bBReg:
4279 case Match_InvalidSVEPredicate3bHReg:
4280 case Match_InvalidSVEPredicate3bSReg:
4281 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004282 case Match_MSR:
4283 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004284 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004285 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004286 // Any time we get here, there's nothing fancy to do. Just get the
4287 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004288 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004289 if (ErrorLoc == SMLoc())
4290 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004291 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004292 }
4293 }
4294
4295 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004296}
4297
4298/// ParseDirective parses the arm specific directives
4299bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004300 const MCObjectFileInfo::Environment Format =
4301 getContext().getObjectFileInfo()->getObjectFileType();
4302 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4303 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004304
Tim Northover3b0846e2014-05-24 12:50:23 +00004305 StringRef IDVal = DirectiveID.getIdentifier();
4306 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004307 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004308 parseDirectiveArch(Loc);
4309 else if (IDVal == ".cpu")
4310 parseDirectiveCPU(Loc);
4311 else if (IDVal == ".hword")
4312 parseDirectiveWord(2, Loc);
4313 else if (IDVal == ".word")
4314 parseDirectiveWord(4, Loc);
4315 else if (IDVal == ".xword")
4316 parseDirectiveWord(8, Loc);
4317 else if (IDVal == ".tlsdesccall")
4318 parseDirectiveTLSDescCall(Loc);
4319 else if (IDVal == ".ltorg" || IDVal == ".pool")
4320 parseDirectiveLtorg(Loc);
4321 else if (IDVal == ".unreq")
4322 parseDirectiveUnreq(Loc);
4323 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004324 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004325 parseDirectiveInst(Loc);
4326 else
4327 return true;
4328 } else if (IDVal == MCLOHDirectiveName())
4329 parseDirectiveLOH(IDVal, Loc);
4330 else
4331 return true;
4332 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004333}
4334
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004335static const struct {
4336 const char *Name;
4337 const FeatureBitset Features;
4338} ExtensionMap[] = {
4339 { "crc", {AArch64::FeatureCRC} },
4340 { "crypto", {AArch64::FeatureCrypto} },
4341 { "fp", {AArch64::FeatureFPARMv8} },
4342 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004343 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004344 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004345
4346 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004347 { "pan", {} },
4348 { "lor", {} },
4349 { "rdma", {} },
4350 { "profile", {} },
4351};
4352
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004353/// parseDirectiveArch
4354/// ::= .arch token
4355bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4356 SMLoc ArchLoc = getLoc();
4357
4358 StringRef Arch, ExtensionString;
4359 std::tie(Arch, ExtensionString) =
4360 getParser().parseStringToEndOfStatement().trim().split('+');
4361
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004362 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4363 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004364 return Error(ArchLoc, "unknown arch name");
4365
4366 if (parseToken(AsmToken::EndOfStatement))
4367 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004368
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004369 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004370 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004371 AArch64::getArchFeatures(ID, AArch64Features);
4372 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4373 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004374
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004375 MCSubtargetInfo &STI = copySTI();
4376 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4377 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4378
4379 SmallVector<StringRef, 4> RequestedExtensions;
4380 if (!ExtensionString.empty())
4381 ExtensionString.split(RequestedExtensions, '+');
4382
4383 FeatureBitset Features = STI.getFeatureBits();
4384 for (auto Name : RequestedExtensions) {
4385 bool EnableFeature = true;
4386
4387 if (Name.startswith_lower("no")) {
4388 EnableFeature = false;
4389 Name = Name.substr(2);
4390 }
4391
4392 for (const auto &Extension : ExtensionMap) {
4393 if (Extension.Name != Name)
4394 continue;
4395
4396 if (Extension.Features.none())
4397 report_fatal_error("unsupported architectural extension: " + Name);
4398
4399 FeatureBitset ToggleFeatures = EnableFeature
4400 ? (~Features & Extension.Features)
4401 : ( Features & Extension.Features);
4402 uint64_t Features =
4403 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4404 setAvailableFeatures(Features);
4405 break;
4406 }
4407 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004408 return false;
4409}
4410
Tim Northover8b96c7e2017-05-15 19:42:15 +00004411static SMLoc incrementLoc(SMLoc L, int Offset) {
4412 return SMLoc::getFromPointer(L.getPointer() + Offset);
4413}
4414
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004415/// parseDirectiveCPU
4416/// ::= .cpu id
4417bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004418 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004419
4420 StringRef CPU, ExtensionString;
4421 std::tie(CPU, ExtensionString) =
4422 getParser().parseStringToEndOfStatement().trim().split('+');
4423
Nirav Davee833c6c2016-11-08 18:31:04 +00004424 if (parseToken(AsmToken::EndOfStatement))
4425 return true;
4426
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004427 SmallVector<StringRef, 4> RequestedExtensions;
4428 if (!ExtensionString.empty())
4429 ExtensionString.split(RequestedExtensions, '+');
4430
4431 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4432 // once that is tablegen'ed
4433 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004434 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004435 return false;
4436 }
4437
4438 MCSubtargetInfo &STI = copySTI();
4439 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004440 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004441
4442 FeatureBitset Features = STI.getFeatureBits();
4443 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004444 // Advance source location past '+'.
4445 CurLoc = incrementLoc(CurLoc, 1);
4446
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004447 bool EnableFeature = true;
4448
4449 if (Name.startswith_lower("no")) {
4450 EnableFeature = false;
4451 Name = Name.substr(2);
4452 }
4453
Tim Northover8b96c7e2017-05-15 19:42:15 +00004454 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004455 for (const auto &Extension : ExtensionMap) {
4456 if (Extension.Name != Name)
4457 continue;
4458
4459 if (Extension.Features.none())
4460 report_fatal_error("unsupported architectural extension: " + Name);
4461
4462 FeatureBitset ToggleFeatures = EnableFeature
4463 ? (~Features & Extension.Features)
4464 : ( Features & Extension.Features);
4465 uint64_t Features =
4466 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4467 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004468 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004469
4470 break;
4471 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004472
4473 if (!FoundExtension)
4474 Error(CurLoc, "unsupported architectural extension");
4475
4476 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004477 }
4478 return false;
4479}
4480
Tim Northover3b0846e2014-05-24 12:50:23 +00004481/// parseDirectiveWord
4482/// ::= .word [ expression (, expression)* ]
4483bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004484 auto parseOp = [&]() -> bool {
4485 const MCExpr *Value;
4486 if (getParser().parseExpression(Value))
4487 return true;
4488 getParser().getStreamer().EmitValue(Value, Size, L);
4489 return false;
4490 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004491
Nirav Davee833c6c2016-11-08 18:31:04 +00004492 if (parseMany(parseOp))
4493 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004494 return false;
4495}
4496
Chad Rosierdcd2a302014-10-22 20:35:57 +00004497/// parseDirectiveInst
4498/// ::= .inst opcode [, ...]
4499bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004500 if (getLexer().is(AsmToken::EndOfStatement))
4501 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004502
Nirav Davee833c6c2016-11-08 18:31:04 +00004503 auto parseOp = [&]() -> bool {
4504 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004505 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004506 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4507 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004508 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004509 if (check(!Value, L, "expected constant expression"))
4510 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004511 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004512 return false;
4513 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004514
Nirav Davee833c6c2016-11-08 18:31:04 +00004515 if (parseMany(parseOp))
4516 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004517 return false;
4518}
4519
Tim Northover3b0846e2014-05-24 12:50:23 +00004520// parseDirectiveTLSDescCall:
4521// ::= .tlsdesccall symbol
4522bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4523 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004524 if (check(getParser().parseIdentifier(Name), L,
4525 "expected symbol after directive") ||
4526 parseToken(AsmToken::EndOfStatement))
4527 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004528
Jim Grosbach6f482002015-05-18 18:43:14 +00004529 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004530 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4531 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004532
4533 MCInst Inst;
4534 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004535 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004536
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004537 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004538 return false;
4539}
4540
4541/// ::= .loh <lohName | lohId> label1, ..., labelN
4542/// The number of arguments depends on the loh identifier.
4543bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004544 MCLOHType Kind;
4545 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4546 if (getParser().getTok().isNot(AsmToken::Integer))
4547 return TokError("expected an identifier or a number in directive");
4548 // We successfully get a numeric value for the identifier.
4549 // Check if it is valid.
4550 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004551 if (Id <= -1U && !isValidMCLOHType(Id))
4552 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004553 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004554 } else {
4555 StringRef Name = getTok().getIdentifier();
4556 // We successfully parse an identifier.
4557 // Check if it is a recognized one.
4558 int Id = MCLOHNameToId(Name);
4559
4560 if (Id == -1)
4561 return TokError("invalid identifier in directive");
4562 Kind = (MCLOHType)Id;
4563 }
4564 // Consume the identifier.
4565 Lex();
4566 // Get the number of arguments of this LOH.
4567 int NbArgs = MCLOHIdToNbArgs(Kind);
4568
4569 assert(NbArgs != -1 && "Invalid number of arguments");
4570
4571 SmallVector<MCSymbol *, 3> Args;
4572 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4573 StringRef Name;
4574 if (getParser().parseIdentifier(Name))
4575 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004576 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004577
4578 if (Idx + 1 == NbArgs)
4579 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004580 if (parseToken(AsmToken::Comma,
4581 "unexpected token in '" + Twine(IDVal) + "' directive"))
4582 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004583 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004584 if (parseToken(AsmToken::EndOfStatement,
4585 "unexpected token in '" + Twine(IDVal) + "' directive"))
4586 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004587
4588 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4589 return false;
4590}
4591
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004592/// parseDirectiveLtorg
4593/// ::= .ltorg | .pool
4594bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004595 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4596 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004597 getTargetStreamer().emitCurrentConstantPool();
4598 return false;
4599}
4600
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004601/// parseDirectiveReq
4602/// ::= name .req registername
4603bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004604 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004605 Parser.Lex(); // Eat the '.req' token.
4606 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004607 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004608 unsigned RegNum;
4609 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004610
Sander de Smalen50d87022018-04-19 07:35:08 +00004611 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004612 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004613 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004614 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004615
Sander de Smalen50d87022018-04-19 07:35:08 +00004616 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004617 return true;
4618
Sander de Smalen50d87022018-04-19 07:35:08 +00004619 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004620 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004621 }
4622
Sander de Smalen50d87022018-04-19 07:35:08 +00004623 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004624 StringRef Kind;
4625 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004626 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004627 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004628
Sander de Smalen50d87022018-04-19 07:35:08 +00004629 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004630 return true;
4631
Sander de Smalen50d87022018-04-19 07:35:08 +00004632 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004633 return Error(SRegLoc,
4634 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004635 }
4636
Sander de Smalen50d87022018-04-19 07:35:08 +00004637 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00004638 StringRef Kind;
4639 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004640 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004641
Sander de Smalen50d87022018-04-19 07:35:08 +00004642 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00004643 return true;
4644
Sander de Smalen50d87022018-04-19 07:35:08 +00004645 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00004646 return Error(SRegLoc,
4647 "sve predicate register without type specifier expected");
4648 }
4649
Sander de Smalen50d87022018-04-19 07:35:08 +00004650 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00004651 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004652
4653 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004654 if (parseToken(AsmToken::EndOfStatement,
4655 "unexpected input in .req directive"))
4656 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004657
Sander de Smalen8e607342017-11-15 15:44:43 +00004658 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004659 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004660 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4661
Nirav Dave2364748a2016-09-16 18:30:20 +00004662 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004663}
4664
4665/// parseDirectiveUneq
4666/// ::= .unreq registername
4667bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004668 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004669 if (getTok().isNot(AsmToken::Identifier))
4670 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004671 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4672 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004673 if (parseToken(AsmToken::EndOfStatement))
4674 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004675 return false;
4676}
4677
Tim Northover3b0846e2014-05-24 12:50:23 +00004678bool
4679AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4680 AArch64MCExpr::VariantKind &ELFRefKind,
4681 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4682 int64_t &Addend) {
4683 ELFRefKind = AArch64MCExpr::VK_INVALID;
4684 DarwinRefKind = MCSymbolRefExpr::VK_None;
4685 Addend = 0;
4686
4687 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4688 ELFRefKind = AE->getKind();
4689 Expr = AE->getSubExpr();
4690 }
4691
4692 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4693 if (SE) {
4694 // It's a simple symbol reference with no addend.
4695 DarwinRefKind = SE->getKind();
4696 return true;
4697 }
4698
4699 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4700 if (!BE)
4701 return false;
4702
4703 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4704 if (!SE)
4705 return false;
4706 DarwinRefKind = SE->getKind();
4707
4708 if (BE->getOpcode() != MCBinaryExpr::Add &&
4709 BE->getOpcode() != MCBinaryExpr::Sub)
4710 return false;
4711
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004712 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004713 // on here than we can deal with.
4714 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4715 if (!AddendExpr)
4716 return false;
4717
4718 Addend = AddendExpr->getValue();
4719 if (BE->getOpcode() == MCBinaryExpr::Sub)
4720 Addend = -Addend;
4721
4722 // It's some symbol reference + a constant addend, but really
4723 // shouldn't use both Darwin and ELF syntax.
4724 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4725 DarwinRefKind == MCSymbolRefExpr::VK_None;
4726}
4727
4728/// Force static initialization.
4729extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004730 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4731 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4732 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004733}
4734
4735#define GET_REGISTER_MATCHER
4736#define GET_SUBTARGET_FEATURE_NAME
4737#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004738#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004739#include "AArch64GenAsmMatcher.inc"
4740
4741// Define this matcher function after the auto-generated include so we
4742// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004743unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004744 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004745 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004746 // If the kind is a token for a literal immediate, check if our asm
4747 // operand matches. This is for InstAliases which have a fixed-value
4748 // immediate in the syntax.
4749 int64_t ExpectedVal;
4750 switch (Kind) {
4751 default:
4752 return Match_InvalidOperand;
4753 case MCK__35_0:
4754 ExpectedVal = 0;
4755 break;
4756 case MCK__35_1:
4757 ExpectedVal = 1;
4758 break;
4759 case MCK__35_12:
4760 ExpectedVal = 12;
4761 break;
4762 case MCK__35_16:
4763 ExpectedVal = 16;
4764 break;
4765 case MCK__35_2:
4766 ExpectedVal = 2;
4767 break;
4768 case MCK__35_24:
4769 ExpectedVal = 24;
4770 break;
4771 case MCK__35_3:
4772 ExpectedVal = 3;
4773 break;
4774 case MCK__35_32:
4775 ExpectedVal = 32;
4776 break;
4777 case MCK__35_4:
4778 ExpectedVal = 4;
4779 break;
4780 case MCK__35_48:
4781 ExpectedVal = 48;
4782 break;
4783 case MCK__35_6:
4784 ExpectedVal = 6;
4785 break;
4786 case MCK__35_64:
4787 ExpectedVal = 64;
4788 break;
4789 case MCK__35_8:
4790 ExpectedVal = 8;
4791 break;
4792 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004793 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004794 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004795 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004796 if (!CE)
4797 return Match_InvalidOperand;
4798 if (CE->getValue() == ExpectedVal)
4799 return Match_Success;
4800 return Match_InvalidOperand;
4801}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004802
Alex Bradbury58eba092016-11-01 16:32:05 +00004803OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004804AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4805
4806 SMLoc S = getLoc();
4807
4808 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4809 Error(S, "expected register");
4810 return MatchOperand_ParseFail;
4811 }
4812
Sander de Smalen50d87022018-04-19 07:35:08 +00004813 unsigned FirstReg;
4814 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
4815 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004816 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00004817
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004818 const MCRegisterClass &WRegClass =
4819 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4820 const MCRegisterClass &XRegClass =
4821 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4822
4823 bool isXReg = XRegClass.contains(FirstReg),
4824 isWReg = WRegClass.contains(FirstReg);
4825 if (!isXReg && !isWReg) {
4826 Error(S, "expected first even register of a "
4827 "consecutive same-size even/odd register pair");
4828 return MatchOperand_ParseFail;
4829 }
4830
4831 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4832 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4833
4834 if (FirstEncoding & 0x1) {
4835 Error(S, "expected first even register of a "
4836 "consecutive same-size even/odd register pair");
4837 return MatchOperand_ParseFail;
4838 }
4839
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004840 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00004841 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004842 return MatchOperand_ParseFail;
4843 }
4844 // Eat the comma
4845 getParser().Lex();
4846
4847 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00004848 unsigned SecondReg;
4849 Res = tryParseScalarRegister(SecondReg);
4850 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004851 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004852
Eugene Zelenko049b0172017-01-06 00:30:53 +00004853 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004854 (isXReg && !XRegClass.contains(SecondReg)) ||
4855 (isWReg && !WRegClass.contains(SecondReg))) {
4856 Error(E,"expected second odd register of a "
4857 "consecutive same-size even/odd register pair");
4858 return MatchOperand_ParseFail;
4859 }
Joel Jones504bf332016-10-24 13:37:13 +00004860
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004861 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004862 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004863 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4864 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4865 } else {
4866 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4867 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4868 }
4869
Florian Hahnc4422242017-11-07 13:07:50 +00004870 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4871 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004872
4873 return MatchOperand_Success;
4874}
Florian Hahn91f11e52017-11-07 16:45:48 +00004875
4876template <bool ParseSuffix>
4877OperandMatchResultTy
4878AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004879 const SMLoc S = getLoc();
4880 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00004881 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00004882 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004883
Sander de Smalen8e607342017-11-15 15:44:43 +00004884 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004885 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004886
4887 if (Res != MatchOperand_Success)
4888 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004889
4890 if (ParseSuffix && Kind.empty())
4891 return MatchOperand_NoMatch;
4892
Sander de Smalen73937b72018-04-11 07:36:10 +00004893 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
4894 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00004895 return MatchOperand_NoMatch;
4896
Sander de Smalen73937b72018-04-11 07:36:10 +00004897 unsigned ElementWidth = KindRes->second;
4898 Operands.push_back(AArch64Operand::CreateVectorReg(
4899 RegNum, RegKind::SVEDataVector, ElementWidth, S, S,
4900 getContext()));
Florian Hahn91f11e52017-11-07 16:45:48 +00004901
4902 return MatchOperand_Success;
4903}
Sander de Smalen245e0e62018-01-22 10:46:00 +00004904
4905OperandMatchResultTy
4906AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
4907 MCAsmParser &Parser = getParser();
4908
4909 SMLoc SS = getLoc();
4910 const AsmToken &TokE = Parser.getTok();
4911 bool IsHash = TokE.is(AsmToken::Hash);
4912
4913 if (!IsHash && TokE.isNot(AsmToken::Identifier))
4914 return MatchOperand_NoMatch;
4915
4916 int64_t Pattern;
4917 if (IsHash) {
4918 Parser.Lex(); // Eat hash
4919
4920 // Parse the immediate operand.
4921 const MCExpr *ImmVal;
4922 SS = getLoc();
4923 if (Parser.parseExpression(ImmVal))
4924 return MatchOperand_ParseFail;
4925
4926 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4927 if (!MCE)
4928 return MatchOperand_ParseFail;
4929
4930 Pattern = MCE->getValue();
4931 } else {
4932 // Parse the pattern
4933 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
4934 if (!Pat)
4935 return MatchOperand_NoMatch;
4936
4937 Parser.Lex();
4938 Pattern = Pat->Encoding;
4939 assert(Pattern >= 0 && Pattern < 32);
4940 }
4941
4942 Operands.push_back(
4943 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
4944 SS, getLoc(), getContext()));
4945
4946 return MatchOperand_Success;
4947}