blob: 705d492e0a91d160528b321c73ea68da45b1ac39 [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);
Sander de Smaleneb896b12018-04-25 09:26:47 +0000143 template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +0000144 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
Sander de Smalen50ded902018-04-29 17:33:38 +0000509 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
510 return isImmScaled<Bits, Scale>(true);
511 }
512
513 template <int Bits, int Scale> DiagnosticPredicate isUImmScaled() const {
514 return isImmScaled<Bits, Scale>(false);
515 }
516
Sander de Smalenfe17a782018-04-26 12:54:42 +0000517 template <int Bits, int Scale>
Sander de Smalen50ded902018-04-29 17:33:38 +0000518 DiagnosticPredicate isImmScaled(bool Signed) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000519 if (!isImm())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000520 return DiagnosticPredicateTy::NoMatch;
521
Tim Northover3b0846e2014-05-24 12:50:23 +0000522 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
523 if (!MCE)
Sander de Smalenfe17a782018-04-26 12:54:42 +0000524 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000525
Sander de Smalen50ded902018-04-29 17:33:38 +0000526 int64_t MinVal, MaxVal;
527 if (Signed) {
528 int64_t Shift = Bits - 1;
529 MinVal = (int64_t(1) << Shift) * -Scale;
530 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
531 } else {
532 MinVal = 0;
533 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
534 }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000535
Tim Northover3b0846e2014-05-24 12:50:23 +0000536 int64_t Val = MCE->getValue();
Sander de Smalenfe17a782018-04-26 12:54:42 +0000537 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
538 return DiagnosticPredicateTy::Match;
539
540 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +0000541 }
542
Sander de Smalen245e0e62018-01-22 10:46:00 +0000543 bool isSVEPattern() const {
544 if (!isImm())
545 return false;
546 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
547 if (!MCE)
548 return false;
549 int64_t Val = MCE->getValue();
550 return Val >= 0 && Val < 32;
551 }
552
Tim Northover3b0846e2014-05-24 12:50:23 +0000553 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
554 AArch64MCExpr::VariantKind ELFRefKind;
555 MCSymbolRefExpr::VariantKind DarwinRefKind;
556 int64_t Addend;
557 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
558 Addend)) {
559 // If we don't understand the expression, assume the best and
560 // let the fixup and relocation code deal with it.
561 return true;
562 }
563
564 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
565 ELFRefKind == AArch64MCExpr::VK_LO12 ||
566 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
567 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
568 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
569 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
570 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
571 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000572 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
573 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
574 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000575 // Note that we don't range-check the addend. It's adjusted modulo page
576 // size when converted, so there is no "out of range" condition when using
577 // @pageoff.
578 return Addend >= 0 && (Addend % Scale) == 0;
579 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
580 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
581 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
582 return Addend == 0;
583 }
584
585 return false;
586 }
587
588 template <int Scale> bool isUImm12Offset() const {
589 if (!isImm())
590 return false;
591
592 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
593 if (!MCE)
594 return isSymbolicUImm12Offset(getImm(), Scale);
595
596 int64_t Val = MCE->getValue();
597 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
598 }
599
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000600 template <int N, int M>
601 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000602 if (!isImm())
603 return false;
604 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
605 if (!MCE)
606 return false;
607 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000608 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000609 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000610
Sander de Smalena1c259c2018-01-29 13:05:38 +0000611 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
612 // a logical immediate can always be represented when inverted.
613 template <typename T>
614 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000615 if (!isImm())
616 return false;
617 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
618 if (!MCE)
619 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000620
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000621 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000622 int64_t SVal = typename std::make_signed<T>::type(Val);
623 int64_t UVal = typename std::make_unsigned<T>::type(Val);
624 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000625 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000626
Sander de Smalena1c259c2018-01-29 13:05:38 +0000627 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000628 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000629
Tim Northover3b0846e2014-05-24 12:50:23 +0000630 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000631
Tim Northover3b0846e2014-05-24 12:50:23 +0000632 bool isAddSubImm() const {
633 if (!isShiftedImm() && !isImm())
634 return false;
635
636 const MCExpr *Expr;
637
638 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
639 if (isShiftedImm()) {
640 unsigned Shift = ShiftedImm.ShiftAmount;
641 Expr = ShiftedImm.Val;
642 if (Shift != 0 && Shift != 12)
643 return false;
644 } else {
645 Expr = getImm();
646 }
647
648 AArch64MCExpr::VariantKind ELFRefKind;
649 MCSymbolRefExpr::VariantKind DarwinRefKind;
650 int64_t Addend;
651 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
652 DarwinRefKind, Addend)) {
653 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
654 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
655 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
656 || ELFRefKind == AArch64MCExpr::VK_LO12
657 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
658 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
659 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
660 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
661 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
662 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000663 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
664 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
665 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000666 }
667
Diana Picusc93518d2016-10-11 09:17:47 +0000668 // If it's a constant, it should be a real immediate in range:
669 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
670 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
671
672 // If it's an expression, we hope for the best and let the fixup/relocation
673 // code deal with it.
674 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000675 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000676
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000677 bool isAddSubImmNeg() const {
678 if (!isShiftedImm() && !isImm())
679 return false;
680
681 const MCExpr *Expr;
682
683 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
684 if (isShiftedImm()) {
685 unsigned Shift = ShiftedImm.ShiftAmount;
686 Expr = ShiftedImm.Val;
687 if (Shift != 0 && Shift != 12)
688 return false;
689 } else
690 Expr = getImm();
691
692 // Otherwise it should be a real negative immediate in range:
693 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
694 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
695 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000696
Tim Northover3b0846e2014-05-24 12:50:23 +0000697 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000698
Tim Northover3b0846e2014-05-24 12:50:23 +0000699 bool isSIMDImmType10() const {
700 if (!isImm())
701 return false;
702 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
703 if (!MCE)
704 return false;
705 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
706 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000707
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000708 template<int N>
709 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000710 if (!isImm())
711 return false;
712 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
713 if (!MCE)
714 return true;
715 int64_t Val = MCE->getValue();
716 if (Val & 0x3)
717 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000718 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
719 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000720 }
721
722 bool
723 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
724 if (!isImm())
725 return false;
726
727 AArch64MCExpr::VariantKind ELFRefKind;
728 MCSymbolRefExpr::VariantKind DarwinRefKind;
729 int64_t Addend;
730 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
731 DarwinRefKind, Addend)) {
732 return false;
733 }
734 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
735 return false;
736
737 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
738 if (ELFRefKind == AllowedModifiers[i])
739 return Addend == 0;
740 }
741
742 return false;
743 }
744
745 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000746 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000747 }
748
749 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000750 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
751 AArch64MCExpr::VK_TPREL_G2,
752 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000753 }
754
755 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000756 return isMovWSymbol({
757 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000758 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
759 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000760 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000761 }
762
763 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000764 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
765 AArch64MCExpr::VK_TPREL_G0,
766 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000767 }
768
769 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000770 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000771 }
772
773 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000774 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000775 }
776
777 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000778 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
779 AArch64MCExpr::VK_TPREL_G1_NC,
780 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000781 }
782
783 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000784 return isMovWSymbol(
785 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
786 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000787 }
788
789 template<int RegWidth, int Shift>
790 bool isMOVZMovAlias() const {
791 if (!isImm()) return false;
792
793 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
794 if (!CE) return false;
795 uint64_t Value = CE->getValue();
796
Tim Northoverdaa1c012016-06-16 01:42:25 +0000797 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000798 }
799
800 template<int RegWidth, int Shift>
801 bool isMOVNMovAlias() const {
802 if (!isImm()) return false;
803
804 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
805 if (!CE) return false;
806 uint64_t Value = CE->getValue();
807
Tim Northoverdaa1c012016-06-16 01:42:25 +0000808 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000809 }
810
811 bool isFPImm() const { return Kind == k_FPImm; }
812 bool isBarrier() const { return Kind == k_Barrier; }
813 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000814
Tim Northover3b0846e2014-05-24 12:50:23 +0000815 bool isMRSSystemRegister() const {
816 if (!isSysReg()) return false;
817
Tim Northover7cd58932015-01-22 17:23:04 +0000818 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000819 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000820
Tim Northover3b0846e2014-05-24 12:50:23 +0000821 bool isMSRSystemRegister() const {
822 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000823 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000824 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000825
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000826 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000827 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000828 return (SysReg.PStateField == AArch64PState::PAN ||
829 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000830 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000831
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000832 bool isSystemPStateFieldWithImm0_15() const {
833 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000834 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000835 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000836
Florian Hahnc4422242017-11-07 13:07:50 +0000837 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000838 return Kind == k_Register;
839 }
840
841 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000842 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
843 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000844
Florian Hahnc4422242017-11-07 13:07:50 +0000845 bool isNeonVectorReg() const {
846 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
847 }
848
849 bool isNeonVectorRegLo() const {
850 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000851 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
852 Reg.RegNum);
853 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000854
Sander de Smalencd6be962017-12-20 11:02:42 +0000855 template <unsigned Class> bool isSVEVectorReg() const {
856 RegKind RK;
857 switch (Class) {
858 case AArch64::ZPRRegClassID:
859 RK = RegKind::SVEDataVector;
860 break;
861 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000862 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000863 RK = RegKind::SVEPredicateVector;
864 break;
865 default:
866 llvm_unreachable("Unsupport register class");
867 }
868
869 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000870 AArch64MCRegisterClasses[Class].contains(getReg());
871 }
872
Sander de Smalencd6be962017-12-20 11:02:42 +0000873 template <int ElementWidth, unsigned Class>
874 bool isSVEVectorRegOfWidth() const {
875 return isSVEVectorReg<Class>() &&
Sander de Smalen73937b72018-04-11 07:36:10 +0000876 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth);
Florian Hahn91f11e52017-11-07 16:45:48 +0000877 }
878
Sander de Smaleneb896b12018-04-25 09:26:47 +0000879 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +0000880 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
881 bool ShiftWidthAlwaysSame>
Sander de Smalenfe17a782018-04-26 12:54:42 +0000882 DiagnosticPredicate isSVEVectorRegWithShiftExtend() const {
883 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
884 return DiagnosticPredicateTy::NoMatch;
885
Sander de Smalen5861c262018-04-30 07:24:38 +0000886 if (!isSVEVectorRegOfWidth<ElementWidth, Class>())
887 return DiagnosticPredicateTy::NearMatch;
888
889 // Give a more specific diagnostic when the user has explicitly typed in
890 // a shift-amount that does not match what is expected, but for which
891 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
892 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
893 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
894 ShiftExtendTy == AArch64_AM::SXTW) &&
895 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
896 return DiagnosticPredicateTy::NoMatch;
897
898 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000899 return DiagnosticPredicateTy::Match;
900
901 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +0000902 }
903
Tim Northover3b0846e2014-05-24 12:50:23 +0000904 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000905 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000906 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
907 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000908
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000909 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000910 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000911 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
912 Reg.RegNum);
913 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000914
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000915 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000916 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000917 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
918 Reg.RegNum);
919 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000920
Sam Parker5f934642017-08-31 09:27:04 +0000921 template<int64_t Angle, int64_t Remainder>
922 bool isComplexRotation() const {
923 if (!isImm()) return false;
924
925 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
926 if (!CE) return false;
927 uint64_t Value = CE->getValue();
928
929 return (Value % Angle == Remainder && Value <= 270);
930 }
931
Sander de Smalen149916d2018-04-20 07:24:20 +0000932 template <unsigned RegClassID> bool isGPR64() const {
933 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
934 AArch64MCRegisterClasses[RegClassID].contains(getReg());
935 }
936
937 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +0000938 DiagnosticPredicate isGPR64WithShiftExtend() const {
939 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
940 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +0000941
Sander de Smalenfe17a782018-04-26 12:54:42 +0000942 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
943 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
944 return DiagnosticPredicateTy::Match;
945 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +0000946 }
947
Tim Northover3b0846e2014-05-24 12:50:23 +0000948 /// Is this a vector list with the type implicit (presumably attached to the
949 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +0000950 template <RegKind VectorKind, unsigned NumRegs>
951 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000952 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +0000953 VectorList.NumElements == 0 &&
954 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000955 }
956
Sander de Smalen650234b2018-04-12 11:40:52 +0000957 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
958 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +0000959 bool isTypedVectorList() const {
960 if (Kind != k_VectorList)
961 return false;
962 if (VectorList.Count != NumRegs)
963 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +0000964 if (VectorList.RegisterKind != VectorKind)
965 return false;
966 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +0000967 return false;
968 return VectorList.NumElements == NumElements;
969 }
970
971 bool isVectorIndex1() const {
972 return Kind == k_VectorIndex && VectorIndex.Val == 1;
973 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000974
Tim Northover3b0846e2014-05-24 12:50:23 +0000975 bool isVectorIndexB() const {
976 return Kind == k_VectorIndex && VectorIndex.Val < 16;
977 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000978
Tim Northover3b0846e2014-05-24 12:50:23 +0000979 bool isVectorIndexH() const {
980 return Kind == k_VectorIndex && VectorIndex.Val < 8;
981 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000982
Tim Northover3b0846e2014-05-24 12:50:23 +0000983 bool isVectorIndexS() const {
984 return Kind == k_VectorIndex && VectorIndex.Val < 4;
985 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000986
Tim Northover3b0846e2014-05-24 12:50:23 +0000987 bool isVectorIndexD() const {
988 return Kind == k_VectorIndex && VectorIndex.Val < 2;
989 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000990
Tim Northover3b0846e2014-05-24 12:50:23 +0000991 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000992
Tim Northover3b0846e2014-05-24 12:50:23 +0000993 bool isTokenEqual(StringRef Str) const {
994 return Kind == k_Token && getToken() == Str;
995 }
996 bool isSysCR() const { return Kind == k_SysCR; }
997 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000998 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000999 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1000 bool isShifter() const {
1001 if (!isShiftExtend())
1002 return false;
1003
1004 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1005 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1006 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1007 ST == AArch64_AM::MSL);
1008 }
1009 bool isExtend() const {
1010 if (!isShiftExtend())
1011 return false;
1012
1013 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1014 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1015 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1016 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1017 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1018 ET == AArch64_AM::LSL) &&
1019 getShiftExtendAmount() <= 4;
1020 }
1021
1022 bool isExtend64() const {
1023 if (!isExtend())
1024 return false;
1025 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1026 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1027 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1028 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001029
Tim Northover3b0846e2014-05-24 12:50:23 +00001030 bool isExtendLSL64() const {
1031 if (!isExtend())
1032 return false;
1033 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1034 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1035 ET == AArch64_AM::LSL) &&
1036 getShiftExtendAmount() <= 4;
1037 }
1038
1039 template<int Width> bool isMemXExtend() const {
1040 if (!isExtend())
1041 return false;
1042 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1043 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1044 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1045 getShiftExtendAmount() == 0);
1046 }
1047
1048 template<int Width> bool isMemWExtend() const {
1049 if (!isExtend())
1050 return false;
1051 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1052 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1053 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1054 getShiftExtendAmount() == 0);
1055 }
1056
1057 template <unsigned width>
1058 bool isArithmeticShifter() const {
1059 if (!isShifter())
1060 return false;
1061
1062 // An arithmetic shifter is LSL, LSR, or ASR.
1063 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1064 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1065 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1066 }
1067
1068 template <unsigned width>
1069 bool isLogicalShifter() const {
1070 if (!isShifter())
1071 return false;
1072
1073 // A logical shifter is LSL, LSR, ASR or ROR.
1074 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1075 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1076 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1077 getShiftExtendAmount() < width;
1078 }
1079
1080 bool isMovImm32Shifter() const {
1081 if (!isShifter())
1082 return false;
1083
1084 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1085 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1086 if (ST != AArch64_AM::LSL)
1087 return false;
1088 uint64_t Val = getShiftExtendAmount();
1089 return (Val == 0 || Val == 16);
1090 }
1091
1092 bool isMovImm64Shifter() const {
1093 if (!isShifter())
1094 return false;
1095
1096 // A MOVi shifter is LSL of 0 or 16.
1097 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1098 if (ST != AArch64_AM::LSL)
1099 return false;
1100 uint64_t Val = getShiftExtendAmount();
1101 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1102 }
1103
1104 bool isLogicalVecShifter() const {
1105 if (!isShifter())
1106 return false;
1107
1108 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1109 unsigned Shift = getShiftExtendAmount();
1110 return getShiftExtendType() == AArch64_AM::LSL &&
1111 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1112 }
1113
1114 bool isLogicalVecHalfWordShifter() const {
1115 if (!isLogicalVecShifter())
1116 return false;
1117
1118 // A logical vector shifter is a left shift by 0 or 8.
1119 unsigned Shift = getShiftExtendAmount();
1120 return getShiftExtendType() == AArch64_AM::LSL &&
1121 (Shift == 0 || Shift == 8);
1122 }
1123
1124 bool isMoveVecShifter() const {
1125 if (!isShiftExtend())
1126 return false;
1127
1128 // A logical vector shifter is a left shift by 8 or 16.
1129 unsigned Shift = getShiftExtendAmount();
1130 return getShiftExtendType() == AArch64_AM::MSL &&
1131 (Shift == 8 || Shift == 16);
1132 }
1133
1134 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1135 // to LDUR/STUR when the offset is not legal for the former but is for
1136 // the latter. As such, in addition to checking for being a legal unscaled
1137 // address, also check that it is not a legal scaled address. This avoids
1138 // ambiguity in the matcher.
1139 template<int Width>
1140 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001141 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001142 }
1143
1144 bool isAdrpLabel() const {
1145 // Validation was handled during parsing, so we just sanity check that
1146 // something didn't go haywire.
1147 if (!isImm())
1148 return false;
1149
1150 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1151 int64_t Val = CE->getValue();
1152 int64_t Min = - (4096 * (1LL << (21 - 1)));
1153 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1154 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1155 }
1156
1157 return true;
1158 }
1159
1160 bool isAdrLabel() const {
1161 // Validation was handled during parsing, so we just sanity check that
1162 // something didn't go haywire.
1163 if (!isImm())
1164 return false;
1165
1166 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1167 int64_t Val = CE->getValue();
1168 int64_t Min = - (1LL << (21 - 1));
1169 int64_t Max = ((1LL << (21 - 1)) - 1);
1170 return Val >= Min && Val <= Max;
1171 }
1172
1173 return true;
1174 }
1175
1176 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1177 // Add as immediates when possible. Null MCExpr = 0.
1178 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001179 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001180 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001181 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001182 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001183 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001184 }
1185
1186 void addRegOperands(MCInst &Inst, unsigned N) const {
1187 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001188 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001189 }
1190
1191 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1192 assert(N == 1 && "Invalid number of operands!");
1193 assert(
1194 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1195
1196 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1197 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1198 RI->getEncodingValue(getReg()));
1199
Jim Grosbache9119e42015-05-13 18:37:00 +00001200 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001201 }
1202
1203 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1204 assert(N == 1 && "Invalid number of operands!");
1205 assert(
1206 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001207 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001208 }
1209
1210 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1211 assert(N == 1 && "Invalid number of operands!");
1212 assert(
1213 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001214 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001215 }
1216
1217 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1218 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001219 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001220 }
1221
Sander de Smalen525e3222018-04-12 13:19:32 +00001222 enum VecListIndexType {
1223 VecListIdx_DReg = 0,
1224 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001225 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001226 };
1227
1228 template <VecListIndexType RegTy, unsigned NumRegs>
1229 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001230 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001231 static const unsigned FirstRegs[][5] = {
1232 /* DReg */ { AArch64::Q0,
1233 AArch64::D0, AArch64::D0_D1,
1234 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1235 /* QReg */ { AArch64::Q0,
1236 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001237 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1238 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001239 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001240 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001241 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001242
Sander de Smalen7a210db2018-04-16 10:46:18 +00001243 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1244 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001245
Sander de Smalen525e3222018-04-12 13:19:32 +00001246 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1247 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1248 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001249 }
1250
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001251 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001252 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001253 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001254 }
1255
1256 void addImmOperands(MCInst &Inst, unsigned N) const {
1257 assert(N == 1 && "Invalid number of operands!");
1258 // If this is a pageoff symrefexpr with an addend, adjust the addend
1259 // to be only the page-offset portion. Otherwise, just add the expr
1260 // as-is.
1261 addExpr(Inst, getImm());
1262 }
1263
1264 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1265 assert(N == 2 && "Invalid number of operands!");
1266 if (isShiftedImm()) {
1267 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001268 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001269 } else {
1270 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001271 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001272 }
1273 }
1274
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001275 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1276 assert(N == 2 && "Invalid number of operands!");
1277
1278 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1279 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1280 int64_t Val = -CE->getValue();
1281 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1282
1283 Inst.addOperand(MCOperand::createImm(Val));
1284 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1285 }
1286
Tim Northover3b0846e2014-05-24 12:50:23 +00001287 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1288 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001289 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001290 }
1291
1292 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1293 assert(N == 1 && "Invalid number of operands!");
1294 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1295 if (!MCE)
1296 addExpr(Inst, getImm());
1297 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001298 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001299 }
1300
1301 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1302 addImmOperands(Inst, N);
1303 }
1304
1305 template<int Scale>
1306 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1307 assert(N == 1 && "Invalid number of operands!");
1308 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1309
1310 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001311 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001312 return;
1313 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001314 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001315 }
1316
Sander de Smalen5c625982018-04-13 12:56:14 +00001317 template <int Scale>
1318 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1319 assert(N == 1 && "Invalid number of operands!");
1320 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1321 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1322 }
1323
Sander de Smalena1c259c2018-01-29 13:05:38 +00001324 template <typename T>
1325 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001326 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001327 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001328 typename std::make_unsigned<T>::type Val = MCE->getValue();
1329 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001330 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001331 }
1332
Sander de Smalena1c259c2018-01-29 13:05:38 +00001333 template <typename T>
1334 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001335 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001336 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001337 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1338 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001339 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001340 }
1341
Tim Northover3b0846e2014-05-24 12:50:23 +00001342 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1343 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001344 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001345 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001346 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001347 }
1348
1349 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1350 // Branch operands don't encode the low bits, so shift them off
1351 // here. If it's a label, however, just put it on directly as there's
1352 // not enough information now to do anything.
1353 assert(N == 1 && "Invalid number of operands!");
1354 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1355 if (!MCE) {
1356 addExpr(Inst, getImm());
1357 return;
1358 }
1359 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001360 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001361 }
1362
1363 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1364 // Branch operands don't encode the low bits, so shift them off
1365 // here. If it's a label, however, just put it on directly as there's
1366 // not enough information now to do anything.
1367 assert(N == 1 && "Invalid number of operands!");
1368 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1369 if (!MCE) {
1370 addExpr(Inst, getImm());
1371 return;
1372 }
1373 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001374 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001375 }
1376
1377 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1378 // Branch operands don't encode the low bits, so shift them off
1379 // here. If it's a label, however, just put it on directly as there's
1380 // not enough information now to do anything.
1381 assert(N == 1 && "Invalid number of operands!");
1382 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1383 if (!MCE) {
1384 addExpr(Inst, getImm());
1385 return;
1386 }
1387 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001388 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001389 }
1390
1391 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1392 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001393 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001394 }
1395
1396 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1397 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001398 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001399 }
1400
1401 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1402 assert(N == 1 && "Invalid number of operands!");
1403
Jim Grosbache9119e42015-05-13 18:37:00 +00001404 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001405 }
1406
1407 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1408 assert(N == 1 && "Invalid number of operands!");
1409
Jim Grosbache9119e42015-05-13 18:37:00 +00001410 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001411 }
1412
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001413 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1414 assert(N == 1 && "Invalid number of operands!");
1415
1416 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1417 }
1418
1419 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001420 assert(N == 1 && "Invalid number of operands!");
1421
Jim Grosbache9119e42015-05-13 18:37:00 +00001422 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001423 }
1424
1425 void addSysCROperands(MCInst &Inst, unsigned N) const {
1426 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001427 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001428 }
1429
1430 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1431 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001432 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001433 }
1434
Oliver Stannarda34e4702015-12-01 10:48:51 +00001435 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1436 assert(N == 1 && "Invalid number of operands!");
1437 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1438 }
1439
Tim Northover3b0846e2014-05-24 12:50:23 +00001440 void addShifterOperands(MCInst &Inst, unsigned N) const {
1441 assert(N == 1 && "Invalid number of operands!");
1442 unsigned Imm =
1443 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001444 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001445 }
1446
1447 void addExtendOperands(MCInst &Inst, unsigned N) const {
1448 assert(N == 1 && "Invalid number of operands!");
1449 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1450 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1451 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001452 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001453 }
1454
1455 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1456 assert(N == 1 && "Invalid number of operands!");
1457 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1458 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1459 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001460 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001461 }
1462
1463 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1464 assert(N == 2 && "Invalid number of operands!");
1465 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1466 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001467 Inst.addOperand(MCOperand::createImm(IsSigned));
1468 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001469 }
1470
1471 // For 8-bit load/store instructions with a register offset, both the
1472 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1473 // they're disambiguated by whether the shift was explicit or implicit rather
1474 // than its size.
1475 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1476 assert(N == 2 && "Invalid number of operands!");
1477 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1478 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001479 Inst.addOperand(MCOperand::createImm(IsSigned));
1480 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001481 }
1482
1483 template<int Shift>
1484 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1485 assert(N == 1 && "Invalid number of operands!");
1486
1487 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1488 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001489 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001490 }
1491
1492 template<int Shift>
1493 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1494 assert(N == 1 && "Invalid number of operands!");
1495
1496 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1497 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001498 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001499 }
1500
Sam Parker5f934642017-08-31 09:27:04 +00001501 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1502 assert(N == 1 && "Invalid number of operands!");
1503 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1504 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1505 }
1506
1507 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1508 assert(N == 1 && "Invalid number of operands!");
1509 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1510 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1511 }
1512
Tim Northover3b0846e2014-05-24 12:50:23 +00001513 void print(raw_ostream &OS) const override;
1514
David Blaikie960ea3f2014-06-08 16:18:35 +00001515 static std::unique_ptr<AArch64Operand>
1516 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1517 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001518 Op->Tok.Data = Str.data();
1519 Op->Tok.Length = Str.size();
1520 Op->Tok.IsSuffix = IsSuffix;
1521 Op->StartLoc = S;
1522 Op->EndLoc = S;
1523 return Op;
1524 }
1525
David Blaikie960ea3f2014-06-08 16:18:35 +00001526 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001527 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
1528 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1529 unsigned ShiftAmount = 0,
1530 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001531 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001532 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001533 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001534 Op->Reg.ElementWidth = 0;
1535 Op->Reg.ShiftExtend.Type = ExtTy;
1536 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1537 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001538 Op->StartLoc = S;
1539 Op->EndLoc = E;
1540 return Op;
1541 }
1542
David Blaikie960ea3f2014-06-08 16:18:35 +00001543 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001544 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001545 SMLoc S, SMLoc E, MCContext &Ctx,
1546 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1547 unsigned ShiftAmount = 0,
1548 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001549 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1550 Kind == RegKind::SVEPredicateVector) &&
1551 "Invalid vector kind");
Sander de Smalen149916d2018-04-20 07:24:20 +00001552 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, ExtTy, ShiftAmount,
1553 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001554 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001555 return Op;
1556 }
1557
1558 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001559 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001560 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1561 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001562 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001563 Op->VectorList.RegNum = RegNum;
1564 Op->VectorList.Count = Count;
1565 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001566 Op->VectorList.ElementWidth = ElementWidth;
1567 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001568 Op->StartLoc = S;
1569 Op->EndLoc = E;
1570 return Op;
1571 }
1572
David Blaikie960ea3f2014-06-08 16:18:35 +00001573 static std::unique_ptr<AArch64Operand>
1574 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1575 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001576 Op->VectorIndex.Val = Idx;
1577 Op->StartLoc = S;
1578 Op->EndLoc = E;
1579 return Op;
1580 }
1581
David Blaikie960ea3f2014-06-08 16:18:35 +00001582 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1583 SMLoc E, MCContext &Ctx) {
1584 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001585 Op->Imm.Val = Val;
1586 Op->StartLoc = S;
1587 Op->EndLoc = E;
1588 return Op;
1589 }
1590
David Blaikie960ea3f2014-06-08 16:18:35 +00001591 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1592 unsigned ShiftAmount,
1593 SMLoc S, SMLoc E,
1594 MCContext &Ctx) {
1595 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001596 Op->ShiftedImm .Val = Val;
1597 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1598 Op->StartLoc = S;
1599 Op->EndLoc = E;
1600 return Op;
1601 }
1602
David Blaikie960ea3f2014-06-08 16:18:35 +00001603 static std::unique_ptr<AArch64Operand>
1604 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1605 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001606 Op->CondCode.Code = Code;
1607 Op->StartLoc = S;
1608 Op->EndLoc = E;
1609 return Op;
1610 }
1611
David Blaikie960ea3f2014-06-08 16:18:35 +00001612 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1613 MCContext &Ctx) {
1614 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001615 Op->FPImm.Val = Val;
1616 Op->StartLoc = S;
1617 Op->EndLoc = S;
1618 return Op;
1619 }
1620
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001621 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1622 StringRef Str,
1623 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001624 MCContext &Ctx) {
1625 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001626 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001627 Op->Barrier.Data = Str.data();
1628 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001629 Op->StartLoc = S;
1630 Op->EndLoc = S;
1631 return Op;
1632 }
1633
Tim Northover7cd58932015-01-22 17:23:04 +00001634 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1635 uint32_t MRSReg,
1636 uint32_t MSRReg,
1637 uint32_t PStateField,
1638 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001639 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001640 Op->SysReg.Data = Str.data();
1641 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001642 Op->SysReg.MRSReg = MRSReg;
1643 Op->SysReg.MSRReg = MSRReg;
1644 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001645 Op->StartLoc = S;
1646 Op->EndLoc = S;
1647 return Op;
1648 }
1649
David Blaikie960ea3f2014-06-08 16:18:35 +00001650 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1651 SMLoc E, MCContext &Ctx) {
1652 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001653 Op->SysCRImm.Val = Val;
1654 Op->StartLoc = S;
1655 Op->EndLoc = E;
1656 return Op;
1657 }
1658
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001659 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1660 StringRef Str,
1661 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001662 MCContext &Ctx) {
1663 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001664 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001665 Op->Barrier.Data = Str.data();
1666 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001667 Op->StartLoc = S;
1668 Op->EndLoc = S;
1669 return Op;
1670 }
1671
Oliver Stannarda34e4702015-12-01 10:48:51 +00001672 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1673 StringRef Str,
1674 SMLoc S,
1675 MCContext &Ctx) {
1676 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1677 Op->PSBHint.Val = Val;
1678 Op->PSBHint.Data = Str.data();
1679 Op->PSBHint.Length = Str.size();
1680 Op->StartLoc = S;
1681 Op->EndLoc = S;
1682 return Op;
1683 }
1684
David Blaikie960ea3f2014-06-08 16:18:35 +00001685 static std::unique_ptr<AArch64Operand>
1686 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1687 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1688 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001689 Op->ShiftExtend.Type = ShOp;
1690 Op->ShiftExtend.Amount = Val;
1691 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1692 Op->StartLoc = S;
1693 Op->EndLoc = E;
1694 return Op;
1695 }
1696};
1697
1698} // end anonymous namespace.
1699
1700void AArch64Operand::print(raw_ostream &OS) const {
1701 switch (Kind) {
1702 case k_FPImm:
1703 OS << "<fpimm " << getFPImm() << "("
1704 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1705 break;
1706 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001707 StringRef Name = getBarrierName();
1708 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001709 OS << "<barrier " << Name << ">";
1710 else
1711 OS << "<barrier invalid #" << getBarrier() << ">";
1712 break;
1713 }
1714 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001715 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001716 break;
1717 case k_ShiftedImm: {
1718 unsigned Shift = getShiftedImmShift();
1719 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001720 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001721 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1722 break;
1723 }
1724 case k_CondCode:
1725 OS << "<condcode " << getCondCode() << ">";
1726 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001727 case k_VectorList: {
1728 OS << "<vectorlist ";
1729 unsigned Reg = getVectorListStart();
1730 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1731 OS << Reg + i << " ";
1732 OS << ">";
1733 break;
1734 }
1735 case k_VectorIndex:
1736 OS << "<vectorindex " << getVectorIndex() << ">";
1737 break;
1738 case k_SysReg:
1739 OS << "<sysreg: " << getSysReg() << '>';
1740 break;
1741 case k_Token:
1742 OS << "'" << getToken() << "'";
1743 break;
1744 case k_SysCR:
1745 OS << "c" << getSysCR();
1746 break;
1747 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001748 StringRef Name = getPrefetchName();
1749 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001750 OS << "<prfop " << Name << ">";
1751 else
1752 OS << "<prfop invalid #" << getPrefetch() << ">";
1753 break;
1754 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001755 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001756 OS << getPSBHintName();
1757 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00001758 case k_Register:
1759 OS << "<register " << getReg() << ">";
1760 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
1761 break;
1762 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001763 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001764 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1765 << getShiftExtendAmount();
1766 if (!hasShiftExtendAmount())
1767 OS << "<imp>";
1768 OS << '>';
1769 break;
1770 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001771}
1772
1773/// @name Auto-generated Match Functions
1774/// {
1775
1776static unsigned MatchRegisterName(StringRef Name);
1777
1778/// }
1779
Florian Hahnc4422242017-11-07 13:07:50 +00001780static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001781 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001782 .Case("v0", AArch64::Q0)
1783 .Case("v1", AArch64::Q1)
1784 .Case("v2", AArch64::Q2)
1785 .Case("v3", AArch64::Q3)
1786 .Case("v4", AArch64::Q4)
1787 .Case("v5", AArch64::Q5)
1788 .Case("v6", AArch64::Q6)
1789 .Case("v7", AArch64::Q7)
1790 .Case("v8", AArch64::Q8)
1791 .Case("v9", AArch64::Q9)
1792 .Case("v10", AArch64::Q10)
1793 .Case("v11", AArch64::Q11)
1794 .Case("v12", AArch64::Q12)
1795 .Case("v13", AArch64::Q13)
1796 .Case("v14", AArch64::Q14)
1797 .Case("v15", AArch64::Q15)
1798 .Case("v16", AArch64::Q16)
1799 .Case("v17", AArch64::Q17)
1800 .Case("v18", AArch64::Q18)
1801 .Case("v19", AArch64::Q19)
1802 .Case("v20", AArch64::Q20)
1803 .Case("v21", AArch64::Q21)
1804 .Case("v22", AArch64::Q22)
1805 .Case("v23", AArch64::Q23)
1806 .Case("v24", AArch64::Q24)
1807 .Case("v25", AArch64::Q25)
1808 .Case("v26", AArch64::Q26)
1809 .Case("v27", AArch64::Q27)
1810 .Case("v28", AArch64::Q28)
1811 .Case("v29", AArch64::Q29)
1812 .Case("v30", AArch64::Q30)
1813 .Case("v31", AArch64::Q31)
1814 .Default(0);
1815}
1816
Sander de Smalen73937b72018-04-11 07:36:10 +00001817/// Returns an optional pair of (#elements, element-width) if Suffix
1818/// is a valid vector kind. Where the number of elements in a vector
1819/// or the vector width is implicit or explicitly unknown (but still a
1820/// valid suffix kind), 0 is used.
1821static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1822 RegKind VectorKind) {
1823 std::pair<int, int> Res = {-1, -1};
1824
1825 switch (VectorKind) {
1826 case RegKind::NeonVector:
1827 Res =
1828 StringSwitch<std::pair<int, int>>(Suffix.lower())
1829 .Case("", {0, 0})
1830 .Case(".1d", {1, 64})
1831 .Case(".1q", {1, 128})
1832 // '.2h' needed for fp16 scalar pairwise reductions
1833 .Case(".2h", {2, 16})
1834 .Case(".2s", {2, 32})
1835 .Case(".2d", {2, 64})
1836 // '.4b' is another special case for the ARMv8.2a dot product
1837 // operand
1838 .Case(".4b", {4, 8})
1839 .Case(".4h", {4, 16})
1840 .Case(".4s", {4, 32})
1841 .Case(".8b", {8, 8})
1842 .Case(".8h", {8, 16})
1843 .Case(".16b", {16, 8})
1844 // Accept the width neutral ones, too, for verbose syntax. If those
1845 // aren't used in the right places, the token operand won't match so
1846 // all will work out.
1847 .Case(".b", {0, 8})
1848 .Case(".h", {0, 16})
1849 .Case(".s", {0, 32})
1850 .Case(".d", {0, 64})
1851 .Default({-1, -1});
1852 break;
1853 case RegKind::SVEPredicateVector:
1854 case RegKind::SVEDataVector:
1855 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1856 .Case("", {0, 0})
1857 .Case(".b", {0, 8})
1858 .Case(".h", {0, 16})
1859 .Case(".s", {0, 32})
1860 .Case(".d", {0, 64})
1861 .Case(".q", {0, 128})
1862 .Default({-1, -1});
1863 break;
1864 default:
1865 llvm_unreachable("Unsupported RegKind");
1866 }
1867
1868 if (Res == std::make_pair(-1, -1))
1869 return Optional<std::pair<int, int>>();
1870
1871 return Optional<std::pair<int, int>>(Res);
1872}
1873
1874static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1875 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001876}
1877
Florian Hahn91f11e52017-11-07 16:45:48 +00001878static unsigned matchSVEDataVectorRegName(StringRef Name) {
1879 return StringSwitch<unsigned>(Name.lower())
1880 .Case("z0", AArch64::Z0)
1881 .Case("z1", AArch64::Z1)
1882 .Case("z2", AArch64::Z2)
1883 .Case("z3", AArch64::Z3)
1884 .Case("z4", AArch64::Z4)
1885 .Case("z5", AArch64::Z5)
1886 .Case("z6", AArch64::Z6)
1887 .Case("z7", AArch64::Z7)
1888 .Case("z8", AArch64::Z8)
1889 .Case("z9", AArch64::Z9)
1890 .Case("z10", AArch64::Z10)
1891 .Case("z11", AArch64::Z11)
1892 .Case("z12", AArch64::Z12)
1893 .Case("z13", AArch64::Z13)
1894 .Case("z14", AArch64::Z14)
1895 .Case("z15", AArch64::Z15)
1896 .Case("z16", AArch64::Z16)
1897 .Case("z17", AArch64::Z17)
1898 .Case("z18", AArch64::Z18)
1899 .Case("z19", AArch64::Z19)
1900 .Case("z20", AArch64::Z20)
1901 .Case("z21", AArch64::Z21)
1902 .Case("z22", AArch64::Z22)
1903 .Case("z23", AArch64::Z23)
1904 .Case("z24", AArch64::Z24)
1905 .Case("z25", AArch64::Z25)
1906 .Case("z26", AArch64::Z26)
1907 .Case("z27", AArch64::Z27)
1908 .Case("z28", AArch64::Z28)
1909 .Case("z29", AArch64::Z29)
1910 .Case("z30", AArch64::Z30)
1911 .Case("z31", AArch64::Z31)
1912 .Default(0);
1913}
1914
Sander de Smalencd6be962017-12-20 11:02:42 +00001915static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1916 return StringSwitch<unsigned>(Name.lower())
1917 .Case("p0", AArch64::P0)
1918 .Case("p1", AArch64::P1)
1919 .Case("p2", AArch64::P2)
1920 .Case("p3", AArch64::P3)
1921 .Case("p4", AArch64::P4)
1922 .Case("p5", AArch64::P5)
1923 .Case("p6", AArch64::P6)
1924 .Case("p7", AArch64::P7)
1925 .Case("p8", AArch64::P8)
1926 .Case("p9", AArch64::P9)
1927 .Case("p10", AArch64::P10)
1928 .Case("p11", AArch64::P11)
1929 .Case("p12", AArch64::P12)
1930 .Case("p13", AArch64::P13)
1931 .Case("p14", AArch64::P14)
1932 .Case("p15", AArch64::P15)
1933 .Default(0);
1934}
1935
Tim Northover3b0846e2014-05-24 12:50:23 +00001936bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1937 SMLoc &EndLoc) {
1938 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00001939 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00001940 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00001941 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00001942}
1943
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001944// Matches a register name or register alias previously defined by '.req'
1945unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001946 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001947 unsigned RegNum = 0;
1948 if ((RegNum = matchSVEDataVectorRegName(Name)))
1949 return Kind == RegKind::SVEDataVector ? RegNum : 0;
1950
Sander de Smalencd6be962017-12-20 11:02:42 +00001951 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
1952 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
1953
Sander de Smalenc067c302017-12-20 09:45:45 +00001954 if ((RegNum = MatchNeonVectorRegName(Name)))
1955 return Kind == RegKind::NeonVector ? RegNum : 0;
1956
1957 // The parsed register must be of RegKind Scalar
1958 if ((RegNum = MatchRegisterName(Name)))
1959 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001960
Florian Hahnc4422242017-11-07 13:07:50 +00001961 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00001962 // Handle a few common aliases of registers.
1963 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
1964 .Case("fp", AArch64::FP)
1965 .Case("lr", AArch64::LR)
1966 .Case("x31", AArch64::XZR)
1967 .Case("w31", AArch64::WZR)
1968 .Default(0))
1969 return Kind == RegKind::Scalar ? RegNum : 0;
1970
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001971 // Check for aliases registered via .req. Canonicalize to lower case.
1972 // That's more consistent since register names are case insensitive, and
1973 // it's how the original entry was passed in from MC/MCParser/AsmParser.
1974 auto Entry = RegisterReqs.find(Name.lower());
1975 if (Entry == RegisterReqs.end())
1976 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00001977
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001978 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00001979 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001980 RegNum = Entry->getValue().second;
1981 }
1982 return RegNum;
1983}
1984
Sander de Smalen50d87022018-04-19 07:35:08 +00001985/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00001986/// Identifier when called, and if it is a register name the token is eaten and
1987/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00001988OperandMatchResultTy
1989AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001990 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001991 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00001992 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00001993 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001994
1995 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00001996 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
1997 if (Reg == 0)
1998 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00001999
Sander de Smalen50d87022018-04-19 07:35:08 +00002000 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002001 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002002 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002003}
2004
Tim Northover3b0846e2014-05-24 12:50:23 +00002005/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002006OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002007AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002008 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002009 SMLoc S = getLoc();
2010
2011 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2012 Error(S, "Expected cN operand where 0 <= N <= 15");
2013 return MatchOperand_ParseFail;
2014 }
2015
2016 StringRef Tok = Parser.getTok().getIdentifier();
2017 if (Tok[0] != 'c' && Tok[0] != 'C') {
2018 Error(S, "Expected cN operand where 0 <= N <= 15");
2019 return MatchOperand_ParseFail;
2020 }
2021
2022 uint32_t CRNum;
2023 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2024 if (BadNum || CRNum > 15) {
2025 Error(S, "Expected cN operand where 0 <= N <= 15");
2026 return MatchOperand_ParseFail;
2027 }
2028
2029 Parser.Lex(); // Eat identifier token.
2030 Operands.push_back(
2031 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2032 return MatchOperand_Success;
2033}
2034
2035/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002036OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002037AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002038 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002039 SMLoc S = getLoc();
2040 const AsmToken &Tok = Parser.getTok();
2041 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002042 // Eat optional hash.
2043 if (parseOptionalToken(AsmToken::Hash) ||
2044 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002045 const MCExpr *ImmVal;
2046 if (getParser().parseExpression(ImmVal))
2047 return MatchOperand_ParseFail;
2048
2049 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2050 if (!MCE) {
2051 TokError("immediate value expected for prefetch operand");
2052 return MatchOperand_ParseFail;
2053 }
2054 unsigned prfop = MCE->getValue();
2055 if (prfop > 31) {
2056 TokError("prefetch operand out of range, [0,31] expected");
2057 return MatchOperand_ParseFail;
2058 }
2059
Tim Northovere6ae6762016-07-05 21:23:04 +00002060 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2061 Operands.push_back(AArch64Operand::CreatePrefetch(
2062 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002063 return MatchOperand_Success;
2064 }
2065
2066 if (Tok.isNot(AsmToken::Identifier)) {
2067 TokError("pre-fetch hint expected");
2068 return MatchOperand_ParseFail;
2069 }
2070
Tim Northovere6ae6762016-07-05 21:23:04 +00002071 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2072 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002073 TokError("pre-fetch hint expected");
2074 return MatchOperand_ParseFail;
2075 }
2076
2077 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002078 Operands.push_back(AArch64Operand::CreatePrefetch(
2079 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002080 return MatchOperand_Success;
2081}
2082
Oliver Stannarda34e4702015-12-01 10:48:51 +00002083/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002084OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002085AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2086 MCAsmParser &Parser = getParser();
2087 SMLoc S = getLoc();
2088 const AsmToken &Tok = Parser.getTok();
2089 if (Tok.isNot(AsmToken::Identifier)) {
2090 TokError("invalid operand for instruction");
2091 return MatchOperand_ParseFail;
2092 }
2093
Tim Northovere6ae6762016-07-05 21:23:04 +00002094 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2095 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002096 TokError("invalid operand for instruction");
2097 return MatchOperand_ParseFail;
2098 }
2099
2100 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002101 Operands.push_back(AArch64Operand::CreatePSBHint(
2102 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002103 return MatchOperand_Success;
2104}
2105
Tim Northover3b0846e2014-05-24 12:50:23 +00002106/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2107/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002108OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002109AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002110 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002111 SMLoc S = getLoc();
2112 const MCExpr *Expr;
2113
2114 if (Parser.getTok().is(AsmToken::Hash)) {
2115 Parser.Lex(); // Eat hash token.
2116 }
2117
2118 if (parseSymbolicImmVal(Expr))
2119 return MatchOperand_ParseFail;
2120
2121 AArch64MCExpr::VariantKind ELFRefKind;
2122 MCSymbolRefExpr::VariantKind DarwinRefKind;
2123 int64_t Addend;
2124 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2125 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2126 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2127 // No modifier was specified at all; this is the syntax for an ELF basic
2128 // ADRP relocation (unfortunately).
2129 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002130 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002131 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2132 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2133 Addend != 0) {
2134 Error(S, "gotpage label reference not allowed an addend");
2135 return MatchOperand_ParseFail;
2136 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2137 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2138 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2139 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2140 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2141 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2142 // The operand must be an @page or @gotpage qualified symbolref.
2143 Error(S, "page or gotpage label reference expected");
2144 return MatchOperand_ParseFail;
2145 }
2146 }
2147
2148 // We have either a label reference possibly with addend or an immediate. The
2149 // addend is a raw value here. The linker will adjust it to only reference the
2150 // page.
2151 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2152 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2153
2154 return MatchOperand_Success;
2155}
2156
2157/// tryParseAdrLabel - Parse and validate a source label for the ADR
2158/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002159OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002160AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2161 SMLoc S = getLoc();
2162 const MCExpr *Expr;
2163
Nirav Davee833c6c2016-11-08 18:31:04 +00002164 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002165 if (getParser().parseExpression(Expr))
2166 return MatchOperand_ParseFail;
2167
2168 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2169 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2170
2171 return MatchOperand_Success;
2172}
2173
2174/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002175OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002176AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002177 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002178 SMLoc S = getLoc();
2179
Nirav Davee833c6c2016-11-08 18:31:04 +00002180 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002181
2182 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002183 bool isNegative = parseOptionalToken(AsmToken::Minus);
2184
Tim Northover3b0846e2014-05-24 12:50:23 +00002185 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002186 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002187 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002188 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002189 Val = Tok.getIntVal();
2190 if (Val > 255 || Val < 0) {
2191 TokError("encoded floating point value out of range");
2192 return MatchOperand_ParseFail;
2193 }
2194 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002195 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002196 if (isNegative)
2197 RealVal.changeSign();
2198
Tim Northover3b0846e2014-05-24 12:50:23 +00002199 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002200 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002201
John Brawn5ca5daa2017-04-20 10:13:54 +00002202 // Check for out of range values. As an exception we let Zero through,
2203 // but as tokens instead of an FPImm so that it can be matched by the
2204 // appropriate alias if one exists.
2205 if (RealVal.isPosZero()) {
2206 Parser.Lex(); // Eat the token.
2207 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2208 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2209 return MatchOperand_Success;
2210 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002211 TokError("expected compatible register or floating-point constant");
2212 return MatchOperand_ParseFail;
2213 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002214 }
2215 Parser.Lex(); // Eat the token.
2216 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2217 return MatchOperand_Success;
2218 }
2219
2220 if (!Hash)
2221 return MatchOperand_NoMatch;
2222
2223 TokError("invalid floating point immediate");
2224 return MatchOperand_ParseFail;
2225}
2226
2227/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002228OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002229AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002230 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002231 SMLoc S = getLoc();
2232
2233 if (Parser.getTok().is(AsmToken::Hash))
2234 Parser.Lex(); // Eat '#'
2235 else if (Parser.getTok().isNot(AsmToken::Integer))
2236 // Operand should start from # or should be integer, emit error otherwise.
2237 return MatchOperand_NoMatch;
2238
2239 const MCExpr *Imm;
2240 if (parseSymbolicImmVal(Imm))
2241 return MatchOperand_ParseFail;
2242 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2243 uint64_t ShiftAmount = 0;
2244 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2245 if (MCE) {
2246 int64_t Val = MCE->getValue();
2247 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002248 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002249 ShiftAmount = 12;
2250 }
2251 }
2252 SMLoc E = Parser.getTok().getLoc();
2253 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2254 getContext()));
2255 return MatchOperand_Success;
2256 }
2257
2258 // Eat ','
2259 Parser.Lex();
2260
2261 // The optional operand must be "lsl #N" where N is non-negative.
2262 if (!Parser.getTok().is(AsmToken::Identifier) ||
2263 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2264 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2265 return MatchOperand_ParseFail;
2266 }
2267
2268 // Eat 'lsl'
2269 Parser.Lex();
2270
Nirav Davee833c6c2016-11-08 18:31:04 +00002271 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002272
2273 if (Parser.getTok().isNot(AsmToken::Integer)) {
2274 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2275 return MatchOperand_ParseFail;
2276 }
2277
2278 int64_t ShiftAmount = Parser.getTok().getIntVal();
2279
2280 if (ShiftAmount < 0) {
2281 Error(Parser.getTok().getLoc(), "positive shift amount required");
2282 return MatchOperand_ParseFail;
2283 }
2284 Parser.Lex(); // Eat the number
2285
2286 SMLoc E = Parser.getTok().getLoc();
2287 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2288 S, E, getContext()));
2289 return MatchOperand_Success;
2290}
2291
2292/// parseCondCodeString - Parse a Condition Code string.
2293AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2294 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2295 .Case("eq", AArch64CC::EQ)
2296 .Case("ne", AArch64CC::NE)
2297 .Case("cs", AArch64CC::HS)
2298 .Case("hs", AArch64CC::HS)
2299 .Case("cc", AArch64CC::LO)
2300 .Case("lo", AArch64CC::LO)
2301 .Case("mi", AArch64CC::MI)
2302 .Case("pl", AArch64CC::PL)
2303 .Case("vs", AArch64CC::VS)
2304 .Case("vc", AArch64CC::VC)
2305 .Case("hi", AArch64CC::HI)
2306 .Case("ls", AArch64CC::LS)
2307 .Case("ge", AArch64CC::GE)
2308 .Case("lt", AArch64CC::LT)
2309 .Case("gt", AArch64CC::GT)
2310 .Case("le", AArch64CC::LE)
2311 .Case("al", AArch64CC::AL)
2312 .Case("nv", AArch64CC::NV)
2313 .Default(AArch64CC::Invalid);
2314 return CC;
2315}
2316
2317/// parseCondCode - Parse a Condition Code operand.
2318bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2319 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002320 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002321 SMLoc S = getLoc();
2322 const AsmToken &Tok = Parser.getTok();
2323 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2324
2325 StringRef Cond = Tok.getString();
2326 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2327 if (CC == AArch64CC::Invalid)
2328 return TokError("invalid condition code");
2329 Parser.Lex(); // Eat identifier token.
2330
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002331 if (invertCondCode) {
2332 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2333 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002334 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002335 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002336
2337 Operands.push_back(
2338 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2339 return false;
2340}
2341
2342/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2343/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002344OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002345AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002346 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002347 const AsmToken &Tok = Parser.getTok();
2348 std::string LowerID = Tok.getString().lower();
2349 AArch64_AM::ShiftExtendType ShOp =
2350 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2351 .Case("lsl", AArch64_AM::LSL)
2352 .Case("lsr", AArch64_AM::LSR)
2353 .Case("asr", AArch64_AM::ASR)
2354 .Case("ror", AArch64_AM::ROR)
2355 .Case("msl", AArch64_AM::MSL)
2356 .Case("uxtb", AArch64_AM::UXTB)
2357 .Case("uxth", AArch64_AM::UXTH)
2358 .Case("uxtw", AArch64_AM::UXTW)
2359 .Case("uxtx", AArch64_AM::UXTX)
2360 .Case("sxtb", AArch64_AM::SXTB)
2361 .Case("sxth", AArch64_AM::SXTH)
2362 .Case("sxtw", AArch64_AM::SXTW)
2363 .Case("sxtx", AArch64_AM::SXTX)
2364 .Default(AArch64_AM::InvalidShiftExtend);
2365
2366 if (ShOp == AArch64_AM::InvalidShiftExtend)
2367 return MatchOperand_NoMatch;
2368
2369 SMLoc S = Tok.getLoc();
2370 Parser.Lex();
2371
Nirav Davee833c6c2016-11-08 18:31:04 +00002372 bool Hash = parseOptionalToken(AsmToken::Hash);
2373
Tim Northover3b0846e2014-05-24 12:50:23 +00002374 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2375 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2376 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2377 ShOp == AArch64_AM::MSL) {
2378 // We expect a number here.
2379 TokError("expected #imm after shift specifier");
2380 return MatchOperand_ParseFail;
2381 }
2382
Chad Rosier2ff37b82016-12-27 16:58:09 +00002383 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002384 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2385 Operands.push_back(
2386 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2387 return MatchOperand_Success;
2388 }
2389
Chad Rosier2ff37b82016-12-27 16:58:09 +00002390 // Make sure we do actually have a number, identifier or a parenthesized
2391 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002392 SMLoc E = Parser.getTok().getLoc();
2393 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002394 !Parser.getTok().is(AsmToken::LParen) &&
2395 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002396 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002397 return MatchOperand_ParseFail;
2398 }
2399
2400 const MCExpr *ImmVal;
2401 if (getParser().parseExpression(ImmVal))
2402 return MatchOperand_ParseFail;
2403
2404 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2405 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002406 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002407 return MatchOperand_ParseFail;
2408 }
2409
Jim Grosbach57fd2622014-09-23 22:16:02 +00002410 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002411 Operands.push_back(AArch64Operand::CreateShiftExtend(
2412 ShOp, MCE->getValue(), true, S, E, getContext()));
2413 return MatchOperand_Success;
2414}
2415
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002416static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2417 if (FBS[AArch64::HasV8_1aOps])
2418 Str += "ARMv8.1a";
2419 else if (FBS[AArch64::HasV8_2aOps])
2420 Str += "ARMv8.2a";
2421 else
2422 Str += "(unknown)";
2423}
2424
2425void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2426 SMLoc S) {
2427 const uint16_t Op2 = Encoding & 7;
2428 const uint16_t Cm = (Encoding & 0x78) >> 3;
2429 const uint16_t Cn = (Encoding & 0x780) >> 7;
2430 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2431
2432 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2433
2434 Operands.push_back(
2435 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2436 Operands.push_back(
2437 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2438 Operands.push_back(
2439 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2440 Expr = MCConstantExpr::create(Op2, getContext());
2441 Operands.push_back(
2442 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2443}
2444
Tim Northover3b0846e2014-05-24 12:50:23 +00002445/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2446/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2447bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2448 OperandVector &Operands) {
2449 if (Name.find('.') != StringRef::npos)
2450 return TokError("invalid operand");
2451
2452 Mnemonic = Name;
2453 Operands.push_back(
2454 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2455
Rafael Espindola961d4692014-11-11 05:18:41 +00002456 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002457 const AsmToken &Tok = Parser.getTok();
2458 StringRef Op = Tok.getString();
2459 SMLoc S = Tok.getLoc();
2460
Tim Northover3b0846e2014-05-24 12:50:23 +00002461 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002462 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2463 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002464 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002465 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2466 std::string Str("IC " + std::string(IC->Name) + " requires ");
2467 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2468 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002469 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002470 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002471 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002472 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2473 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002474 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002475 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2476 std::string Str("DC " + std::string(DC->Name) + " requires ");
2477 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2478 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002479 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002480 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002481 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002482 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2483 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002484 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002485 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2486 std::string Str("AT " + std::string(AT->Name) + " requires ");
2487 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2488 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002489 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002490 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002491 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002492 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2493 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002494 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002495 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2496 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2497 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2498 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002499 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002500 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002501 }
2502
Tim Northover3b0846e2014-05-24 12:50:23 +00002503 Parser.Lex(); // Eat operand.
2504
2505 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2506 bool HasRegister = false;
2507
2508 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002509 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002510 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2511 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002512 HasRegister = true;
2513 }
2514
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002515 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002516 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002517 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002518 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002519
Nirav Davee833c6c2016-11-08 18:31:04 +00002520 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2521 return true;
2522
Tim Northover3b0846e2014-05-24 12:50:23 +00002523 return false;
2524}
2525
Alex Bradbury58eba092016-11-01 16:32:05 +00002526OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002527AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002528 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002529 const AsmToken &Tok = Parser.getTok();
2530
2531 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002532 if (parseOptionalToken(AsmToken::Hash) ||
2533 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002534 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002535 const MCExpr *ImmVal;
2536 SMLoc ExprLoc = getLoc();
2537 if (getParser().parseExpression(ImmVal))
2538 return MatchOperand_ParseFail;
2539 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2540 if (!MCE) {
2541 Error(ExprLoc, "immediate value expected for barrier operand");
2542 return MatchOperand_ParseFail;
2543 }
2544 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2545 Error(ExprLoc, "barrier operand out of range");
2546 return MatchOperand_ParseFail;
2547 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002548 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2549 Operands.push_back(AArch64Operand::CreateBarrier(
2550 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002551 return MatchOperand_Success;
2552 }
2553
2554 if (Tok.isNot(AsmToken::Identifier)) {
2555 TokError("invalid operand for instruction");
2556 return MatchOperand_ParseFail;
2557 }
2558
Tim Northover3b0846e2014-05-24 12:50:23 +00002559 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002560 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2561 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002562 TokError("'sy' or #imm operand expected");
2563 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002564 } else if (!DB) {
2565 TokError("invalid barrier option name");
2566 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002567 }
2568
Tim Northovere6ae6762016-07-05 21:23:04 +00002569 Operands.push_back(AArch64Operand::CreateBarrier(
2570 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002571 Parser.Lex(); // Consume the option
2572
2573 return MatchOperand_Success;
2574}
2575
Alex Bradbury58eba092016-11-01 16:32:05 +00002576OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002577AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002578 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002579 const AsmToken &Tok = Parser.getTok();
2580
2581 if (Tok.isNot(AsmToken::Identifier))
2582 return MatchOperand_NoMatch;
2583
Tim Northovere6ae6762016-07-05 21:23:04 +00002584 int MRSReg, MSRReg;
2585 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2586 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2587 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2588 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2589 } else
2590 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002591
Tim Northovere6ae6762016-07-05 21:23:04 +00002592 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2593 unsigned PStateImm = -1;
2594 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2595 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002596
Tim Northovere6ae6762016-07-05 21:23:04 +00002597 Operands.push_back(
2598 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2599 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002600 Parser.Lex(); // Eat identifier
2601
2602 return MatchOperand_Success;
2603}
2604
Florian Hahnc4422242017-11-07 13:07:50 +00002605/// tryParseNeonVectorRegister - Parse a vector register operand.
2606bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002607 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002608 if (Parser.getTok().isNot(AsmToken::Identifier))
2609 return true;
2610
2611 SMLoc S = getLoc();
2612 // Check for a vector register specifier first.
2613 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002614 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002615 OperandMatchResultTy Res =
2616 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2617 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002618 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002619
2620 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2621 if (!KindRes)
2622 return true;
2623
2624 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002625 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002626 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2627 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002628
Tim Northover3b0846e2014-05-24 12:50:23 +00002629 // If there was an explicit qualifier, that goes on as a literal text
2630 // operand.
2631 if (!Kind.empty())
2632 Operands.push_back(
2633 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2634
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002635 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2636}
2637
2638OperandMatchResultTy
2639AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002640 SMLoc SIdx = getLoc();
2641 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002642 const MCExpr *ImmVal;
2643 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002644 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002645 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2646 if (!MCE) {
2647 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002648 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002649 }
2650
2651 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002652
Nirav Davee833c6c2016-11-08 18:31:04 +00002653 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002654 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002655
2656 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2657 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002658 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002659 }
2660
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002661 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002662}
2663
Sander de Smalen73937b72018-04-11 07:36:10 +00002664// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002665// optional kind specifier. If it is a register specifier, eat the token
2666// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002667OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002668AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002669 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002670 MCAsmParser &Parser = getParser();
2671 const AsmToken &Tok = Parser.getTok();
2672
Florian Hahn91f11e52017-11-07 16:45:48 +00002673 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002674 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002675
2676 StringRef Name = Tok.getString();
2677 // If there is a kind specifier, it's separated from the register name by
2678 // a '.'.
2679 size_t Start = 0, Next = Name.find('.');
2680 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002681 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002682
2683 if (RegNum) {
2684 if (Next != StringRef::npos) {
2685 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002686 if (!isValidVectorKind(Kind, MatchKind)) {
2687 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002688 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002689 }
2690 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002691 Parser.Lex(); // Eat the register token.
2692
2693 Reg = RegNum;
2694 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002695 }
2696
Sander de Smalen8e607342017-11-15 15:44:43 +00002697 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002698}
2699
Sander de Smalencd6be962017-12-20 11:02:42 +00002700/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2701OperandMatchResultTy
2702AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2703 // Check for a SVE predicate register specifier first.
2704 const SMLoc S = getLoc();
2705 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002706 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002707 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002708 if (Res != MatchOperand_Success)
2709 return Res;
2710
Sander de Smalen73937b72018-04-11 07:36:10 +00002711 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2712 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002713 return MatchOperand_NoMatch;
2714
Sander de Smalen73937b72018-04-11 07:36:10 +00002715 unsigned ElementWidth = KindRes->second;
2716 Operands.push_back(AArch64Operand::CreateVectorReg(
2717 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2718 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002719
Sander de Smalen7868e742018-01-09 11:17:06 +00002720 // Not all predicates are followed by a '/m' or '/z'.
2721 MCAsmParser &Parser = getParser();
2722 if (Parser.getTok().isNot(AsmToken::Slash))
2723 return MatchOperand_Success;
2724
2725 // But when they do they shouldn't have an element type suffix.
2726 if (!Kind.empty()) {
2727 Error(S, "not expecting size suffix");
2728 return MatchOperand_ParseFail;
2729 }
2730
2731 // Add a literal slash as operand
2732 Operands.push_back(
2733 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2734
2735 Parser.Lex(); // Eat the slash.
2736
2737 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002738 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002739 if (Pred != "z" && Pred != "m") {
2740 Error(getLoc(), "expecting 'm' or 'z' predication");
2741 return MatchOperand_ParseFail;
2742 }
2743
2744 // Add zero/merge token.
2745 const char *ZM = Pred == "z" ? "z" : "m";
2746 Operands.push_back(
2747 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2748
2749 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002750 return MatchOperand_Success;
2751}
2752
Sander de Smalen50d87022018-04-19 07:35:08 +00002753/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002754bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002755 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002756 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002757 return false;
2758
Sander de Smalen149916d2018-04-20 07:24:20 +00002759 // Otherwise try for a scalar register.
2760 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
2761 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002762
Sander de Smalen149916d2018-04-20 07:24:20 +00002763 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002764}
2765
2766bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002767 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002768 bool HasELFModifier = false;
2769 AArch64MCExpr::VariantKind RefKind;
2770
Nirav Davee833c6c2016-11-08 18:31:04 +00002771 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002772 HasELFModifier = true;
2773
Nirav Davee833c6c2016-11-08 18:31:04 +00002774 if (Parser.getTok().isNot(AsmToken::Identifier))
2775 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002776
2777 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2778 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2779 .Case("lo12", AArch64MCExpr::VK_LO12)
2780 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2781 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2782 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2783 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2784 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2785 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2786 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2787 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2788 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2789 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2790 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2791 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2792 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2793 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2794 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2795 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2796 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2797 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2798 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2799 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2800 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2801 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2802 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2803 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2804 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2805 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2806 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2807 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2808 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2809 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2810 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2811 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2812 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2813 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002814 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2815 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002816 .Default(AArch64MCExpr::VK_INVALID);
2817
Nirav Davee833c6c2016-11-08 18:31:04 +00002818 if (RefKind == AArch64MCExpr::VK_INVALID)
2819 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002820
2821 Parser.Lex(); // Eat identifier
2822
Nirav Davee833c6c2016-11-08 18:31:04 +00002823 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002824 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002825 }
2826
2827 if (getParser().parseExpression(ImmVal))
2828 return true;
2829
2830 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002831 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002832
2833 return false;
2834}
2835
Sander de Smalen650234b2018-04-12 11:40:52 +00002836template <RegKind VectorKind>
2837OperandMatchResultTy
2838AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
2839 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002840 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00002841 if (!Parser.getTok().is(AsmToken::LCurly))
2842 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002843
2844 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00002845 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00002846 bool NoMatchIsError) {
2847 auto RegTok = Parser.getTok();
2848 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
2849 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002850 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00002851 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002852 llvm_unreachable("Expected a valid vector kind");
2853 }
2854
Sander de Smalen650234b2018-04-12 11:40:52 +00002855 if (RegTok.isNot(AsmToken::Identifier) ||
2856 ParseRes == MatchOperand_ParseFail ||
2857 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
2858 Error(Loc, "vector register expected");
2859 return MatchOperand_ParseFail;
2860 }
2861
2862 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002863 };
2864
Tim Northover3b0846e2014-05-24 12:50:23 +00002865 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00002866 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00002867 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00002868
Tim Northover3b0846e2014-05-24 12:50:23 +00002869 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002870 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002871 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
2872
2873 // Put back the original left bracket if there was no match, so that
2874 // different types of list-operands can be matched (e.g. SVE, Neon).
2875 if (ParseRes == MatchOperand_NoMatch)
2876 Parser.getLexer().UnLex(LCurly);
2877
2878 if (ParseRes != MatchOperand_Success)
2879 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002880
Tim Northover3b0846e2014-05-24 12:50:23 +00002881 int64_t PrevReg = FirstReg;
2882 unsigned Count = 1;
2883
Nirav Davee833c6c2016-11-08 18:31:04 +00002884 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002885 SMLoc Loc = getLoc();
2886 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002887
Sander de Smalen50d87022018-04-19 07:35:08 +00002888 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002889 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2890 if (ParseRes != MatchOperand_Success)
2891 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002892
Tim Northover3b0846e2014-05-24 12:50:23 +00002893 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002894 if (Kind != NextKind) {
2895 Error(Loc, "mismatched register size suffix");
2896 return MatchOperand_ParseFail;
2897 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002898
2899 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2900
2901 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002902 Error(Loc, "invalid number of vectors");
2903 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002904 }
2905
2906 Count += Space;
2907 }
2908 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002909 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002910 SMLoc Loc = getLoc();
2911 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002912 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002913 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2914 if (ParseRes != MatchOperand_Success)
2915 return ParseRes;
2916
Tim Northover3b0846e2014-05-24 12:50:23 +00002917 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002918 if (Kind != NextKind) {
2919 Error(Loc, "mismatched register size suffix");
2920 return MatchOperand_ParseFail;
2921 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002922
2923 // Registers must be incremental (with wraparound at 31)
2924 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00002925 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
2926 Error(Loc, "registers must be sequential");
2927 return MatchOperand_ParseFail;
2928 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002929
2930 PrevReg = Reg;
2931 ++Count;
2932 }
2933 }
2934
Nirav Davee833c6c2016-11-08 18:31:04 +00002935 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00002936 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002937
Sander de Smalen650234b2018-04-12 11:40:52 +00002938 if (Count > 4) {
2939 Error(S, "invalid number of vectors");
2940 return MatchOperand_ParseFail;
2941 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002942
2943 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00002944 unsigned ElementWidth = 0;
2945 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002946 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00002947 std::tie(NumElements, ElementWidth) = *VK;
2948 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002949
2950 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00002951 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
2952 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002953
Sander de Smalen650234b2018-04-12 11:40:52 +00002954 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002955}
2956
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002957/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
2958bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002959 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
2960 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002961 return true;
2962
2963 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2964}
2965
Alex Bradbury58eba092016-11-01 16:32:05 +00002966OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002967AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002968 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002969
Sander de Smalen50d87022018-04-19 07:35:08 +00002970 unsigned RegNum;
2971 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
2972 if (Res != MatchOperand_Success)
2973 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00002974
Nirav Davee833c6c2016-11-08 18:31:04 +00002975 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002976 Operands.push_back(AArch64Operand::CreateReg(
2977 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002978 return MatchOperand_Success;
2979 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002980
Nirav Davee833c6c2016-11-08 18:31:04 +00002981 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002982
Sander de Smalen50d87022018-04-19 07:35:08 +00002983 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002984 Error(getLoc(), "index must be absent or #0");
2985 return MatchOperand_ParseFail;
2986 }
2987
2988 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00002989 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00002990 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
2991 Error(getLoc(), "index must be absent or #0");
2992 return MatchOperand_ParseFail;
2993 }
2994
Sander de Smalen50d87022018-04-19 07:35:08 +00002995 Operands.push_back(AArch64Operand::CreateReg(
2996 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002997 return MatchOperand_Success;
2998}
2999
Sander de Smalen149916d2018-04-20 07:24:20 +00003000template <bool ParseShiftExtend>
3001OperandMatchResultTy
3002AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3003 SMLoc StartLoc = getLoc();
3004
3005 unsigned RegNum;
3006 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3007 if (Res != MatchOperand_Success)
3008 return Res;
3009
3010 // No shift/extend is the default.
3011 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3012 Operands.push_back(AArch64Operand::CreateReg(
3013 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
3014 return MatchOperand_Success;
3015 }
3016
3017 // Eat the comma
3018 getParser().Lex();
3019
3020 // Match the shift
3021 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3022 Res = tryParseOptionalShiftExtend(ExtOpnd);
3023 if (Res != MatchOperand_Success)
3024 return Res;
3025
3026 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
3027 Operands.push_back(AArch64Operand::CreateReg(RegNum, RegKind::Scalar,
3028 StartLoc, Ext->getEndLoc(), getContext(),
3029 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3030 Ext->hasShiftExtendAmount()));
3031
3032 return MatchOperand_Success;
3033}
3034
Sander de Smalen5c625982018-04-13 12:56:14 +00003035bool AArch64AsmParser::parseOptionalMulVl(OperandVector &Operands) {
3036 MCAsmParser &Parser = getParser();
3037
3038 // Some SVE instructions have a decoration after the immediate, i.e.
3039 // "mul vl". We parse them here and add tokens, which must be present in the
3040 // asm string in the tablegen instruction.
3041 if (!Parser.getTok().getString().equals_lower("mul") ||
3042 !Parser.getLexer().peekTok().getString().equals_lower("vl"))
3043 return true;
3044
3045 SMLoc S = getLoc();
3046 Operands.push_back(
3047 AArch64Operand::CreateToken("mul", false, S, getContext()));
3048 Parser.Lex(); // Eat the "mul"
3049
3050 S = getLoc();
3051 Operands.push_back(
3052 AArch64Operand::CreateToken("vl", false, S, getContext()));
3053 Parser.Lex(); // Eat the "vl"
3054
3055 return false;
3056}
3057
Tim Northover3b0846e2014-05-24 12:50:23 +00003058/// parseOperand - Parse a arm instruction operand. For now this parses the
3059/// operand regardless of the mnemonic.
3060bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3061 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003062 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003063
3064 OperandMatchResultTy ResTy =
3065 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3066
Tim Northover3b0846e2014-05-24 12:50:23 +00003067 // Check if the current operand has a custom associated parser, if so, try to
3068 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003069 if (ResTy == MatchOperand_Success)
3070 return false;
3071 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3072 // there was a match, but an error occurred, in which case, just return that
3073 // the operand parsing failed.
3074 if (ResTy == MatchOperand_ParseFail)
3075 return true;
3076
3077 // Nothing custom, so do general case parsing.
3078 SMLoc S, E;
3079 switch (getLexer().getKind()) {
3080 default: {
3081 SMLoc S = getLoc();
3082 const MCExpr *Expr;
3083 if (parseSymbolicImmVal(Expr))
3084 return Error(S, "invalid operand");
3085
3086 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3087 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3088 return false;
3089 }
3090 case AsmToken::LBrac: {
3091 SMLoc Loc = Parser.getTok().getLoc();
3092 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3093 getContext()));
3094 Parser.Lex(); // Eat '['
3095
3096 // There's no comma after a '[', so we can parse the next operand
3097 // immediately.
3098 return parseOperand(Operands, false, false);
3099 }
3100 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003101 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003102 case AsmToken::Identifier: {
3103 // If we're expecting a Condition Code operand, then just parse that.
3104 if (isCondCode)
3105 return parseCondCode(Operands, invertCondCode);
3106
3107 // If it's a register name, parse it.
3108 if (!parseRegister(Operands))
3109 return false;
3110
Sander de Smalen5c625982018-04-13 12:56:14 +00003111 // See if this is a "mul vl" decoration used by SVE instructions.
3112 if (!parseOptionalMulVl(Operands))
3113 return false;
3114
Tim Northover3b0846e2014-05-24 12:50:23 +00003115 // This could be an optional "shift" or "extend" operand.
3116 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3117 // We can only continue if no tokens were eaten.
3118 if (GotShift != MatchOperand_NoMatch)
3119 return GotShift;
3120
3121 // This was not a register so parse other operands that start with an
3122 // identifier (like labels) as expressions and create them as immediates.
3123 const MCExpr *IdVal;
3124 S = getLoc();
3125 if (getParser().parseExpression(IdVal))
3126 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003127 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3128 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3129 return false;
3130 }
3131 case AsmToken::Integer:
3132 case AsmToken::Real:
3133 case AsmToken::Hash: {
3134 // #42 -> immediate.
3135 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003136
3137 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003138
3139 // Parse a negative sign
3140 bool isNegative = false;
3141 if (Parser.getTok().is(AsmToken::Minus)) {
3142 isNegative = true;
3143 // We need to consume this token only when we have a Real, otherwise
3144 // we let parseSymbolicImmVal take care of it
3145 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3146 Parser.Lex();
3147 }
3148
3149 // The only Real that should come through here is a literal #0.0 for
3150 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3151 // so convert the value.
3152 const AsmToken &Tok = Parser.getTok();
3153 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003154 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003155 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3156 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3157 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3158 Mnemonic != "fcmlt")
3159 return TokError("unexpected floating point literal");
3160 else if (IntVal != 0 || isNegative)
3161 return TokError("expected floating-point constant #0.0");
3162 Parser.Lex(); // Eat the token.
3163
3164 Operands.push_back(
3165 AArch64Operand::CreateToken("#0", false, S, getContext()));
3166 Operands.push_back(
3167 AArch64Operand::CreateToken(".0", false, S, getContext()));
3168 return false;
3169 }
3170
3171 const MCExpr *ImmVal;
3172 if (parseSymbolicImmVal(ImmVal))
3173 return true;
3174
3175 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3176 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3177 return false;
3178 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003179 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003180 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003181 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003182 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003183 Parser.Lex(); // Eat '='
3184 const MCExpr *SubExprVal;
3185 if (getParser().parseExpression(SubExprVal))
3186 return true;
3187
David Peixottoae5ba762014-07-18 16:05:14 +00003188 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003189 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003190 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003191
3192 bool IsXReg =
3193 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3194 Operands[1]->getReg());
3195
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003196 MCContext& Ctx = getContext();
3197 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3198 // 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 +00003199 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003200 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3201 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3202 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3203 ShiftAmt += 16;
3204 Imm >>= 16;
3205 }
3206 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3207 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3208 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003209 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003210 if (ShiftAmt)
3211 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3212 ShiftAmt, true, S, E, Ctx));
3213 return false;
3214 }
David Peixottoae5ba762014-07-18 16:05:14 +00003215 APInt Simm = APInt(64, Imm << ShiftAmt);
3216 // check if the immediate is an unsigned or signed 32-bit int for W regs
3217 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3218 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003219 }
3220 // 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 +00003221 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003222 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003223 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3224 return false;
3225 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003226 }
3227}
3228
3229/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3230/// operands.
3231bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3232 StringRef Name, SMLoc NameLoc,
3233 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003234 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003235 Name = StringSwitch<StringRef>(Name.lower())
3236 .Case("beq", "b.eq")
3237 .Case("bne", "b.ne")
3238 .Case("bhs", "b.hs")
3239 .Case("bcs", "b.cs")
3240 .Case("blo", "b.lo")
3241 .Case("bcc", "b.cc")
3242 .Case("bmi", "b.mi")
3243 .Case("bpl", "b.pl")
3244 .Case("bvs", "b.vs")
3245 .Case("bvc", "b.vc")
3246 .Case("bhi", "b.hi")
3247 .Case("bls", "b.ls")
3248 .Case("bge", "b.ge")
3249 .Case("blt", "b.lt")
3250 .Case("bgt", "b.gt")
3251 .Case("ble", "b.le")
3252 .Case("bal", "b.al")
3253 .Case("bnv", "b.nv")
3254 .Default(Name);
3255
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003256 // First check for the AArch64-specific .req directive.
3257 if (Parser.getTok().is(AsmToken::Identifier) &&
3258 Parser.getTok().getIdentifier() == ".req") {
3259 parseDirectiveReq(Name, NameLoc);
3260 // We always return 'error' for this, as we're done with this
3261 // statement and don't need to match the 'instruction."
3262 return true;
3263 }
3264
Tim Northover3b0846e2014-05-24 12:50:23 +00003265 // Create the leading tokens for the mnemonic, split by '.' characters.
3266 size_t Start = 0, Next = Name.find('.');
3267 StringRef Head = Name.slice(Start, Next);
3268
3269 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003270 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3271 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003272
3273 Operands.push_back(
3274 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3275 Mnemonic = Head;
3276
3277 // Handle condition codes for a branch mnemonic
3278 if (Head == "b" && Next != StringRef::npos) {
3279 Start = Next;
3280 Next = Name.find('.', Start + 1);
3281 Head = Name.slice(Start + 1, Next);
3282
3283 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3284 (Head.data() - Name.data()));
3285 AArch64CC::CondCode CC = parseCondCodeString(Head);
3286 if (CC == AArch64CC::Invalid)
3287 return Error(SuffixLoc, "invalid condition code");
3288 Operands.push_back(
3289 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3290 Operands.push_back(
3291 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3292 }
3293
3294 // Add the remaining tokens in the mnemonic.
3295 while (Next != StringRef::npos) {
3296 Start = Next;
3297 Next = Name.find('.', Start + 1);
3298 Head = Name.slice(Start, Next);
3299 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3300 (Head.data() - Name.data()) + 1);
3301 Operands.push_back(
3302 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3303 }
3304
3305 // Conditional compare instructions have a Condition Code operand, which needs
3306 // to be parsed and an immediate operand created.
3307 bool condCodeFourthOperand =
3308 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3309 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3310 Head == "csinc" || Head == "csinv" || Head == "csneg");
3311
3312 // These instructions are aliases to some of the conditional select
3313 // instructions. However, the condition code is inverted in the aliased
3314 // instruction.
3315 //
3316 // FIXME: Is this the correct way to handle these? Or should the parser
3317 // generate the aliased instructions directly?
3318 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3319 bool condCodeThirdOperand =
3320 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3321
3322 // Read the remaining operands.
3323 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3324 // Read the first operand.
3325 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003326 return true;
3327 }
3328
3329 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003330 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003331 // Parse and remember the operand.
3332 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3333 (N == 3 && condCodeThirdOperand) ||
3334 (N == 2 && condCodeSecondOperand),
3335 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003336 return true;
3337 }
3338
3339 // After successfully parsing some operands there are two special cases to
3340 // consider (i.e. notional operands not separated by commas). Both are due
3341 // to memory specifiers:
3342 // + An RBrac will end an address for load/store/prefetch
3343 // + An '!' will indicate a pre-indexed operation.
3344 //
3345 // It's someone else's responsibility to make sure these tokens are sane
3346 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003347
Nirav Davee833c6c2016-11-08 18:31:04 +00003348 SMLoc RLoc = Parser.getTok().getLoc();
3349 if (parseOptionalToken(AsmToken::RBrac))
3350 Operands.push_back(
3351 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3352 SMLoc ELoc = Parser.getTok().getLoc();
3353 if (parseOptionalToken(AsmToken::Exclaim))
3354 Operands.push_back(
3355 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003356
3357 ++N;
3358 }
3359 }
3360
Nirav Davee833c6c2016-11-08 18:31:04 +00003361 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3362 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003363
Tim Northover3b0846e2014-05-24 12:50:23 +00003364 return false;
3365}
3366
3367// FIXME: This entire function is a giant hack to provide us with decent
3368// operand range validation/diagnostics until TableGen/MC can be extended
3369// to support autogeneration of this kind of validation.
3370bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3371 SmallVectorImpl<SMLoc> &Loc) {
3372 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3373 // Check for indexed addressing modes w/ the base register being the
3374 // same as a destination/source register or pair load where
3375 // the Rt == Rt2. All of those are undefined behaviour.
3376 switch (Inst.getOpcode()) {
3377 case AArch64::LDPSWpre:
3378 case AArch64::LDPWpost:
3379 case AArch64::LDPWpre:
3380 case AArch64::LDPXpost:
3381 case AArch64::LDPXpre: {
3382 unsigned Rt = Inst.getOperand(1).getReg();
3383 unsigned Rt2 = Inst.getOperand(2).getReg();
3384 unsigned Rn = Inst.getOperand(3).getReg();
3385 if (RI->isSubRegisterEq(Rn, Rt))
3386 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3387 "is also a destination");
3388 if (RI->isSubRegisterEq(Rn, Rt2))
3389 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3390 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003391 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003392 }
3393 case AArch64::LDPDi:
3394 case AArch64::LDPQi:
3395 case AArch64::LDPSi:
3396 case AArch64::LDPSWi:
3397 case AArch64::LDPWi:
3398 case AArch64::LDPXi: {
3399 unsigned Rt = Inst.getOperand(0).getReg();
3400 unsigned Rt2 = Inst.getOperand(1).getReg();
3401 if (Rt == Rt2)
3402 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3403 break;
3404 }
3405 case AArch64::LDPDpost:
3406 case AArch64::LDPDpre:
3407 case AArch64::LDPQpost:
3408 case AArch64::LDPQpre:
3409 case AArch64::LDPSpost:
3410 case AArch64::LDPSpre:
3411 case AArch64::LDPSWpost: {
3412 unsigned Rt = Inst.getOperand(1).getReg();
3413 unsigned Rt2 = Inst.getOperand(2).getReg();
3414 if (Rt == Rt2)
3415 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3416 break;
3417 }
3418 case AArch64::STPDpost:
3419 case AArch64::STPDpre:
3420 case AArch64::STPQpost:
3421 case AArch64::STPQpre:
3422 case AArch64::STPSpost:
3423 case AArch64::STPSpre:
3424 case AArch64::STPWpost:
3425 case AArch64::STPWpre:
3426 case AArch64::STPXpost:
3427 case AArch64::STPXpre: {
3428 unsigned Rt = Inst.getOperand(1).getReg();
3429 unsigned Rt2 = Inst.getOperand(2).getReg();
3430 unsigned Rn = Inst.getOperand(3).getReg();
3431 if (RI->isSubRegisterEq(Rn, Rt))
3432 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3433 "is also a source");
3434 if (RI->isSubRegisterEq(Rn, Rt2))
3435 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3436 "is also a source");
3437 break;
3438 }
3439 case AArch64::LDRBBpre:
3440 case AArch64::LDRBpre:
3441 case AArch64::LDRHHpre:
3442 case AArch64::LDRHpre:
3443 case AArch64::LDRSBWpre:
3444 case AArch64::LDRSBXpre:
3445 case AArch64::LDRSHWpre:
3446 case AArch64::LDRSHXpre:
3447 case AArch64::LDRSWpre:
3448 case AArch64::LDRWpre:
3449 case AArch64::LDRXpre:
3450 case AArch64::LDRBBpost:
3451 case AArch64::LDRBpost:
3452 case AArch64::LDRHHpost:
3453 case AArch64::LDRHpost:
3454 case AArch64::LDRSBWpost:
3455 case AArch64::LDRSBXpost:
3456 case AArch64::LDRSHWpost:
3457 case AArch64::LDRSHXpost:
3458 case AArch64::LDRSWpost:
3459 case AArch64::LDRWpost:
3460 case AArch64::LDRXpost: {
3461 unsigned Rt = Inst.getOperand(1).getReg();
3462 unsigned Rn = Inst.getOperand(2).getReg();
3463 if (RI->isSubRegisterEq(Rn, Rt))
3464 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3465 "is also a source");
3466 break;
3467 }
3468 case AArch64::STRBBpost:
3469 case AArch64::STRBpost:
3470 case AArch64::STRHHpost:
3471 case AArch64::STRHpost:
3472 case AArch64::STRWpost:
3473 case AArch64::STRXpost:
3474 case AArch64::STRBBpre:
3475 case AArch64::STRBpre:
3476 case AArch64::STRHHpre:
3477 case AArch64::STRHpre:
3478 case AArch64::STRWpre:
3479 case AArch64::STRXpre: {
3480 unsigned Rt = Inst.getOperand(1).getReg();
3481 unsigned Rn = Inst.getOperand(2).getReg();
3482 if (RI->isSubRegisterEq(Rn, Rt))
3483 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3484 "is also a source");
3485 break;
3486 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003487 case AArch64::STXRB:
3488 case AArch64::STXRH:
3489 case AArch64::STXRW:
3490 case AArch64::STXRX:
3491 case AArch64::STLXRB:
3492 case AArch64::STLXRH:
3493 case AArch64::STLXRW:
3494 case AArch64::STLXRX: {
3495 unsigned Rs = Inst.getOperand(0).getReg();
3496 unsigned Rt = Inst.getOperand(1).getReg();
3497 unsigned Rn = Inst.getOperand(2).getReg();
3498 if (RI->isSubRegisterEq(Rt, Rs) ||
3499 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3500 return Error(Loc[0],
3501 "unpredictable STXR instruction, status is also a source");
3502 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003503 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003504 case AArch64::STXPW:
3505 case AArch64::STXPX:
3506 case AArch64::STLXPW:
3507 case AArch64::STLXPX: {
3508 unsigned Rs = Inst.getOperand(0).getReg();
3509 unsigned Rt1 = Inst.getOperand(1).getReg();
3510 unsigned Rt2 = Inst.getOperand(2).getReg();
3511 unsigned Rn = Inst.getOperand(3).getReg();
3512 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3513 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3514 return Error(Loc[0],
3515 "unpredictable STXP instruction, status is also a source");
3516 break;
3517 }
3518 }
3519
Tim Northover3b0846e2014-05-24 12:50:23 +00003520
3521 // Now check immediate ranges. Separate from the above as there is overlap
3522 // in the instructions being checked and this keeps the nested conditionals
3523 // to a minimum.
3524 switch (Inst.getOpcode()) {
3525 case AArch64::ADDSWri:
3526 case AArch64::ADDSXri:
3527 case AArch64::ADDWri:
3528 case AArch64::ADDXri:
3529 case AArch64::SUBSWri:
3530 case AArch64::SUBSXri:
3531 case AArch64::SUBWri:
3532 case AArch64::SUBXri: {
3533 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3534 // some slight duplication here.
3535 if (Inst.getOperand(2).isExpr()) {
3536 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3537 AArch64MCExpr::VariantKind ELFRefKind;
3538 MCSymbolRefExpr::VariantKind DarwinRefKind;
3539 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003540 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3541
3542 // Only allow these with ADDXri.
3543 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3544 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3545 Inst.getOpcode() == AArch64::ADDXri)
3546 return false;
3547
3548 // Only allow these with ADDXri/ADDWri
3549 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3550 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3551 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3552 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3553 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3554 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3555 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003556 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3557 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3558 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003559 (Inst.getOpcode() == AArch64::ADDXri ||
3560 Inst.getOpcode() == AArch64::ADDWri))
3561 return false;
3562
3563 // Don't allow symbol refs in the immediate field otherwise
3564 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3565 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3566 // 'cmp w0, 'borked')
3567 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003568 }
Diana Picusc93518d2016-10-11 09:17:47 +00003569 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003570 }
3571 return false;
3572 }
3573 default:
3574 return false;
3575 }
3576}
3577
Craig Topper05515562017-10-26 06:46:41 +00003578static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3579 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003580
3581bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3582 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003583 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003584 case Match_InvalidTiedOperand:
3585 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003586 case Match_MissingFeature:
3587 return Error(Loc,
3588 "instruction requires a CPU feature not currently enabled");
3589 case Match_InvalidOperand:
3590 return Error(Loc, "invalid operand for instruction");
3591 case Match_InvalidSuffix:
3592 return Error(Loc, "invalid type suffix for instruction");
3593 case Match_InvalidCondCode:
3594 return Error(Loc, "expected AArch64 condition code");
3595 case Match_AddSubRegExtendSmall:
3596 return Error(Loc,
3597 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3598 case Match_AddSubRegExtendLarge:
3599 return Error(Loc,
3600 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3601 case Match_AddSubSecondSource:
3602 return Error(Loc,
3603 "expected compatible register, symbol or integer in range [0, 4095]");
3604 case Match_LogicalSecondSource:
3605 return Error(Loc, "expected compatible register or logical immediate");
3606 case Match_InvalidMovImm32Shift:
3607 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3608 case Match_InvalidMovImm64Shift:
3609 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3610 case Match_AddSubRegShift32:
3611 return Error(Loc,
3612 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3613 case Match_AddSubRegShift64:
3614 return Error(Loc,
3615 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3616 case Match_InvalidFPImm:
3617 return Error(Loc,
3618 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003619 case Match_InvalidMemoryIndexedSImm6:
3620 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003621 case Match_InvalidMemoryIndexedSImm5:
3622 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003623 case Match_InvalidMemoryIndexed1SImm4:
3624 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003625 case Match_InvalidMemoryIndexed2SImm4:
3626 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003627 case Match_InvalidMemoryIndexed3SImm4:
3628 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003629 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00003630 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00003631 case Match_InvalidMemoryIndexed16SImm4:
3632 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003633 case Match_InvalidMemoryIndexedSImm9:
3634 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00003635 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00003636 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003637 case Match_InvalidMemoryIndexed4SImm7:
3638 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3639 case Match_InvalidMemoryIndexed8SImm7:
3640 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3641 case Match_InvalidMemoryIndexed16SImm7:
3642 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00003643 case Match_InvalidMemoryIndexed8UImm5:
3644 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
3645 case Match_InvalidMemoryIndexed4UImm5:
3646 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
3647 case Match_InvalidMemoryIndexed2UImm5:
3648 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00003649 case Match_InvalidMemoryIndexed8UImm6:
3650 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
3651 case Match_InvalidMemoryIndexed4UImm6:
3652 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
3653 case Match_InvalidMemoryIndexed2UImm6:
3654 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
3655 case Match_InvalidMemoryIndexed1UImm6:
3656 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003657 case Match_InvalidMemoryWExtend8:
3658 return Error(Loc,
3659 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3660 case Match_InvalidMemoryWExtend16:
3661 return Error(Loc,
3662 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3663 case Match_InvalidMemoryWExtend32:
3664 return Error(Loc,
3665 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3666 case Match_InvalidMemoryWExtend64:
3667 return Error(Loc,
3668 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3669 case Match_InvalidMemoryWExtend128:
3670 return Error(Loc,
3671 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3672 case Match_InvalidMemoryXExtend8:
3673 return Error(Loc,
3674 "expected 'lsl' or 'sxtx' with optional shift of #0");
3675 case Match_InvalidMemoryXExtend16:
3676 return Error(Loc,
3677 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3678 case Match_InvalidMemoryXExtend32:
3679 return Error(Loc,
3680 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3681 case Match_InvalidMemoryXExtend64:
3682 return Error(Loc,
3683 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3684 case Match_InvalidMemoryXExtend128:
3685 return Error(Loc,
3686 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3687 case Match_InvalidMemoryIndexed1:
3688 return Error(Loc, "index must be an integer in range [0, 4095].");
3689 case Match_InvalidMemoryIndexed2:
3690 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3691 case Match_InvalidMemoryIndexed4:
3692 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3693 case Match_InvalidMemoryIndexed8:
3694 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3695 case Match_InvalidMemoryIndexed16:
3696 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003697 case Match_InvalidImm0_1:
3698 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003699 case Match_InvalidImm0_7:
3700 return Error(Loc, "immediate must be an integer in range [0, 7].");
3701 case Match_InvalidImm0_15:
3702 return Error(Loc, "immediate must be an integer in range [0, 15].");
3703 case Match_InvalidImm0_31:
3704 return Error(Loc, "immediate must be an integer in range [0, 31].");
3705 case Match_InvalidImm0_63:
3706 return Error(Loc, "immediate must be an integer in range [0, 63].");
3707 case Match_InvalidImm0_127:
3708 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003709 case Match_InvalidImm0_255:
3710 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003711 case Match_InvalidImm0_65535:
3712 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3713 case Match_InvalidImm1_8:
3714 return Error(Loc, "immediate must be an integer in range [1, 8].");
3715 case Match_InvalidImm1_16:
3716 return Error(Loc, "immediate must be an integer in range [1, 16].");
3717 case Match_InvalidImm1_32:
3718 return Error(Loc, "immediate must be an integer in range [1, 32].");
3719 case Match_InvalidImm1_64:
3720 return Error(Loc, "immediate must be an integer in range [1, 64].");
3721 case Match_InvalidIndex1:
3722 return Error(Loc, "expected lane specifier '[1]'");
3723 case Match_InvalidIndexB:
3724 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3725 case Match_InvalidIndexH:
3726 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3727 case Match_InvalidIndexS:
3728 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3729 case Match_InvalidIndexD:
3730 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3731 case Match_InvalidLabel:
3732 return Error(Loc, "expected label or encodable integer pc offset");
3733 case Match_MRS:
3734 return Error(Loc, "expected readable system register");
3735 case Match_MSR:
3736 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003737 case Match_InvalidComplexRotationEven:
3738 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3739 case Match_InvalidComplexRotationOdd:
3740 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003741 case Match_MnemonicFail: {
3742 std::string Suggestion = AArch64MnemonicSpellCheck(
3743 ((AArch64Operand &)*Operands[0]).getToken(),
3744 ComputeAvailableFeatures(STI->getFeatureBits()));
3745 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3746 }
Sander de Smalen367694b2018-04-20 08:54:49 +00003747 case Match_InvalidGPR64shifted8:
3748 return Error(Loc, "register must be x0..x30 or xzr, without shift");
3749 case Match_InvalidGPR64shifted16:
3750 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
3751 case Match_InvalidGPR64shifted32:
3752 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
3753 case Match_InvalidGPR64shifted64:
3754 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
3755 case Match_InvalidGPR64NoXZRshifted8:
3756 return Error(Loc, "register must be x0..x30 without shift");
3757 case Match_InvalidGPR64NoXZRshifted16:
3758 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
3759 case Match_InvalidGPR64NoXZRshifted32:
3760 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
3761 case Match_InvalidGPR64NoXZRshifted64:
3762 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00003763 case Match_InvalidZPR32UXTW8:
3764 case Match_InvalidZPR32SXTW8:
3765 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
3766 case Match_InvalidZPR32UXTW16:
3767 case Match_InvalidZPR32SXTW16:
3768 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
3769 case Match_InvalidZPR32UXTW32:
3770 case Match_InvalidZPR32SXTW32:
3771 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
3772 case Match_InvalidZPR32UXTW64:
3773 case Match_InvalidZPR32SXTW64:
3774 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
3775 case Match_InvalidZPR64UXTW8:
3776 case Match_InvalidZPR64SXTW8:
3777 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
3778 case Match_InvalidZPR64UXTW16:
3779 case Match_InvalidZPR64SXTW16:
3780 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
3781 case Match_InvalidZPR64UXTW32:
3782 case Match_InvalidZPR64SXTW32:
3783 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
3784 case Match_InvalidZPR64UXTW64:
3785 case Match_InvalidZPR64SXTW64:
3786 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
3787 case Match_InvalidZPR64LSL8:
3788 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
3789 case Match_InvalidZPR64LSL16:
3790 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
3791 case Match_InvalidZPR64LSL32:
3792 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
3793 case Match_InvalidZPR64LSL64:
3794 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003795 case Match_InvalidSVEPattern:
3796 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003797 case Match_InvalidSVEPredicateAnyReg:
3798 case Match_InvalidSVEPredicateBReg:
3799 case Match_InvalidSVEPredicateHReg:
3800 case Match_InvalidSVEPredicateSReg:
3801 case Match_InvalidSVEPredicateDReg:
3802 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003803 case Match_InvalidSVEPredicate3bAnyReg:
3804 case Match_InvalidSVEPredicate3bBReg:
3805 case Match_InvalidSVEPredicate3bHReg:
3806 case Match_InvalidSVEPredicate3bSReg:
3807 case Match_InvalidSVEPredicate3bDReg:
3808 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003809 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003810 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003811 }
3812}
3813
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003814static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003815
3816bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3817 OperandVector &Operands,
3818 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003819 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003820 bool MatchingInlineAsm) {
3821 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003822 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3823 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003824
David Blaikie960ea3f2014-06-08 16:18:35 +00003825 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003826 unsigned NumOperands = Operands.size();
3827
3828 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003829 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3830 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003831 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003832 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003833 if (Op3CE) {
3834 uint64_t Op3Val = Op3CE->getValue();
3835 uint64_t NewOp3Val = 0;
3836 uint64_t NewOp4Val = 0;
3837 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003838 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003839 NewOp3Val = (32 - Op3Val) & 0x1f;
3840 NewOp4Val = 31 - Op3Val;
3841 } else {
3842 NewOp3Val = (64 - Op3Val) & 0x3f;
3843 NewOp4Val = 63 - Op3Val;
3844 }
3845
Jim Grosbach13760bd2015-05-30 01:25:56 +00003846 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3847 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003848
3849 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003850 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003851 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003852 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3853 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3854 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003855 }
3856 }
Tim Northover03b99f62015-04-30 18:28:58 +00003857 } else if (NumOperands == 4 && Tok == "bfc") {
3858 // FIXME: Horrible hack to handle BFC->BFM alias.
3859 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3860 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3861 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3862
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003863 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003864 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3865 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3866
3867 if (LSBCE && WidthCE) {
3868 uint64_t LSB = LSBCE->getValue();
3869 uint64_t Width = WidthCE->getValue();
3870
3871 uint64_t RegWidth = 0;
3872 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3873 Op1.getReg()))
3874 RegWidth = 64;
3875 else
3876 RegWidth = 32;
3877
3878 if (LSB >= RegWidth)
3879 return Error(LSBOp.getStartLoc(),
3880 "expected integer in range [0, 31]");
3881 if (Width < 1 || Width > RegWidth)
3882 return Error(WidthOp.getStartLoc(),
3883 "expected integer in range [1, 32]");
3884
3885 uint64_t ImmR = 0;
3886 if (RegWidth == 32)
3887 ImmR = (32 - LSB) & 0x1f;
3888 else
3889 ImmR = (64 - LSB) & 0x3f;
3890
3891 uint64_t ImmS = Width - 1;
3892
3893 if (ImmR != 0 && ImmS >= ImmR)
3894 return Error(WidthOp.getStartLoc(),
3895 "requested insert overflows register");
3896
Jim Grosbach13760bd2015-05-30 01:25:56 +00003897 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3898 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003899 Operands[0] = AArch64Operand::CreateToken(
3900 "bfm", false, Op.getStartLoc(), getContext());
3901 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003902 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3903 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003904 Operands[3] = AArch64Operand::CreateImm(
3905 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3906 Operands.emplace_back(
3907 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3908 WidthOp.getEndLoc(), getContext()));
3909 }
3910 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003911 } else if (NumOperands == 5) {
3912 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3913 // UBFIZ -> UBFM aliases.
3914 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003915 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3916 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3917 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003918
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003919 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003920 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3921 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003922
3923 if (Op3CE && Op4CE) {
3924 uint64_t Op3Val = Op3CE->getValue();
3925 uint64_t Op4Val = Op4CE->getValue();
3926
3927 uint64_t RegWidth = 0;
3928 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003929 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003930 RegWidth = 64;
3931 else
3932 RegWidth = 32;
3933
3934 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003935 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003936 "expected integer in range [0, 31]");
3937 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003938 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003939 "expected integer in range [1, 32]");
3940
3941 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003942 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003943 NewOp3Val = (32 - Op3Val) & 0x1f;
3944 else
3945 NewOp3Val = (64 - Op3Val) & 0x3f;
3946
3947 uint64_t NewOp4Val = Op4Val - 1;
3948
3949 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003950 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003951 "requested insert overflows register");
3952
3953 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003954 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003955 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003956 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003957 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003958 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003959 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003960 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003961 if (Tok == "bfi")
3962 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003963 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003964 else if (Tok == "sbfiz")
3965 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003966 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003967 else if (Tok == "ubfiz")
3968 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003969 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003970 else
3971 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003972 }
3973 }
3974
3975 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3976 // UBFX -> UBFM aliases.
3977 } else if (NumOperands == 5 &&
3978 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003979 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3980 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3981 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003982
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003983 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003984 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3985 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003986
3987 if (Op3CE && Op4CE) {
3988 uint64_t Op3Val = Op3CE->getValue();
3989 uint64_t Op4Val = Op4CE->getValue();
3990
3991 uint64_t RegWidth = 0;
3992 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003993 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003994 RegWidth = 64;
3995 else
3996 RegWidth = 32;
3997
3998 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003999 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004000 "expected integer in range [0, 31]");
4001 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004002 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004003 "expected integer in range [1, 32]");
4004
4005 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4006
4007 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004008 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004009 "requested extract overflows register");
4010
4011 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004012 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004013 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004014 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004015 if (Tok == "bfxil")
4016 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004017 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004018 else if (Tok == "sbfx")
4019 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004020 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004021 else if (Tok == "ubfx")
4022 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004023 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004024 else
4025 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004026 }
4027 }
4028 }
4029 }
Tim Northover9097a072017-12-18 10:36:00 +00004030
4031 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4032 // instruction for FP registers correctly in some rare circumstances. Convert
4033 // it to a safe instruction and warn (because silently changing someone's
4034 // assembly is rude).
4035 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4036 NumOperands == 4 && Tok == "movi") {
4037 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4038 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4039 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4040 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4041 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4042 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4043 if (Suffix.lower() == ".2d" &&
4044 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4045 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4046 " correctly on this CPU, converting to equivalent movi.16b");
4047 // Switch the suffix to .16b.
4048 unsigned Idx = Op1.isToken() ? 1 : 2;
4049 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4050 getContext());
4051 }
4052 }
4053 }
4054
Tim Northover3b0846e2014-05-24 12:50:23 +00004055 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4056 // InstAlias can't quite handle this since the reg classes aren't
4057 // subclasses.
4058 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4059 // The source register can be Wn here, but the matcher expects a
4060 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004061 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004062 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004063 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004064 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4065 Op.getStartLoc(), Op.getEndLoc(),
4066 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004067 }
4068 }
4069 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4070 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004071 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004072 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004073 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004074 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004075 // The source register can be Wn here, but the matcher expects a
4076 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004077 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004078 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004079 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004080 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4081 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004082 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004083 }
4084 }
4085 }
4086 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4087 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004088 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004089 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004090 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004091 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004092 // The source register can be Wn here, but the matcher expects a
4093 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004094 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004095 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004096 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004097 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4098 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004099 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004100 }
4101 }
4102 }
4103
Tim Northover3b0846e2014-05-24 12:50:23 +00004104 MCInst Inst;
4105 // First try to match against the secondary set of tables containing the
4106 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4107 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004108 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004109
4110 // If that fails, try against the alternate table containing long-form NEON:
4111 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004112 if (MatchResult != Match_Success) {
4113 // But first, save the short-form match result: we can use it in case the
4114 // long-form match also fails.
4115 auto ShortFormNEONErrorInfo = ErrorInfo;
4116 auto ShortFormNEONMatchResult = MatchResult;
4117
Tim Northover3b0846e2014-05-24 12:50:23 +00004118 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004119 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004120
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004121 // Now, both matches failed, and the long-form match failed on the mnemonic
4122 // suffix token operand. The short-form match failure is probably more
4123 // relevant: use it instead.
4124 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004125 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004126 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4127 MatchResult = ShortFormNEONMatchResult;
4128 ErrorInfo = ShortFormNEONErrorInfo;
4129 }
4130 }
4131
Tim Northover3b0846e2014-05-24 12:50:23 +00004132 switch (MatchResult) {
4133 case Match_Success: {
4134 // Perform range checking and other semantic validations
4135 SmallVector<SMLoc, 8> OperandLocs;
4136 NumOperands = Operands.size();
4137 for (unsigned i = 1; i < NumOperands; ++i)
4138 OperandLocs.push_back(Operands[i]->getStartLoc());
4139 if (validateInstruction(Inst, OperandLocs))
4140 return true;
4141
4142 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004143 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004144 return false;
4145 }
4146 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004147 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004148 // Special case the error message for the very common case where only
4149 // a single subtarget feature is missing (neon, e.g.).
4150 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004151 uint64_t Mask = 1;
4152 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4153 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004154 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004155 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004156 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004157 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004158 }
4159 return Error(IDLoc, Msg);
4160 }
4161 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004162 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004163 case Match_InvalidOperand: {
4164 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004165
Tim Northover26bb14e2014-08-18 11:49:42 +00004166 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004167 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004168 return Error(IDLoc, "too few operands for instruction",
4169 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004170
David Blaikie960ea3f2014-06-08 16:18:35 +00004171 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004172 if (ErrorLoc == SMLoc())
4173 ErrorLoc = IDLoc;
4174 }
4175 // If the match failed on a suffix token operand, tweak the diagnostic
4176 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004177 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4178 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004179 MatchResult = Match_InvalidSuffix;
4180
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004181 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004182 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004183 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004184 case Match_InvalidMemoryIndexed1:
4185 case Match_InvalidMemoryIndexed2:
4186 case Match_InvalidMemoryIndexed4:
4187 case Match_InvalidMemoryIndexed8:
4188 case Match_InvalidMemoryIndexed16:
4189 case Match_InvalidCondCode:
4190 case Match_AddSubRegExtendSmall:
4191 case Match_AddSubRegExtendLarge:
4192 case Match_AddSubSecondSource:
4193 case Match_LogicalSecondSource:
4194 case Match_AddSubRegShift32:
4195 case Match_AddSubRegShift64:
4196 case Match_InvalidMovImm32Shift:
4197 case Match_InvalidMovImm64Shift:
4198 case Match_InvalidFPImm:
4199 case Match_InvalidMemoryWExtend8:
4200 case Match_InvalidMemoryWExtend16:
4201 case Match_InvalidMemoryWExtend32:
4202 case Match_InvalidMemoryWExtend64:
4203 case Match_InvalidMemoryWExtend128:
4204 case Match_InvalidMemoryXExtend8:
4205 case Match_InvalidMemoryXExtend16:
4206 case Match_InvalidMemoryXExtend32:
4207 case Match_InvalidMemoryXExtend64:
4208 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004209 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004210 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004211 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004212 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004213 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004214 case Match_InvalidMemoryIndexed4SImm7:
4215 case Match_InvalidMemoryIndexed8SImm7:
4216 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004217 case Match_InvalidMemoryIndexed8UImm5:
4218 case Match_InvalidMemoryIndexed4UImm5:
4219 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004220 case Match_InvalidMemoryIndexed1UImm6:
4221 case Match_InvalidMemoryIndexed2UImm6:
4222 case Match_InvalidMemoryIndexed4UImm6:
4223 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004224 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004225 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004226 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004227 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004228 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004229 case Match_InvalidImm0_7:
4230 case Match_InvalidImm0_15:
4231 case Match_InvalidImm0_31:
4232 case Match_InvalidImm0_63:
4233 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004234 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004235 case Match_InvalidImm0_65535:
4236 case Match_InvalidImm1_8:
4237 case Match_InvalidImm1_16:
4238 case Match_InvalidImm1_32:
4239 case Match_InvalidImm1_64:
4240 case Match_InvalidIndex1:
4241 case Match_InvalidIndexB:
4242 case Match_InvalidIndexH:
4243 case Match_InvalidIndexS:
4244 case Match_InvalidIndexD:
4245 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004246 case Match_InvalidComplexRotationEven:
4247 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004248 case Match_InvalidGPR64shifted8:
4249 case Match_InvalidGPR64shifted16:
4250 case Match_InvalidGPR64shifted32:
4251 case Match_InvalidGPR64shifted64:
4252 case Match_InvalidGPR64NoXZRshifted8:
4253 case Match_InvalidGPR64NoXZRshifted16:
4254 case Match_InvalidGPR64NoXZRshifted32:
4255 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004256 case Match_InvalidZPR32UXTW8:
4257 case Match_InvalidZPR32UXTW16:
4258 case Match_InvalidZPR32UXTW32:
4259 case Match_InvalidZPR32UXTW64:
4260 case Match_InvalidZPR32SXTW8:
4261 case Match_InvalidZPR32SXTW16:
4262 case Match_InvalidZPR32SXTW32:
4263 case Match_InvalidZPR32SXTW64:
4264 case Match_InvalidZPR64UXTW8:
4265 case Match_InvalidZPR64SXTW8:
4266 case Match_InvalidZPR64UXTW16:
4267 case Match_InvalidZPR64SXTW16:
4268 case Match_InvalidZPR64UXTW32:
4269 case Match_InvalidZPR64SXTW32:
4270 case Match_InvalidZPR64UXTW64:
4271 case Match_InvalidZPR64SXTW64:
4272 case Match_InvalidZPR64LSL8:
4273 case Match_InvalidZPR64LSL16:
4274 case Match_InvalidZPR64LSL32:
4275 case Match_InvalidZPR64LSL64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004276 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004277 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004278 case Match_InvalidSVEPredicateBReg:
4279 case Match_InvalidSVEPredicateHReg:
4280 case Match_InvalidSVEPredicateSReg:
4281 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004282 case Match_InvalidSVEPredicate3bAnyReg:
4283 case Match_InvalidSVEPredicate3bBReg:
4284 case Match_InvalidSVEPredicate3bHReg:
4285 case Match_InvalidSVEPredicate3bSReg:
4286 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004287 case Match_MSR:
4288 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004289 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004290 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004291 // Any time we get here, there's nothing fancy to do. Just get the
4292 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004293 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004294 if (ErrorLoc == SMLoc())
4295 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004296 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004297 }
4298 }
4299
4300 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004301}
4302
4303/// ParseDirective parses the arm specific directives
4304bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004305 const MCObjectFileInfo::Environment Format =
4306 getContext().getObjectFileInfo()->getObjectFileType();
4307 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4308 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004309
Tim Northover3b0846e2014-05-24 12:50:23 +00004310 StringRef IDVal = DirectiveID.getIdentifier();
4311 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004312 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004313 parseDirectiveArch(Loc);
4314 else if (IDVal == ".cpu")
4315 parseDirectiveCPU(Loc);
4316 else if (IDVal == ".hword")
4317 parseDirectiveWord(2, Loc);
4318 else if (IDVal == ".word")
4319 parseDirectiveWord(4, Loc);
4320 else if (IDVal == ".xword")
4321 parseDirectiveWord(8, Loc);
4322 else if (IDVal == ".tlsdesccall")
4323 parseDirectiveTLSDescCall(Loc);
4324 else if (IDVal == ".ltorg" || IDVal == ".pool")
4325 parseDirectiveLtorg(Loc);
4326 else if (IDVal == ".unreq")
4327 parseDirectiveUnreq(Loc);
4328 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004329 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004330 parseDirectiveInst(Loc);
4331 else
4332 return true;
4333 } else if (IDVal == MCLOHDirectiveName())
4334 parseDirectiveLOH(IDVal, Loc);
4335 else
4336 return true;
4337 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004338}
4339
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004340static const struct {
4341 const char *Name;
4342 const FeatureBitset Features;
4343} ExtensionMap[] = {
4344 { "crc", {AArch64::FeatureCRC} },
4345 { "crypto", {AArch64::FeatureCrypto} },
4346 { "fp", {AArch64::FeatureFPARMv8} },
4347 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004348 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004349 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004350
4351 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004352 { "pan", {} },
4353 { "lor", {} },
4354 { "rdma", {} },
4355 { "profile", {} },
4356};
4357
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004358/// parseDirectiveArch
4359/// ::= .arch token
4360bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4361 SMLoc ArchLoc = getLoc();
4362
4363 StringRef Arch, ExtensionString;
4364 std::tie(Arch, ExtensionString) =
4365 getParser().parseStringToEndOfStatement().trim().split('+');
4366
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004367 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4368 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004369 return Error(ArchLoc, "unknown arch name");
4370
4371 if (parseToken(AsmToken::EndOfStatement))
4372 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004373
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004374 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004375 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004376 AArch64::getArchFeatures(ID, AArch64Features);
4377 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4378 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004379
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004380 MCSubtargetInfo &STI = copySTI();
4381 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4382 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4383
4384 SmallVector<StringRef, 4> RequestedExtensions;
4385 if (!ExtensionString.empty())
4386 ExtensionString.split(RequestedExtensions, '+');
4387
4388 FeatureBitset Features = STI.getFeatureBits();
4389 for (auto Name : RequestedExtensions) {
4390 bool EnableFeature = true;
4391
4392 if (Name.startswith_lower("no")) {
4393 EnableFeature = false;
4394 Name = Name.substr(2);
4395 }
4396
4397 for (const auto &Extension : ExtensionMap) {
4398 if (Extension.Name != Name)
4399 continue;
4400
4401 if (Extension.Features.none())
4402 report_fatal_error("unsupported architectural extension: " + Name);
4403
4404 FeatureBitset ToggleFeatures = EnableFeature
4405 ? (~Features & Extension.Features)
4406 : ( Features & Extension.Features);
4407 uint64_t Features =
4408 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4409 setAvailableFeatures(Features);
4410 break;
4411 }
4412 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004413 return false;
4414}
4415
Tim Northover8b96c7e2017-05-15 19:42:15 +00004416static SMLoc incrementLoc(SMLoc L, int Offset) {
4417 return SMLoc::getFromPointer(L.getPointer() + Offset);
4418}
4419
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004420/// parseDirectiveCPU
4421/// ::= .cpu id
4422bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004423 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004424
4425 StringRef CPU, ExtensionString;
4426 std::tie(CPU, ExtensionString) =
4427 getParser().parseStringToEndOfStatement().trim().split('+');
4428
Nirav Davee833c6c2016-11-08 18:31:04 +00004429 if (parseToken(AsmToken::EndOfStatement))
4430 return true;
4431
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004432 SmallVector<StringRef, 4> RequestedExtensions;
4433 if (!ExtensionString.empty())
4434 ExtensionString.split(RequestedExtensions, '+');
4435
4436 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4437 // once that is tablegen'ed
4438 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004439 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004440 return false;
4441 }
4442
4443 MCSubtargetInfo &STI = copySTI();
4444 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004445 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004446
4447 FeatureBitset Features = STI.getFeatureBits();
4448 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004449 // Advance source location past '+'.
4450 CurLoc = incrementLoc(CurLoc, 1);
4451
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004452 bool EnableFeature = true;
4453
4454 if (Name.startswith_lower("no")) {
4455 EnableFeature = false;
4456 Name = Name.substr(2);
4457 }
4458
Tim Northover8b96c7e2017-05-15 19:42:15 +00004459 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004460 for (const auto &Extension : ExtensionMap) {
4461 if (Extension.Name != Name)
4462 continue;
4463
4464 if (Extension.Features.none())
4465 report_fatal_error("unsupported architectural extension: " + Name);
4466
4467 FeatureBitset ToggleFeatures = EnableFeature
4468 ? (~Features & Extension.Features)
4469 : ( Features & Extension.Features);
4470 uint64_t Features =
4471 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4472 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004473 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004474
4475 break;
4476 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004477
4478 if (!FoundExtension)
4479 Error(CurLoc, "unsupported architectural extension");
4480
4481 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004482 }
4483 return false;
4484}
4485
Tim Northover3b0846e2014-05-24 12:50:23 +00004486/// parseDirectiveWord
4487/// ::= .word [ expression (, expression)* ]
4488bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004489 auto parseOp = [&]() -> bool {
4490 const MCExpr *Value;
4491 if (getParser().parseExpression(Value))
4492 return true;
4493 getParser().getStreamer().EmitValue(Value, Size, L);
4494 return false;
4495 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004496
Nirav Davee833c6c2016-11-08 18:31:04 +00004497 if (parseMany(parseOp))
4498 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004499 return false;
4500}
4501
Chad Rosierdcd2a302014-10-22 20:35:57 +00004502/// parseDirectiveInst
4503/// ::= .inst opcode [, ...]
4504bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004505 if (getLexer().is(AsmToken::EndOfStatement))
4506 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004507
Nirav Davee833c6c2016-11-08 18:31:04 +00004508 auto parseOp = [&]() -> bool {
4509 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004510 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004511 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4512 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004513 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004514 if (check(!Value, L, "expected constant expression"))
4515 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004516 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004517 return false;
4518 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004519
Nirav Davee833c6c2016-11-08 18:31:04 +00004520 if (parseMany(parseOp))
4521 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004522 return false;
4523}
4524
Tim Northover3b0846e2014-05-24 12:50:23 +00004525// parseDirectiveTLSDescCall:
4526// ::= .tlsdesccall symbol
4527bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4528 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004529 if (check(getParser().parseIdentifier(Name), L,
4530 "expected symbol after directive") ||
4531 parseToken(AsmToken::EndOfStatement))
4532 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004533
Jim Grosbach6f482002015-05-18 18:43:14 +00004534 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004535 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4536 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004537
4538 MCInst Inst;
4539 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004540 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004541
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004542 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004543 return false;
4544}
4545
4546/// ::= .loh <lohName | lohId> label1, ..., labelN
4547/// The number of arguments depends on the loh identifier.
4548bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004549 MCLOHType Kind;
4550 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4551 if (getParser().getTok().isNot(AsmToken::Integer))
4552 return TokError("expected an identifier or a number in directive");
4553 // We successfully get a numeric value for the identifier.
4554 // Check if it is valid.
4555 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004556 if (Id <= -1U && !isValidMCLOHType(Id))
4557 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004558 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004559 } else {
4560 StringRef Name = getTok().getIdentifier();
4561 // We successfully parse an identifier.
4562 // Check if it is a recognized one.
4563 int Id = MCLOHNameToId(Name);
4564
4565 if (Id == -1)
4566 return TokError("invalid identifier in directive");
4567 Kind = (MCLOHType)Id;
4568 }
4569 // Consume the identifier.
4570 Lex();
4571 // Get the number of arguments of this LOH.
4572 int NbArgs = MCLOHIdToNbArgs(Kind);
4573
4574 assert(NbArgs != -1 && "Invalid number of arguments");
4575
4576 SmallVector<MCSymbol *, 3> Args;
4577 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4578 StringRef Name;
4579 if (getParser().parseIdentifier(Name))
4580 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004581 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004582
4583 if (Idx + 1 == NbArgs)
4584 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004585 if (parseToken(AsmToken::Comma,
4586 "unexpected token in '" + Twine(IDVal) + "' directive"))
4587 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004588 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004589 if (parseToken(AsmToken::EndOfStatement,
4590 "unexpected token in '" + Twine(IDVal) + "' directive"))
4591 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004592
4593 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4594 return false;
4595}
4596
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004597/// parseDirectiveLtorg
4598/// ::= .ltorg | .pool
4599bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004600 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4601 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004602 getTargetStreamer().emitCurrentConstantPool();
4603 return false;
4604}
4605
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004606/// parseDirectiveReq
4607/// ::= name .req registername
4608bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004609 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004610 Parser.Lex(); // Eat the '.req' token.
4611 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004612 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004613 unsigned RegNum;
4614 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004615
Sander de Smalen50d87022018-04-19 07:35:08 +00004616 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004617 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004618 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004619 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004620
Sander de Smalen50d87022018-04-19 07:35:08 +00004621 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004622 return true;
4623
Sander de Smalen50d87022018-04-19 07:35:08 +00004624 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004625 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004626 }
4627
Sander de Smalen50d87022018-04-19 07:35:08 +00004628 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004629 StringRef Kind;
4630 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004631 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004632 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004633
Sander de Smalen50d87022018-04-19 07:35:08 +00004634 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004635 return true;
4636
Sander de Smalen50d87022018-04-19 07:35:08 +00004637 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004638 return Error(SRegLoc,
4639 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004640 }
4641
Sander de Smalen50d87022018-04-19 07:35:08 +00004642 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00004643 StringRef Kind;
4644 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004645 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004646
Sander de Smalen50d87022018-04-19 07:35:08 +00004647 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00004648 return true;
4649
Sander de Smalen50d87022018-04-19 07:35:08 +00004650 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00004651 return Error(SRegLoc,
4652 "sve predicate register without type specifier expected");
4653 }
4654
Sander de Smalen50d87022018-04-19 07:35:08 +00004655 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00004656 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004657
4658 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004659 if (parseToken(AsmToken::EndOfStatement,
4660 "unexpected input in .req directive"))
4661 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004662
Sander de Smalen8e607342017-11-15 15:44:43 +00004663 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004664 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004665 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4666
Nirav Dave2364748a2016-09-16 18:30:20 +00004667 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004668}
4669
4670/// parseDirectiveUneq
4671/// ::= .unreq registername
4672bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004673 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004674 if (getTok().isNot(AsmToken::Identifier))
4675 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004676 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4677 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004678 if (parseToken(AsmToken::EndOfStatement))
4679 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004680 return false;
4681}
4682
Tim Northover3b0846e2014-05-24 12:50:23 +00004683bool
4684AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4685 AArch64MCExpr::VariantKind &ELFRefKind,
4686 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4687 int64_t &Addend) {
4688 ELFRefKind = AArch64MCExpr::VK_INVALID;
4689 DarwinRefKind = MCSymbolRefExpr::VK_None;
4690 Addend = 0;
4691
4692 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4693 ELFRefKind = AE->getKind();
4694 Expr = AE->getSubExpr();
4695 }
4696
4697 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4698 if (SE) {
4699 // It's a simple symbol reference with no addend.
4700 DarwinRefKind = SE->getKind();
4701 return true;
4702 }
4703
4704 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4705 if (!BE)
4706 return false;
4707
4708 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4709 if (!SE)
4710 return false;
4711 DarwinRefKind = SE->getKind();
4712
4713 if (BE->getOpcode() != MCBinaryExpr::Add &&
4714 BE->getOpcode() != MCBinaryExpr::Sub)
4715 return false;
4716
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004717 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004718 // on here than we can deal with.
4719 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4720 if (!AddendExpr)
4721 return false;
4722
4723 Addend = AddendExpr->getValue();
4724 if (BE->getOpcode() == MCBinaryExpr::Sub)
4725 Addend = -Addend;
4726
4727 // It's some symbol reference + a constant addend, but really
4728 // shouldn't use both Darwin and ELF syntax.
4729 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4730 DarwinRefKind == MCSymbolRefExpr::VK_None;
4731}
4732
4733/// Force static initialization.
4734extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004735 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4736 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4737 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004738}
4739
4740#define GET_REGISTER_MATCHER
4741#define GET_SUBTARGET_FEATURE_NAME
4742#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004743#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004744#include "AArch64GenAsmMatcher.inc"
4745
4746// Define this matcher function after the auto-generated include so we
4747// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004748unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004749 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004750 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004751 // If the kind is a token for a literal immediate, check if our asm
4752 // operand matches. This is for InstAliases which have a fixed-value
4753 // immediate in the syntax.
4754 int64_t ExpectedVal;
4755 switch (Kind) {
4756 default:
4757 return Match_InvalidOperand;
4758 case MCK__35_0:
4759 ExpectedVal = 0;
4760 break;
4761 case MCK__35_1:
4762 ExpectedVal = 1;
4763 break;
4764 case MCK__35_12:
4765 ExpectedVal = 12;
4766 break;
4767 case MCK__35_16:
4768 ExpectedVal = 16;
4769 break;
4770 case MCK__35_2:
4771 ExpectedVal = 2;
4772 break;
4773 case MCK__35_24:
4774 ExpectedVal = 24;
4775 break;
4776 case MCK__35_3:
4777 ExpectedVal = 3;
4778 break;
4779 case MCK__35_32:
4780 ExpectedVal = 32;
4781 break;
4782 case MCK__35_4:
4783 ExpectedVal = 4;
4784 break;
4785 case MCK__35_48:
4786 ExpectedVal = 48;
4787 break;
4788 case MCK__35_6:
4789 ExpectedVal = 6;
4790 break;
4791 case MCK__35_64:
4792 ExpectedVal = 64;
4793 break;
4794 case MCK__35_8:
4795 ExpectedVal = 8;
4796 break;
4797 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004798 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004799 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004800 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004801 if (!CE)
4802 return Match_InvalidOperand;
4803 if (CE->getValue() == ExpectedVal)
4804 return Match_Success;
4805 return Match_InvalidOperand;
4806}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004807
Alex Bradbury58eba092016-11-01 16:32:05 +00004808OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004809AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4810
4811 SMLoc S = getLoc();
4812
4813 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4814 Error(S, "expected register");
4815 return MatchOperand_ParseFail;
4816 }
4817
Sander de Smalen50d87022018-04-19 07:35:08 +00004818 unsigned FirstReg;
4819 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
4820 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004821 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00004822
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004823 const MCRegisterClass &WRegClass =
4824 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4825 const MCRegisterClass &XRegClass =
4826 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4827
4828 bool isXReg = XRegClass.contains(FirstReg),
4829 isWReg = WRegClass.contains(FirstReg);
4830 if (!isXReg && !isWReg) {
4831 Error(S, "expected first even register of a "
4832 "consecutive same-size even/odd register pair");
4833 return MatchOperand_ParseFail;
4834 }
4835
4836 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4837 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4838
4839 if (FirstEncoding & 0x1) {
4840 Error(S, "expected first even register of a "
4841 "consecutive same-size even/odd register pair");
4842 return MatchOperand_ParseFail;
4843 }
4844
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004845 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00004846 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004847 return MatchOperand_ParseFail;
4848 }
4849 // Eat the comma
4850 getParser().Lex();
4851
4852 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00004853 unsigned SecondReg;
4854 Res = tryParseScalarRegister(SecondReg);
4855 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004856 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004857
Eugene Zelenko049b0172017-01-06 00:30:53 +00004858 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004859 (isXReg && !XRegClass.contains(SecondReg)) ||
4860 (isWReg && !WRegClass.contains(SecondReg))) {
4861 Error(E,"expected second odd register of a "
4862 "consecutive same-size even/odd register pair");
4863 return MatchOperand_ParseFail;
4864 }
Joel Jones504bf332016-10-24 13:37:13 +00004865
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004866 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004867 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004868 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4869 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4870 } else {
4871 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4872 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4873 }
4874
Florian Hahnc4422242017-11-07 13:07:50 +00004875 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4876 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004877
4878 return MatchOperand_Success;
4879}
Florian Hahn91f11e52017-11-07 16:45:48 +00004880
Sander de Smaleneb896b12018-04-25 09:26:47 +00004881template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00004882OperandMatchResultTy
4883AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004884 const SMLoc S = getLoc();
4885 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00004886 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00004887 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004888
Sander de Smalen8e607342017-11-15 15:44:43 +00004889 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004890 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004891
4892 if (Res != MatchOperand_Success)
4893 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004894
4895 if (ParseSuffix && Kind.empty())
4896 return MatchOperand_NoMatch;
4897
Sander de Smalen73937b72018-04-11 07:36:10 +00004898 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
4899 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00004900 return MatchOperand_NoMatch;
4901
Sander de Smalen73937b72018-04-11 07:36:10 +00004902 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00004903
4904 // No shift/extend is the default.
4905 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
4906 Operands.push_back(AArch64Operand::CreateVectorReg(
4907 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
4908
4909 return MatchOperand_Success;
4910 }
4911
4912 // Eat the comma
4913 getParser().Lex();
4914
4915 // Match the shift
4916 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
4917 Res = tryParseOptionalShiftExtend(ExtOpnd);
4918 if (Res != MatchOperand_Success)
4919 return Res;
4920
4921 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00004922 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00004923 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
4924 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
4925 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00004926
4927 return MatchOperand_Success;
4928}
Sander de Smalen245e0e62018-01-22 10:46:00 +00004929
4930OperandMatchResultTy
4931AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
4932 MCAsmParser &Parser = getParser();
4933
4934 SMLoc SS = getLoc();
4935 const AsmToken &TokE = Parser.getTok();
4936 bool IsHash = TokE.is(AsmToken::Hash);
4937
4938 if (!IsHash && TokE.isNot(AsmToken::Identifier))
4939 return MatchOperand_NoMatch;
4940
4941 int64_t Pattern;
4942 if (IsHash) {
4943 Parser.Lex(); // Eat hash
4944
4945 // Parse the immediate operand.
4946 const MCExpr *ImmVal;
4947 SS = getLoc();
4948 if (Parser.parseExpression(ImmVal))
4949 return MatchOperand_ParseFail;
4950
4951 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4952 if (!MCE)
4953 return MatchOperand_ParseFail;
4954
4955 Pattern = MCE->getValue();
4956 } else {
4957 // Parse the pattern
4958 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
4959 if (!Pat)
4960 return MatchOperand_NoMatch;
4961
4962 Parser.Lex();
4963 Pattern = Pat->Encoding;
4964 assert(Pattern >= 0 && Pattern < 32);
4965 }
4966
4967 Operands.push_back(
4968 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
4969 SS, getLoc(), getContext()));
4970
4971 return MatchOperand_Success;
4972}