blob: c648a8db6ecedc3b23979d9c2cec8ccb486acaf5 [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,
880 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +0000881 DiagnosticPredicate isSVEVectorRegWithShiftExtend() const {
882 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
883 return DiagnosticPredicateTy::NoMatch;
884
885 if (isSVEVectorRegOfWidth<ElementWidth, Class>() &&
886 ShiftExtendTy == getShiftExtendType() &&
887 getShiftExtendAmount() == Log2_32(ShiftWidth / 8))
888 return DiagnosticPredicateTy::Match;
889
890 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +0000891 }
892
Tim Northover3b0846e2014-05-24 12:50:23 +0000893 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000894 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000895 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
896 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000897
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000898 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000899 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000900 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
901 Reg.RegNum);
902 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000903
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000904 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000905 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000906 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
907 Reg.RegNum);
908 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000909
Sam Parker5f934642017-08-31 09:27:04 +0000910 template<int64_t Angle, int64_t Remainder>
911 bool isComplexRotation() const {
912 if (!isImm()) return false;
913
914 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
915 if (!CE) return false;
916 uint64_t Value = CE->getValue();
917
918 return (Value % Angle == Remainder && Value <= 270);
919 }
920
Sander de Smalen149916d2018-04-20 07:24:20 +0000921 template <unsigned RegClassID> bool isGPR64() const {
922 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
923 AArch64MCRegisterClasses[RegClassID].contains(getReg());
924 }
925
926 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +0000927 DiagnosticPredicate isGPR64WithShiftExtend() const {
928 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
929 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +0000930
Sander de Smalenfe17a782018-04-26 12:54:42 +0000931 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
932 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
933 return DiagnosticPredicateTy::Match;
934 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +0000935 }
936
Tim Northover3b0846e2014-05-24 12:50:23 +0000937 /// Is this a vector list with the type implicit (presumably attached to the
938 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +0000939 template <RegKind VectorKind, unsigned NumRegs>
940 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000941 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +0000942 VectorList.NumElements == 0 &&
943 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000944 }
945
Sander de Smalen650234b2018-04-12 11:40:52 +0000946 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
947 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +0000948 bool isTypedVectorList() const {
949 if (Kind != k_VectorList)
950 return false;
951 if (VectorList.Count != NumRegs)
952 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +0000953 if (VectorList.RegisterKind != VectorKind)
954 return false;
955 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +0000956 return false;
957 return VectorList.NumElements == NumElements;
958 }
959
960 bool isVectorIndex1() const {
961 return Kind == k_VectorIndex && VectorIndex.Val == 1;
962 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000963
Tim Northover3b0846e2014-05-24 12:50:23 +0000964 bool isVectorIndexB() const {
965 return Kind == k_VectorIndex && VectorIndex.Val < 16;
966 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000967
Tim Northover3b0846e2014-05-24 12:50:23 +0000968 bool isVectorIndexH() const {
969 return Kind == k_VectorIndex && VectorIndex.Val < 8;
970 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000971
Tim Northover3b0846e2014-05-24 12:50:23 +0000972 bool isVectorIndexS() const {
973 return Kind == k_VectorIndex && VectorIndex.Val < 4;
974 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000975
Tim Northover3b0846e2014-05-24 12:50:23 +0000976 bool isVectorIndexD() const {
977 return Kind == k_VectorIndex && VectorIndex.Val < 2;
978 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000979
Tim Northover3b0846e2014-05-24 12:50:23 +0000980 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000981
Tim Northover3b0846e2014-05-24 12:50:23 +0000982 bool isTokenEqual(StringRef Str) const {
983 return Kind == k_Token && getToken() == Str;
984 }
985 bool isSysCR() const { return Kind == k_SysCR; }
986 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000987 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000988 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
989 bool isShifter() const {
990 if (!isShiftExtend())
991 return false;
992
993 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
994 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
995 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
996 ST == AArch64_AM::MSL);
997 }
998 bool isExtend() const {
999 if (!isShiftExtend())
1000 return false;
1001
1002 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1003 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1004 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1005 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1006 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1007 ET == AArch64_AM::LSL) &&
1008 getShiftExtendAmount() <= 4;
1009 }
1010
1011 bool isExtend64() const {
1012 if (!isExtend())
1013 return false;
1014 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1015 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1016 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1017 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001018
Tim Northover3b0846e2014-05-24 12:50:23 +00001019 bool isExtendLSL64() const {
1020 if (!isExtend())
1021 return false;
1022 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1023 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1024 ET == AArch64_AM::LSL) &&
1025 getShiftExtendAmount() <= 4;
1026 }
1027
1028 template<int Width> bool isMemXExtend() const {
1029 if (!isExtend())
1030 return false;
1031 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1032 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1033 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1034 getShiftExtendAmount() == 0);
1035 }
1036
1037 template<int Width> bool isMemWExtend() const {
1038 if (!isExtend())
1039 return false;
1040 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1041 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1042 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1043 getShiftExtendAmount() == 0);
1044 }
1045
1046 template <unsigned width>
1047 bool isArithmeticShifter() const {
1048 if (!isShifter())
1049 return false;
1050
1051 // An arithmetic shifter is LSL, LSR, or ASR.
1052 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1053 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1054 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1055 }
1056
1057 template <unsigned width>
1058 bool isLogicalShifter() const {
1059 if (!isShifter())
1060 return false;
1061
1062 // A logical shifter is LSL, LSR, ASR or ROR.
1063 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1064 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1065 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1066 getShiftExtendAmount() < width;
1067 }
1068
1069 bool isMovImm32Shifter() const {
1070 if (!isShifter())
1071 return false;
1072
1073 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1074 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1075 if (ST != AArch64_AM::LSL)
1076 return false;
1077 uint64_t Val = getShiftExtendAmount();
1078 return (Val == 0 || Val == 16);
1079 }
1080
1081 bool isMovImm64Shifter() const {
1082 if (!isShifter())
1083 return false;
1084
1085 // A MOVi shifter is LSL of 0 or 16.
1086 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1087 if (ST != AArch64_AM::LSL)
1088 return false;
1089 uint64_t Val = getShiftExtendAmount();
1090 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1091 }
1092
1093 bool isLogicalVecShifter() const {
1094 if (!isShifter())
1095 return false;
1096
1097 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1098 unsigned Shift = getShiftExtendAmount();
1099 return getShiftExtendType() == AArch64_AM::LSL &&
1100 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1101 }
1102
1103 bool isLogicalVecHalfWordShifter() const {
1104 if (!isLogicalVecShifter())
1105 return false;
1106
1107 // A logical vector shifter is a left shift by 0 or 8.
1108 unsigned Shift = getShiftExtendAmount();
1109 return getShiftExtendType() == AArch64_AM::LSL &&
1110 (Shift == 0 || Shift == 8);
1111 }
1112
1113 bool isMoveVecShifter() const {
1114 if (!isShiftExtend())
1115 return false;
1116
1117 // A logical vector shifter is a left shift by 8 or 16.
1118 unsigned Shift = getShiftExtendAmount();
1119 return getShiftExtendType() == AArch64_AM::MSL &&
1120 (Shift == 8 || Shift == 16);
1121 }
1122
1123 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1124 // to LDUR/STUR when the offset is not legal for the former but is for
1125 // the latter. As such, in addition to checking for being a legal unscaled
1126 // address, also check that it is not a legal scaled address. This avoids
1127 // ambiguity in the matcher.
1128 template<int Width>
1129 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001130 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001131 }
1132
1133 bool isAdrpLabel() const {
1134 // Validation was handled during parsing, so we just sanity check that
1135 // something didn't go haywire.
1136 if (!isImm())
1137 return false;
1138
1139 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1140 int64_t Val = CE->getValue();
1141 int64_t Min = - (4096 * (1LL << (21 - 1)));
1142 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1143 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1144 }
1145
1146 return true;
1147 }
1148
1149 bool isAdrLabel() const {
1150 // Validation was handled during parsing, so we just sanity check that
1151 // something didn't go haywire.
1152 if (!isImm())
1153 return false;
1154
1155 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1156 int64_t Val = CE->getValue();
1157 int64_t Min = - (1LL << (21 - 1));
1158 int64_t Max = ((1LL << (21 - 1)) - 1);
1159 return Val >= Min && Val <= Max;
1160 }
1161
1162 return true;
1163 }
1164
1165 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1166 // Add as immediates when possible. Null MCExpr = 0.
1167 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001168 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001169 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001170 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001171 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001172 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001173 }
1174
1175 void addRegOperands(MCInst &Inst, unsigned N) const {
1176 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001177 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001178 }
1179
1180 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1181 assert(N == 1 && "Invalid number of operands!");
1182 assert(
1183 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1184
1185 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1186 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1187 RI->getEncodingValue(getReg()));
1188
Jim Grosbache9119e42015-05-13 18:37:00 +00001189 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001190 }
1191
1192 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1193 assert(N == 1 && "Invalid number of operands!");
1194 assert(
1195 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001196 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001197 }
1198
1199 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1200 assert(N == 1 && "Invalid number of operands!");
1201 assert(
1202 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001203 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001204 }
1205
1206 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1207 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001208 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001209 }
1210
Sander de Smalen525e3222018-04-12 13:19:32 +00001211 enum VecListIndexType {
1212 VecListIdx_DReg = 0,
1213 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001214 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001215 };
1216
1217 template <VecListIndexType RegTy, unsigned NumRegs>
1218 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001219 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001220 static const unsigned FirstRegs[][5] = {
1221 /* DReg */ { AArch64::Q0,
1222 AArch64::D0, AArch64::D0_D1,
1223 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1224 /* QReg */ { AArch64::Q0,
1225 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001226 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1227 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001228 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001229 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001230 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001231
Sander de Smalen7a210db2018-04-16 10:46:18 +00001232 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1233 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001234
Sander de Smalen525e3222018-04-12 13:19:32 +00001235 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1236 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1237 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001238 }
1239
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001240 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001241 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001242 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001243 }
1244
1245 void addImmOperands(MCInst &Inst, unsigned N) const {
1246 assert(N == 1 && "Invalid number of operands!");
1247 // If this is a pageoff symrefexpr with an addend, adjust the addend
1248 // to be only the page-offset portion. Otherwise, just add the expr
1249 // as-is.
1250 addExpr(Inst, getImm());
1251 }
1252
1253 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1254 assert(N == 2 && "Invalid number of operands!");
1255 if (isShiftedImm()) {
1256 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001257 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001258 } else {
1259 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001260 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001261 }
1262 }
1263
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001264 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1265 assert(N == 2 && "Invalid number of operands!");
1266
1267 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1268 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1269 int64_t Val = -CE->getValue();
1270 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1271
1272 Inst.addOperand(MCOperand::createImm(Val));
1273 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1274 }
1275
Tim Northover3b0846e2014-05-24 12:50:23 +00001276 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1277 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001278 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001279 }
1280
1281 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1282 assert(N == 1 && "Invalid number of operands!");
1283 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1284 if (!MCE)
1285 addExpr(Inst, getImm());
1286 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001287 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001288 }
1289
1290 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1291 addImmOperands(Inst, N);
1292 }
1293
1294 template<int Scale>
1295 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1296 assert(N == 1 && "Invalid number of operands!");
1297 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1298
1299 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001300 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001301 return;
1302 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001303 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001304 }
1305
Sander de Smalen5c625982018-04-13 12:56:14 +00001306 template <int Scale>
1307 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1308 assert(N == 1 && "Invalid number of operands!");
1309 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1310 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1311 }
1312
Sander de Smalena1c259c2018-01-29 13:05:38 +00001313 template <typename T>
1314 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001315 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001316 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001317 typename std::make_unsigned<T>::type Val = MCE->getValue();
1318 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001319 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001320 }
1321
Sander de Smalena1c259c2018-01-29 13:05:38 +00001322 template <typename T>
1323 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001324 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001325 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001326 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1327 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001328 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001329 }
1330
Tim Northover3b0846e2014-05-24 12:50:23 +00001331 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1332 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001333 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001334 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001335 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001336 }
1337
1338 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1339 // Branch operands don't encode the low bits, so shift them off
1340 // here. If it's a label, however, just put it on directly as there's
1341 // not enough information now to do anything.
1342 assert(N == 1 && "Invalid number of operands!");
1343 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1344 if (!MCE) {
1345 addExpr(Inst, getImm());
1346 return;
1347 }
1348 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001349 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001350 }
1351
1352 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1353 // Branch operands don't encode the low bits, so shift them off
1354 // here. If it's a label, however, just put it on directly as there's
1355 // not enough information now to do anything.
1356 assert(N == 1 && "Invalid number of operands!");
1357 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1358 if (!MCE) {
1359 addExpr(Inst, getImm());
1360 return;
1361 }
1362 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001363 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001364 }
1365
1366 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1367 // Branch operands don't encode the low bits, so shift them off
1368 // here. If it's a label, however, just put it on directly as there's
1369 // not enough information now to do anything.
1370 assert(N == 1 && "Invalid number of operands!");
1371 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1372 if (!MCE) {
1373 addExpr(Inst, getImm());
1374 return;
1375 }
1376 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001377 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001378 }
1379
1380 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1381 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001382 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001383 }
1384
1385 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1386 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001387 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001388 }
1389
1390 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1391 assert(N == 1 && "Invalid number of operands!");
1392
Jim Grosbache9119e42015-05-13 18:37:00 +00001393 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001394 }
1395
1396 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1397 assert(N == 1 && "Invalid number of operands!");
1398
Jim Grosbache9119e42015-05-13 18:37:00 +00001399 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001400 }
1401
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001402 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1403 assert(N == 1 && "Invalid number of operands!");
1404
1405 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1406 }
1407
1408 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001409 assert(N == 1 && "Invalid number of operands!");
1410
Jim Grosbache9119e42015-05-13 18:37:00 +00001411 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001412 }
1413
1414 void addSysCROperands(MCInst &Inst, unsigned N) const {
1415 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001416 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001417 }
1418
1419 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1420 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001421 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001422 }
1423
Oliver Stannarda34e4702015-12-01 10:48:51 +00001424 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1425 assert(N == 1 && "Invalid number of operands!");
1426 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1427 }
1428
Tim Northover3b0846e2014-05-24 12:50:23 +00001429 void addShifterOperands(MCInst &Inst, unsigned N) const {
1430 assert(N == 1 && "Invalid number of operands!");
1431 unsigned Imm =
1432 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001433 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 }
1435
1436 void addExtendOperands(MCInst &Inst, unsigned N) const {
1437 assert(N == 1 && "Invalid number of operands!");
1438 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1439 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1440 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001441 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001442 }
1443
1444 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1445 assert(N == 1 && "Invalid number of operands!");
1446 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1447 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1448 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001449 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001450 }
1451
1452 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1453 assert(N == 2 && "Invalid number of operands!");
1454 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1455 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001456 Inst.addOperand(MCOperand::createImm(IsSigned));
1457 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001458 }
1459
1460 // For 8-bit load/store instructions with a register offset, both the
1461 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1462 // they're disambiguated by whether the shift was explicit or implicit rather
1463 // than its size.
1464 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1465 assert(N == 2 && "Invalid number of operands!");
1466 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1467 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001468 Inst.addOperand(MCOperand::createImm(IsSigned));
1469 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001470 }
1471
1472 template<int Shift>
1473 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1474 assert(N == 1 && "Invalid number of operands!");
1475
1476 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1477 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001478 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001479 }
1480
1481 template<int Shift>
1482 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1483 assert(N == 1 && "Invalid number of operands!");
1484
1485 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1486 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001487 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001488 }
1489
Sam Parker5f934642017-08-31 09:27:04 +00001490 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1491 assert(N == 1 && "Invalid number of operands!");
1492 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1493 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1494 }
1495
1496 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1497 assert(N == 1 && "Invalid number of operands!");
1498 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1499 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1500 }
1501
Tim Northover3b0846e2014-05-24 12:50:23 +00001502 void print(raw_ostream &OS) const override;
1503
David Blaikie960ea3f2014-06-08 16:18:35 +00001504 static std::unique_ptr<AArch64Operand>
1505 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1506 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001507 Op->Tok.Data = Str.data();
1508 Op->Tok.Length = Str.size();
1509 Op->Tok.IsSuffix = IsSuffix;
1510 Op->StartLoc = S;
1511 Op->EndLoc = S;
1512 return Op;
1513 }
1514
David Blaikie960ea3f2014-06-08 16:18:35 +00001515 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001516 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
1517 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1518 unsigned ShiftAmount = 0,
1519 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001520 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001521 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001522 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001523 Op->Reg.ElementWidth = 0;
1524 Op->Reg.ShiftExtend.Type = ExtTy;
1525 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1526 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001527 Op->StartLoc = S;
1528 Op->EndLoc = E;
1529 return Op;
1530 }
1531
David Blaikie960ea3f2014-06-08 16:18:35 +00001532 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001533 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001534 SMLoc S, SMLoc E, MCContext &Ctx,
1535 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1536 unsigned ShiftAmount = 0,
1537 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001538 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1539 Kind == RegKind::SVEPredicateVector) &&
1540 "Invalid vector kind");
Sander de Smalen149916d2018-04-20 07:24:20 +00001541 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, ExtTy, ShiftAmount,
1542 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001543 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001544 return Op;
1545 }
1546
1547 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001548 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001549 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1550 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001551 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001552 Op->VectorList.RegNum = RegNum;
1553 Op->VectorList.Count = Count;
1554 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001555 Op->VectorList.ElementWidth = ElementWidth;
1556 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001557 Op->StartLoc = S;
1558 Op->EndLoc = E;
1559 return Op;
1560 }
1561
David Blaikie960ea3f2014-06-08 16:18:35 +00001562 static std::unique_ptr<AArch64Operand>
1563 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1564 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001565 Op->VectorIndex.Val = Idx;
1566 Op->StartLoc = S;
1567 Op->EndLoc = E;
1568 return Op;
1569 }
1570
David Blaikie960ea3f2014-06-08 16:18:35 +00001571 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1572 SMLoc E, MCContext &Ctx) {
1573 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001574 Op->Imm.Val = Val;
1575 Op->StartLoc = S;
1576 Op->EndLoc = E;
1577 return Op;
1578 }
1579
David Blaikie960ea3f2014-06-08 16:18:35 +00001580 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1581 unsigned ShiftAmount,
1582 SMLoc S, SMLoc E,
1583 MCContext &Ctx) {
1584 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001585 Op->ShiftedImm .Val = Val;
1586 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1587 Op->StartLoc = S;
1588 Op->EndLoc = E;
1589 return Op;
1590 }
1591
David Blaikie960ea3f2014-06-08 16:18:35 +00001592 static std::unique_ptr<AArch64Operand>
1593 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1594 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001595 Op->CondCode.Code = Code;
1596 Op->StartLoc = S;
1597 Op->EndLoc = E;
1598 return Op;
1599 }
1600
David Blaikie960ea3f2014-06-08 16:18:35 +00001601 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1602 MCContext &Ctx) {
1603 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001604 Op->FPImm.Val = Val;
1605 Op->StartLoc = S;
1606 Op->EndLoc = S;
1607 return Op;
1608 }
1609
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001610 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1611 StringRef Str,
1612 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001613 MCContext &Ctx) {
1614 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001615 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001616 Op->Barrier.Data = Str.data();
1617 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001618 Op->StartLoc = S;
1619 Op->EndLoc = S;
1620 return Op;
1621 }
1622
Tim Northover7cd58932015-01-22 17:23:04 +00001623 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1624 uint32_t MRSReg,
1625 uint32_t MSRReg,
1626 uint32_t PStateField,
1627 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001628 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001629 Op->SysReg.Data = Str.data();
1630 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001631 Op->SysReg.MRSReg = MRSReg;
1632 Op->SysReg.MSRReg = MSRReg;
1633 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001634 Op->StartLoc = S;
1635 Op->EndLoc = S;
1636 return Op;
1637 }
1638
David Blaikie960ea3f2014-06-08 16:18:35 +00001639 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1640 SMLoc E, MCContext &Ctx) {
1641 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001642 Op->SysCRImm.Val = Val;
1643 Op->StartLoc = S;
1644 Op->EndLoc = E;
1645 return Op;
1646 }
1647
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001648 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1649 StringRef Str,
1650 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001651 MCContext &Ctx) {
1652 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001653 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001654 Op->Barrier.Data = Str.data();
1655 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001656 Op->StartLoc = S;
1657 Op->EndLoc = S;
1658 return Op;
1659 }
1660
Oliver Stannarda34e4702015-12-01 10:48:51 +00001661 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1662 StringRef Str,
1663 SMLoc S,
1664 MCContext &Ctx) {
1665 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1666 Op->PSBHint.Val = Val;
1667 Op->PSBHint.Data = Str.data();
1668 Op->PSBHint.Length = Str.size();
1669 Op->StartLoc = S;
1670 Op->EndLoc = S;
1671 return Op;
1672 }
1673
David Blaikie960ea3f2014-06-08 16:18:35 +00001674 static std::unique_ptr<AArch64Operand>
1675 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1676 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1677 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001678 Op->ShiftExtend.Type = ShOp;
1679 Op->ShiftExtend.Amount = Val;
1680 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1681 Op->StartLoc = S;
1682 Op->EndLoc = E;
1683 return Op;
1684 }
1685};
1686
1687} // end anonymous namespace.
1688
1689void AArch64Operand::print(raw_ostream &OS) const {
1690 switch (Kind) {
1691 case k_FPImm:
1692 OS << "<fpimm " << getFPImm() << "("
1693 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1694 break;
1695 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001696 StringRef Name = getBarrierName();
1697 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001698 OS << "<barrier " << Name << ">";
1699 else
1700 OS << "<barrier invalid #" << getBarrier() << ">";
1701 break;
1702 }
1703 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001704 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001705 break;
1706 case k_ShiftedImm: {
1707 unsigned Shift = getShiftedImmShift();
1708 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001709 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001710 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1711 break;
1712 }
1713 case k_CondCode:
1714 OS << "<condcode " << getCondCode() << ">";
1715 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001716 case k_VectorList: {
1717 OS << "<vectorlist ";
1718 unsigned Reg = getVectorListStart();
1719 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1720 OS << Reg + i << " ";
1721 OS << ">";
1722 break;
1723 }
1724 case k_VectorIndex:
1725 OS << "<vectorindex " << getVectorIndex() << ">";
1726 break;
1727 case k_SysReg:
1728 OS << "<sysreg: " << getSysReg() << '>';
1729 break;
1730 case k_Token:
1731 OS << "'" << getToken() << "'";
1732 break;
1733 case k_SysCR:
1734 OS << "c" << getSysCR();
1735 break;
1736 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001737 StringRef Name = getPrefetchName();
1738 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001739 OS << "<prfop " << Name << ">";
1740 else
1741 OS << "<prfop invalid #" << getPrefetch() << ">";
1742 break;
1743 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001744 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001745 OS << getPSBHintName();
1746 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00001747 case k_Register:
1748 OS << "<register " << getReg() << ">";
1749 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
1750 break;
1751 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001752 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001753 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1754 << getShiftExtendAmount();
1755 if (!hasShiftExtendAmount())
1756 OS << "<imp>";
1757 OS << '>';
1758 break;
1759 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001760}
1761
1762/// @name Auto-generated Match Functions
1763/// {
1764
1765static unsigned MatchRegisterName(StringRef Name);
1766
1767/// }
1768
Florian Hahnc4422242017-11-07 13:07:50 +00001769static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001770 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001771 .Case("v0", AArch64::Q0)
1772 .Case("v1", AArch64::Q1)
1773 .Case("v2", AArch64::Q2)
1774 .Case("v3", AArch64::Q3)
1775 .Case("v4", AArch64::Q4)
1776 .Case("v5", AArch64::Q5)
1777 .Case("v6", AArch64::Q6)
1778 .Case("v7", AArch64::Q7)
1779 .Case("v8", AArch64::Q8)
1780 .Case("v9", AArch64::Q9)
1781 .Case("v10", AArch64::Q10)
1782 .Case("v11", AArch64::Q11)
1783 .Case("v12", AArch64::Q12)
1784 .Case("v13", AArch64::Q13)
1785 .Case("v14", AArch64::Q14)
1786 .Case("v15", AArch64::Q15)
1787 .Case("v16", AArch64::Q16)
1788 .Case("v17", AArch64::Q17)
1789 .Case("v18", AArch64::Q18)
1790 .Case("v19", AArch64::Q19)
1791 .Case("v20", AArch64::Q20)
1792 .Case("v21", AArch64::Q21)
1793 .Case("v22", AArch64::Q22)
1794 .Case("v23", AArch64::Q23)
1795 .Case("v24", AArch64::Q24)
1796 .Case("v25", AArch64::Q25)
1797 .Case("v26", AArch64::Q26)
1798 .Case("v27", AArch64::Q27)
1799 .Case("v28", AArch64::Q28)
1800 .Case("v29", AArch64::Q29)
1801 .Case("v30", AArch64::Q30)
1802 .Case("v31", AArch64::Q31)
1803 .Default(0);
1804}
1805
Sander de Smalen73937b72018-04-11 07:36:10 +00001806/// Returns an optional pair of (#elements, element-width) if Suffix
1807/// is a valid vector kind. Where the number of elements in a vector
1808/// or the vector width is implicit or explicitly unknown (but still a
1809/// valid suffix kind), 0 is used.
1810static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1811 RegKind VectorKind) {
1812 std::pair<int, int> Res = {-1, -1};
1813
1814 switch (VectorKind) {
1815 case RegKind::NeonVector:
1816 Res =
1817 StringSwitch<std::pair<int, int>>(Suffix.lower())
1818 .Case("", {0, 0})
1819 .Case(".1d", {1, 64})
1820 .Case(".1q", {1, 128})
1821 // '.2h' needed for fp16 scalar pairwise reductions
1822 .Case(".2h", {2, 16})
1823 .Case(".2s", {2, 32})
1824 .Case(".2d", {2, 64})
1825 // '.4b' is another special case for the ARMv8.2a dot product
1826 // operand
1827 .Case(".4b", {4, 8})
1828 .Case(".4h", {4, 16})
1829 .Case(".4s", {4, 32})
1830 .Case(".8b", {8, 8})
1831 .Case(".8h", {8, 16})
1832 .Case(".16b", {16, 8})
1833 // Accept the width neutral ones, too, for verbose syntax. If those
1834 // aren't used in the right places, the token operand won't match so
1835 // all will work out.
1836 .Case(".b", {0, 8})
1837 .Case(".h", {0, 16})
1838 .Case(".s", {0, 32})
1839 .Case(".d", {0, 64})
1840 .Default({-1, -1});
1841 break;
1842 case RegKind::SVEPredicateVector:
1843 case RegKind::SVEDataVector:
1844 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1845 .Case("", {0, 0})
1846 .Case(".b", {0, 8})
1847 .Case(".h", {0, 16})
1848 .Case(".s", {0, 32})
1849 .Case(".d", {0, 64})
1850 .Case(".q", {0, 128})
1851 .Default({-1, -1});
1852 break;
1853 default:
1854 llvm_unreachable("Unsupported RegKind");
1855 }
1856
1857 if (Res == std::make_pair(-1, -1))
1858 return Optional<std::pair<int, int>>();
1859
1860 return Optional<std::pair<int, int>>(Res);
1861}
1862
1863static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1864 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001865}
1866
Florian Hahn91f11e52017-11-07 16:45:48 +00001867static unsigned matchSVEDataVectorRegName(StringRef Name) {
1868 return StringSwitch<unsigned>(Name.lower())
1869 .Case("z0", AArch64::Z0)
1870 .Case("z1", AArch64::Z1)
1871 .Case("z2", AArch64::Z2)
1872 .Case("z3", AArch64::Z3)
1873 .Case("z4", AArch64::Z4)
1874 .Case("z5", AArch64::Z5)
1875 .Case("z6", AArch64::Z6)
1876 .Case("z7", AArch64::Z7)
1877 .Case("z8", AArch64::Z8)
1878 .Case("z9", AArch64::Z9)
1879 .Case("z10", AArch64::Z10)
1880 .Case("z11", AArch64::Z11)
1881 .Case("z12", AArch64::Z12)
1882 .Case("z13", AArch64::Z13)
1883 .Case("z14", AArch64::Z14)
1884 .Case("z15", AArch64::Z15)
1885 .Case("z16", AArch64::Z16)
1886 .Case("z17", AArch64::Z17)
1887 .Case("z18", AArch64::Z18)
1888 .Case("z19", AArch64::Z19)
1889 .Case("z20", AArch64::Z20)
1890 .Case("z21", AArch64::Z21)
1891 .Case("z22", AArch64::Z22)
1892 .Case("z23", AArch64::Z23)
1893 .Case("z24", AArch64::Z24)
1894 .Case("z25", AArch64::Z25)
1895 .Case("z26", AArch64::Z26)
1896 .Case("z27", AArch64::Z27)
1897 .Case("z28", AArch64::Z28)
1898 .Case("z29", AArch64::Z29)
1899 .Case("z30", AArch64::Z30)
1900 .Case("z31", AArch64::Z31)
1901 .Default(0);
1902}
1903
Sander de Smalencd6be962017-12-20 11:02:42 +00001904static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1905 return StringSwitch<unsigned>(Name.lower())
1906 .Case("p0", AArch64::P0)
1907 .Case("p1", AArch64::P1)
1908 .Case("p2", AArch64::P2)
1909 .Case("p3", AArch64::P3)
1910 .Case("p4", AArch64::P4)
1911 .Case("p5", AArch64::P5)
1912 .Case("p6", AArch64::P6)
1913 .Case("p7", AArch64::P7)
1914 .Case("p8", AArch64::P8)
1915 .Case("p9", AArch64::P9)
1916 .Case("p10", AArch64::P10)
1917 .Case("p11", AArch64::P11)
1918 .Case("p12", AArch64::P12)
1919 .Case("p13", AArch64::P13)
1920 .Case("p14", AArch64::P14)
1921 .Case("p15", AArch64::P15)
1922 .Default(0);
1923}
1924
Tim Northover3b0846e2014-05-24 12:50:23 +00001925bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1926 SMLoc &EndLoc) {
1927 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00001928 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00001929 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00001930 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00001931}
1932
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001933// Matches a register name or register alias previously defined by '.req'
1934unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001935 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001936 unsigned RegNum = 0;
1937 if ((RegNum = matchSVEDataVectorRegName(Name)))
1938 return Kind == RegKind::SVEDataVector ? RegNum : 0;
1939
Sander de Smalencd6be962017-12-20 11:02:42 +00001940 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
1941 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
1942
Sander de Smalenc067c302017-12-20 09:45:45 +00001943 if ((RegNum = MatchNeonVectorRegName(Name)))
1944 return Kind == RegKind::NeonVector ? RegNum : 0;
1945
1946 // The parsed register must be of RegKind Scalar
1947 if ((RegNum = MatchRegisterName(Name)))
1948 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001949
Florian Hahnc4422242017-11-07 13:07:50 +00001950 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00001951 // Handle a few common aliases of registers.
1952 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
1953 .Case("fp", AArch64::FP)
1954 .Case("lr", AArch64::LR)
1955 .Case("x31", AArch64::XZR)
1956 .Case("w31", AArch64::WZR)
1957 .Default(0))
1958 return Kind == RegKind::Scalar ? RegNum : 0;
1959
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001960 // Check for aliases registered via .req. Canonicalize to lower case.
1961 // That's more consistent since register names are case insensitive, and
1962 // it's how the original entry was passed in from MC/MCParser/AsmParser.
1963 auto Entry = RegisterReqs.find(Name.lower());
1964 if (Entry == RegisterReqs.end())
1965 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00001966
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001967 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00001968 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001969 RegNum = Entry->getValue().second;
1970 }
1971 return RegNum;
1972}
1973
Sander de Smalen50d87022018-04-19 07:35:08 +00001974/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00001975/// Identifier when called, and if it is a register name the token is eaten and
1976/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00001977OperandMatchResultTy
1978AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001979 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001980 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00001981 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00001982 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001983
1984 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00001985 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
1986 if (Reg == 0)
1987 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00001988
Sander de Smalen50d87022018-04-19 07:35:08 +00001989 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00001990 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00001991 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00001992}
1993
Tim Northover3b0846e2014-05-24 12:50:23 +00001994/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00001995OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00001996AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001997 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001998 SMLoc S = getLoc();
1999
2000 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2001 Error(S, "Expected cN operand where 0 <= N <= 15");
2002 return MatchOperand_ParseFail;
2003 }
2004
2005 StringRef Tok = Parser.getTok().getIdentifier();
2006 if (Tok[0] != 'c' && Tok[0] != 'C') {
2007 Error(S, "Expected cN operand where 0 <= N <= 15");
2008 return MatchOperand_ParseFail;
2009 }
2010
2011 uint32_t CRNum;
2012 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2013 if (BadNum || CRNum > 15) {
2014 Error(S, "Expected cN operand where 0 <= N <= 15");
2015 return MatchOperand_ParseFail;
2016 }
2017
2018 Parser.Lex(); // Eat identifier token.
2019 Operands.push_back(
2020 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2021 return MatchOperand_Success;
2022}
2023
2024/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002025OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002026AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002027 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002028 SMLoc S = getLoc();
2029 const AsmToken &Tok = Parser.getTok();
2030 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002031 // Eat optional hash.
2032 if (parseOptionalToken(AsmToken::Hash) ||
2033 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002034 const MCExpr *ImmVal;
2035 if (getParser().parseExpression(ImmVal))
2036 return MatchOperand_ParseFail;
2037
2038 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2039 if (!MCE) {
2040 TokError("immediate value expected for prefetch operand");
2041 return MatchOperand_ParseFail;
2042 }
2043 unsigned prfop = MCE->getValue();
2044 if (prfop > 31) {
2045 TokError("prefetch operand out of range, [0,31] expected");
2046 return MatchOperand_ParseFail;
2047 }
2048
Tim Northovere6ae6762016-07-05 21:23:04 +00002049 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2050 Operands.push_back(AArch64Operand::CreatePrefetch(
2051 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002052 return MatchOperand_Success;
2053 }
2054
2055 if (Tok.isNot(AsmToken::Identifier)) {
2056 TokError("pre-fetch hint expected");
2057 return MatchOperand_ParseFail;
2058 }
2059
Tim Northovere6ae6762016-07-05 21:23:04 +00002060 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2061 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002062 TokError("pre-fetch hint expected");
2063 return MatchOperand_ParseFail;
2064 }
2065
2066 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002067 Operands.push_back(AArch64Operand::CreatePrefetch(
2068 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002069 return MatchOperand_Success;
2070}
2071
Oliver Stannarda34e4702015-12-01 10:48:51 +00002072/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002073OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002074AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2075 MCAsmParser &Parser = getParser();
2076 SMLoc S = getLoc();
2077 const AsmToken &Tok = Parser.getTok();
2078 if (Tok.isNot(AsmToken::Identifier)) {
2079 TokError("invalid operand for instruction");
2080 return MatchOperand_ParseFail;
2081 }
2082
Tim Northovere6ae6762016-07-05 21:23:04 +00002083 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2084 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002085 TokError("invalid operand for instruction");
2086 return MatchOperand_ParseFail;
2087 }
2088
2089 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002090 Operands.push_back(AArch64Operand::CreatePSBHint(
2091 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002092 return MatchOperand_Success;
2093}
2094
Tim Northover3b0846e2014-05-24 12:50:23 +00002095/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2096/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002097OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002098AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002099 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002100 SMLoc S = getLoc();
2101 const MCExpr *Expr;
2102
2103 if (Parser.getTok().is(AsmToken::Hash)) {
2104 Parser.Lex(); // Eat hash token.
2105 }
2106
2107 if (parseSymbolicImmVal(Expr))
2108 return MatchOperand_ParseFail;
2109
2110 AArch64MCExpr::VariantKind ELFRefKind;
2111 MCSymbolRefExpr::VariantKind DarwinRefKind;
2112 int64_t Addend;
2113 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2114 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2115 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2116 // No modifier was specified at all; this is the syntax for an ELF basic
2117 // ADRP relocation (unfortunately).
2118 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002119 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002120 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2121 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2122 Addend != 0) {
2123 Error(S, "gotpage label reference not allowed an addend");
2124 return MatchOperand_ParseFail;
2125 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2126 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2127 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2128 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2129 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2130 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2131 // The operand must be an @page or @gotpage qualified symbolref.
2132 Error(S, "page or gotpage label reference expected");
2133 return MatchOperand_ParseFail;
2134 }
2135 }
2136
2137 // We have either a label reference possibly with addend or an immediate. The
2138 // addend is a raw value here. The linker will adjust it to only reference the
2139 // page.
2140 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2141 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2142
2143 return MatchOperand_Success;
2144}
2145
2146/// tryParseAdrLabel - Parse and validate a source label for the ADR
2147/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002148OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002149AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2150 SMLoc S = getLoc();
2151 const MCExpr *Expr;
2152
Nirav Davee833c6c2016-11-08 18:31:04 +00002153 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002154 if (getParser().parseExpression(Expr))
2155 return MatchOperand_ParseFail;
2156
2157 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2158 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2159
2160 return MatchOperand_Success;
2161}
2162
2163/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002164OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002165AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002166 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002167 SMLoc S = getLoc();
2168
Nirav Davee833c6c2016-11-08 18:31:04 +00002169 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002170
2171 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002172 bool isNegative = parseOptionalToken(AsmToken::Minus);
2173
Tim Northover3b0846e2014-05-24 12:50:23 +00002174 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002175 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002176 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002177 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002178 Val = Tok.getIntVal();
2179 if (Val > 255 || Val < 0) {
2180 TokError("encoded floating point value out of range");
2181 return MatchOperand_ParseFail;
2182 }
2183 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002184 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002185 if (isNegative)
2186 RealVal.changeSign();
2187
Tim Northover3b0846e2014-05-24 12:50:23 +00002188 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002189 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002190
John Brawn5ca5daa2017-04-20 10:13:54 +00002191 // Check for out of range values. As an exception we let Zero through,
2192 // but as tokens instead of an FPImm so that it can be matched by the
2193 // appropriate alias if one exists.
2194 if (RealVal.isPosZero()) {
2195 Parser.Lex(); // Eat the token.
2196 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2197 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2198 return MatchOperand_Success;
2199 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002200 TokError("expected compatible register or floating-point constant");
2201 return MatchOperand_ParseFail;
2202 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002203 }
2204 Parser.Lex(); // Eat the token.
2205 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2206 return MatchOperand_Success;
2207 }
2208
2209 if (!Hash)
2210 return MatchOperand_NoMatch;
2211
2212 TokError("invalid floating point immediate");
2213 return MatchOperand_ParseFail;
2214}
2215
2216/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002217OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002218AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002219 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002220 SMLoc S = getLoc();
2221
2222 if (Parser.getTok().is(AsmToken::Hash))
2223 Parser.Lex(); // Eat '#'
2224 else if (Parser.getTok().isNot(AsmToken::Integer))
2225 // Operand should start from # or should be integer, emit error otherwise.
2226 return MatchOperand_NoMatch;
2227
2228 const MCExpr *Imm;
2229 if (parseSymbolicImmVal(Imm))
2230 return MatchOperand_ParseFail;
2231 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2232 uint64_t ShiftAmount = 0;
2233 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2234 if (MCE) {
2235 int64_t Val = MCE->getValue();
2236 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002237 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002238 ShiftAmount = 12;
2239 }
2240 }
2241 SMLoc E = Parser.getTok().getLoc();
2242 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2243 getContext()));
2244 return MatchOperand_Success;
2245 }
2246
2247 // Eat ','
2248 Parser.Lex();
2249
2250 // The optional operand must be "lsl #N" where N is non-negative.
2251 if (!Parser.getTok().is(AsmToken::Identifier) ||
2252 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2253 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2254 return MatchOperand_ParseFail;
2255 }
2256
2257 // Eat 'lsl'
2258 Parser.Lex();
2259
Nirav Davee833c6c2016-11-08 18:31:04 +00002260 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002261
2262 if (Parser.getTok().isNot(AsmToken::Integer)) {
2263 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2264 return MatchOperand_ParseFail;
2265 }
2266
2267 int64_t ShiftAmount = Parser.getTok().getIntVal();
2268
2269 if (ShiftAmount < 0) {
2270 Error(Parser.getTok().getLoc(), "positive shift amount required");
2271 return MatchOperand_ParseFail;
2272 }
2273 Parser.Lex(); // Eat the number
2274
2275 SMLoc E = Parser.getTok().getLoc();
2276 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2277 S, E, getContext()));
2278 return MatchOperand_Success;
2279}
2280
2281/// parseCondCodeString - Parse a Condition Code string.
2282AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2283 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2284 .Case("eq", AArch64CC::EQ)
2285 .Case("ne", AArch64CC::NE)
2286 .Case("cs", AArch64CC::HS)
2287 .Case("hs", AArch64CC::HS)
2288 .Case("cc", AArch64CC::LO)
2289 .Case("lo", AArch64CC::LO)
2290 .Case("mi", AArch64CC::MI)
2291 .Case("pl", AArch64CC::PL)
2292 .Case("vs", AArch64CC::VS)
2293 .Case("vc", AArch64CC::VC)
2294 .Case("hi", AArch64CC::HI)
2295 .Case("ls", AArch64CC::LS)
2296 .Case("ge", AArch64CC::GE)
2297 .Case("lt", AArch64CC::LT)
2298 .Case("gt", AArch64CC::GT)
2299 .Case("le", AArch64CC::LE)
2300 .Case("al", AArch64CC::AL)
2301 .Case("nv", AArch64CC::NV)
2302 .Default(AArch64CC::Invalid);
2303 return CC;
2304}
2305
2306/// parseCondCode - Parse a Condition Code operand.
2307bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2308 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002309 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002310 SMLoc S = getLoc();
2311 const AsmToken &Tok = Parser.getTok();
2312 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2313
2314 StringRef Cond = Tok.getString();
2315 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2316 if (CC == AArch64CC::Invalid)
2317 return TokError("invalid condition code");
2318 Parser.Lex(); // Eat identifier token.
2319
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002320 if (invertCondCode) {
2321 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2322 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002323 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002324 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002325
2326 Operands.push_back(
2327 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2328 return false;
2329}
2330
2331/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2332/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002333OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002334AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002335 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002336 const AsmToken &Tok = Parser.getTok();
2337 std::string LowerID = Tok.getString().lower();
2338 AArch64_AM::ShiftExtendType ShOp =
2339 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2340 .Case("lsl", AArch64_AM::LSL)
2341 .Case("lsr", AArch64_AM::LSR)
2342 .Case("asr", AArch64_AM::ASR)
2343 .Case("ror", AArch64_AM::ROR)
2344 .Case("msl", AArch64_AM::MSL)
2345 .Case("uxtb", AArch64_AM::UXTB)
2346 .Case("uxth", AArch64_AM::UXTH)
2347 .Case("uxtw", AArch64_AM::UXTW)
2348 .Case("uxtx", AArch64_AM::UXTX)
2349 .Case("sxtb", AArch64_AM::SXTB)
2350 .Case("sxth", AArch64_AM::SXTH)
2351 .Case("sxtw", AArch64_AM::SXTW)
2352 .Case("sxtx", AArch64_AM::SXTX)
2353 .Default(AArch64_AM::InvalidShiftExtend);
2354
2355 if (ShOp == AArch64_AM::InvalidShiftExtend)
2356 return MatchOperand_NoMatch;
2357
2358 SMLoc S = Tok.getLoc();
2359 Parser.Lex();
2360
Nirav Davee833c6c2016-11-08 18:31:04 +00002361 bool Hash = parseOptionalToken(AsmToken::Hash);
2362
Tim Northover3b0846e2014-05-24 12:50:23 +00002363 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2364 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2365 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2366 ShOp == AArch64_AM::MSL) {
2367 // We expect a number here.
2368 TokError("expected #imm after shift specifier");
2369 return MatchOperand_ParseFail;
2370 }
2371
Chad Rosier2ff37b82016-12-27 16:58:09 +00002372 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002373 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2374 Operands.push_back(
2375 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2376 return MatchOperand_Success;
2377 }
2378
Chad Rosier2ff37b82016-12-27 16:58:09 +00002379 // Make sure we do actually have a number, identifier or a parenthesized
2380 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002381 SMLoc E = Parser.getTok().getLoc();
2382 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002383 !Parser.getTok().is(AsmToken::LParen) &&
2384 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002385 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002386 return MatchOperand_ParseFail;
2387 }
2388
2389 const MCExpr *ImmVal;
2390 if (getParser().parseExpression(ImmVal))
2391 return MatchOperand_ParseFail;
2392
2393 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2394 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002395 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002396 return MatchOperand_ParseFail;
2397 }
2398
Jim Grosbach57fd2622014-09-23 22:16:02 +00002399 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002400 Operands.push_back(AArch64Operand::CreateShiftExtend(
2401 ShOp, MCE->getValue(), true, S, E, getContext()));
2402 return MatchOperand_Success;
2403}
2404
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002405static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2406 if (FBS[AArch64::HasV8_1aOps])
2407 Str += "ARMv8.1a";
2408 else if (FBS[AArch64::HasV8_2aOps])
2409 Str += "ARMv8.2a";
2410 else
2411 Str += "(unknown)";
2412}
2413
2414void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2415 SMLoc S) {
2416 const uint16_t Op2 = Encoding & 7;
2417 const uint16_t Cm = (Encoding & 0x78) >> 3;
2418 const uint16_t Cn = (Encoding & 0x780) >> 7;
2419 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2420
2421 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2422
2423 Operands.push_back(
2424 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2425 Operands.push_back(
2426 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2427 Operands.push_back(
2428 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2429 Expr = MCConstantExpr::create(Op2, getContext());
2430 Operands.push_back(
2431 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2432}
2433
Tim Northover3b0846e2014-05-24 12:50:23 +00002434/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2435/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2436bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2437 OperandVector &Operands) {
2438 if (Name.find('.') != StringRef::npos)
2439 return TokError("invalid operand");
2440
2441 Mnemonic = Name;
2442 Operands.push_back(
2443 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2444
Rafael Espindola961d4692014-11-11 05:18:41 +00002445 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002446 const AsmToken &Tok = Parser.getTok();
2447 StringRef Op = Tok.getString();
2448 SMLoc S = Tok.getLoc();
2449
Tim Northover3b0846e2014-05-24 12:50:23 +00002450 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002451 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2452 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002453 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002454 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2455 std::string Str("IC " + std::string(IC->Name) + " requires ");
2456 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2457 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002458 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002459 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002460 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002461 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2462 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002463 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002464 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2465 std::string Str("DC " + std::string(DC->Name) + " requires ");
2466 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2467 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002468 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002469 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002470 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002471 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2472 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002473 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002474 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2475 std::string Str("AT " + std::string(AT->Name) + " requires ");
2476 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2477 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002478 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002479 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002480 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002481 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2482 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002483 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002484 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2485 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2486 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2487 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002488 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002489 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002490 }
2491
Tim Northover3b0846e2014-05-24 12:50:23 +00002492 Parser.Lex(); // Eat operand.
2493
2494 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2495 bool HasRegister = false;
2496
2497 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002498 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002499 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2500 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002501 HasRegister = true;
2502 }
2503
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002504 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002505 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002506 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002507 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002508
Nirav Davee833c6c2016-11-08 18:31:04 +00002509 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2510 return true;
2511
Tim Northover3b0846e2014-05-24 12:50:23 +00002512 return false;
2513}
2514
Alex Bradbury58eba092016-11-01 16:32:05 +00002515OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002516AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002517 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002518 const AsmToken &Tok = Parser.getTok();
2519
2520 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002521 if (parseOptionalToken(AsmToken::Hash) ||
2522 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002523 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002524 const MCExpr *ImmVal;
2525 SMLoc ExprLoc = getLoc();
2526 if (getParser().parseExpression(ImmVal))
2527 return MatchOperand_ParseFail;
2528 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2529 if (!MCE) {
2530 Error(ExprLoc, "immediate value expected for barrier operand");
2531 return MatchOperand_ParseFail;
2532 }
2533 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2534 Error(ExprLoc, "barrier operand out of range");
2535 return MatchOperand_ParseFail;
2536 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002537 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2538 Operands.push_back(AArch64Operand::CreateBarrier(
2539 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002540 return MatchOperand_Success;
2541 }
2542
2543 if (Tok.isNot(AsmToken::Identifier)) {
2544 TokError("invalid operand for instruction");
2545 return MatchOperand_ParseFail;
2546 }
2547
Tim Northover3b0846e2014-05-24 12:50:23 +00002548 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002549 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2550 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002551 TokError("'sy' or #imm operand expected");
2552 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002553 } else if (!DB) {
2554 TokError("invalid barrier option name");
2555 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002556 }
2557
Tim Northovere6ae6762016-07-05 21:23:04 +00002558 Operands.push_back(AArch64Operand::CreateBarrier(
2559 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002560 Parser.Lex(); // Consume the option
2561
2562 return MatchOperand_Success;
2563}
2564
Alex Bradbury58eba092016-11-01 16:32:05 +00002565OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002566AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002567 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002568 const AsmToken &Tok = Parser.getTok();
2569
2570 if (Tok.isNot(AsmToken::Identifier))
2571 return MatchOperand_NoMatch;
2572
Tim Northovere6ae6762016-07-05 21:23:04 +00002573 int MRSReg, MSRReg;
2574 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2575 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2576 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2577 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2578 } else
2579 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002580
Tim Northovere6ae6762016-07-05 21:23:04 +00002581 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2582 unsigned PStateImm = -1;
2583 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2584 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002585
Tim Northovere6ae6762016-07-05 21:23:04 +00002586 Operands.push_back(
2587 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2588 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002589 Parser.Lex(); // Eat identifier
2590
2591 return MatchOperand_Success;
2592}
2593
Florian Hahnc4422242017-11-07 13:07:50 +00002594/// tryParseNeonVectorRegister - Parse a vector register operand.
2595bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002596 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002597 if (Parser.getTok().isNot(AsmToken::Identifier))
2598 return true;
2599
2600 SMLoc S = getLoc();
2601 // Check for a vector register specifier first.
2602 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002603 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002604 OperandMatchResultTy Res =
2605 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2606 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002607 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002608
2609 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2610 if (!KindRes)
2611 return true;
2612
2613 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002614 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002615 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2616 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002617
Tim Northover3b0846e2014-05-24 12:50:23 +00002618 // If there was an explicit qualifier, that goes on as a literal text
2619 // operand.
2620 if (!Kind.empty())
2621 Operands.push_back(
2622 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2623
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002624 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2625}
2626
2627OperandMatchResultTy
2628AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002629 SMLoc SIdx = getLoc();
2630 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002631 const MCExpr *ImmVal;
2632 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002633 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002634 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2635 if (!MCE) {
2636 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002637 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002638 }
2639
2640 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002641
Nirav Davee833c6c2016-11-08 18:31:04 +00002642 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002643 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002644
2645 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2646 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002647 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002648 }
2649
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002650 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002651}
2652
Sander de Smalen73937b72018-04-11 07:36:10 +00002653// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002654// optional kind specifier. If it is a register specifier, eat the token
2655// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002656OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002657AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002658 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002659 MCAsmParser &Parser = getParser();
2660 const AsmToken &Tok = Parser.getTok();
2661
Florian Hahn91f11e52017-11-07 16:45:48 +00002662 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002663 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002664
2665 StringRef Name = Tok.getString();
2666 // If there is a kind specifier, it's separated from the register name by
2667 // a '.'.
2668 size_t Start = 0, Next = Name.find('.');
2669 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002670 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002671
2672 if (RegNum) {
2673 if (Next != StringRef::npos) {
2674 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002675 if (!isValidVectorKind(Kind, MatchKind)) {
2676 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002677 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002678 }
2679 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002680 Parser.Lex(); // Eat the register token.
2681
2682 Reg = RegNum;
2683 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002684 }
2685
Sander de Smalen8e607342017-11-15 15:44:43 +00002686 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002687}
2688
Sander de Smalencd6be962017-12-20 11:02:42 +00002689/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2690OperandMatchResultTy
2691AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2692 // Check for a SVE predicate register specifier first.
2693 const SMLoc S = getLoc();
2694 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002695 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002696 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002697 if (Res != MatchOperand_Success)
2698 return Res;
2699
Sander de Smalen73937b72018-04-11 07:36:10 +00002700 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2701 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002702 return MatchOperand_NoMatch;
2703
Sander de Smalen73937b72018-04-11 07:36:10 +00002704 unsigned ElementWidth = KindRes->second;
2705 Operands.push_back(AArch64Operand::CreateVectorReg(
2706 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2707 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002708
Sander de Smalen7868e742018-01-09 11:17:06 +00002709 // Not all predicates are followed by a '/m' or '/z'.
2710 MCAsmParser &Parser = getParser();
2711 if (Parser.getTok().isNot(AsmToken::Slash))
2712 return MatchOperand_Success;
2713
2714 // But when they do they shouldn't have an element type suffix.
2715 if (!Kind.empty()) {
2716 Error(S, "not expecting size suffix");
2717 return MatchOperand_ParseFail;
2718 }
2719
2720 // Add a literal slash as operand
2721 Operands.push_back(
2722 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2723
2724 Parser.Lex(); // Eat the slash.
2725
2726 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002727 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002728 if (Pred != "z" && Pred != "m") {
2729 Error(getLoc(), "expecting 'm' or 'z' predication");
2730 return MatchOperand_ParseFail;
2731 }
2732
2733 // Add zero/merge token.
2734 const char *ZM = Pred == "z" ? "z" : "m";
2735 Operands.push_back(
2736 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2737
2738 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002739 return MatchOperand_Success;
2740}
2741
Sander de Smalen50d87022018-04-19 07:35:08 +00002742/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002743bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002744 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002745 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002746 return false;
2747
Sander de Smalen149916d2018-04-20 07:24:20 +00002748 // Otherwise try for a scalar register.
2749 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
2750 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002751
Sander de Smalen149916d2018-04-20 07:24:20 +00002752 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002753}
2754
2755bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002756 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002757 bool HasELFModifier = false;
2758 AArch64MCExpr::VariantKind RefKind;
2759
Nirav Davee833c6c2016-11-08 18:31:04 +00002760 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002761 HasELFModifier = true;
2762
Nirav Davee833c6c2016-11-08 18:31:04 +00002763 if (Parser.getTok().isNot(AsmToken::Identifier))
2764 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002765
2766 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2767 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2768 .Case("lo12", AArch64MCExpr::VK_LO12)
2769 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2770 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2771 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2772 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2773 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2774 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2775 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2776 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2777 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2778 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2779 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2780 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2781 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2782 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2783 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2784 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2785 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2786 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2787 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2788 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2789 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2790 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2791 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2792 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2793 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2794 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2795 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2796 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2797 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2798 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2799 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2800 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2801 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2802 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002803 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2804 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002805 .Default(AArch64MCExpr::VK_INVALID);
2806
Nirav Davee833c6c2016-11-08 18:31:04 +00002807 if (RefKind == AArch64MCExpr::VK_INVALID)
2808 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002809
2810 Parser.Lex(); // Eat identifier
2811
Nirav Davee833c6c2016-11-08 18:31:04 +00002812 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002813 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002814 }
2815
2816 if (getParser().parseExpression(ImmVal))
2817 return true;
2818
2819 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002820 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002821
2822 return false;
2823}
2824
Sander de Smalen650234b2018-04-12 11:40:52 +00002825template <RegKind VectorKind>
2826OperandMatchResultTy
2827AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
2828 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002829 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00002830 if (!Parser.getTok().is(AsmToken::LCurly))
2831 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002832
2833 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00002834 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00002835 bool NoMatchIsError) {
2836 auto RegTok = Parser.getTok();
2837 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
2838 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002839 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00002840 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002841 llvm_unreachable("Expected a valid vector kind");
2842 }
2843
Sander de Smalen650234b2018-04-12 11:40:52 +00002844 if (RegTok.isNot(AsmToken::Identifier) ||
2845 ParseRes == MatchOperand_ParseFail ||
2846 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
2847 Error(Loc, "vector register expected");
2848 return MatchOperand_ParseFail;
2849 }
2850
2851 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002852 };
2853
Tim Northover3b0846e2014-05-24 12:50:23 +00002854 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00002855 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00002856 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00002857
Tim Northover3b0846e2014-05-24 12:50:23 +00002858 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002859 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002860 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
2861
2862 // Put back the original left bracket if there was no match, so that
2863 // different types of list-operands can be matched (e.g. SVE, Neon).
2864 if (ParseRes == MatchOperand_NoMatch)
2865 Parser.getLexer().UnLex(LCurly);
2866
2867 if (ParseRes != MatchOperand_Success)
2868 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002869
Tim Northover3b0846e2014-05-24 12:50:23 +00002870 int64_t PrevReg = FirstReg;
2871 unsigned Count = 1;
2872
Nirav Davee833c6c2016-11-08 18:31:04 +00002873 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002874 SMLoc Loc = getLoc();
2875 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002876
Sander de Smalen50d87022018-04-19 07:35:08 +00002877 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002878 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2879 if (ParseRes != MatchOperand_Success)
2880 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002881
Tim Northover3b0846e2014-05-24 12:50:23 +00002882 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002883 if (Kind != NextKind) {
2884 Error(Loc, "mismatched register size suffix");
2885 return MatchOperand_ParseFail;
2886 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002887
2888 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2889
2890 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002891 Error(Loc, "invalid number of vectors");
2892 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002893 }
2894
2895 Count += Space;
2896 }
2897 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002898 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002899 SMLoc Loc = getLoc();
2900 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002901 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002902 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2903 if (ParseRes != MatchOperand_Success)
2904 return ParseRes;
2905
Tim Northover3b0846e2014-05-24 12:50:23 +00002906 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002907 if (Kind != NextKind) {
2908 Error(Loc, "mismatched register size suffix");
2909 return MatchOperand_ParseFail;
2910 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002911
2912 // Registers must be incremental (with wraparound at 31)
2913 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00002914 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
2915 Error(Loc, "registers must be sequential");
2916 return MatchOperand_ParseFail;
2917 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002918
2919 PrevReg = Reg;
2920 ++Count;
2921 }
2922 }
2923
Nirav Davee833c6c2016-11-08 18:31:04 +00002924 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00002925 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002926
Sander de Smalen650234b2018-04-12 11:40:52 +00002927 if (Count > 4) {
2928 Error(S, "invalid number of vectors");
2929 return MatchOperand_ParseFail;
2930 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002931
2932 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00002933 unsigned ElementWidth = 0;
2934 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002935 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00002936 std::tie(NumElements, ElementWidth) = *VK;
2937 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002938
2939 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00002940 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
2941 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002942
Sander de Smalen650234b2018-04-12 11:40:52 +00002943 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002944}
2945
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002946/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
2947bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002948 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
2949 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002950 return true;
2951
2952 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2953}
2954
Alex Bradbury58eba092016-11-01 16:32:05 +00002955OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002956AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002957 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002958
Sander de Smalen50d87022018-04-19 07:35:08 +00002959 unsigned RegNum;
2960 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
2961 if (Res != MatchOperand_Success)
2962 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00002963
Nirav Davee833c6c2016-11-08 18:31:04 +00002964 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002965 Operands.push_back(AArch64Operand::CreateReg(
2966 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002967 return MatchOperand_Success;
2968 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002969
Nirav Davee833c6c2016-11-08 18:31:04 +00002970 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002971
Sander de Smalen50d87022018-04-19 07:35:08 +00002972 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002973 Error(getLoc(), "index must be absent or #0");
2974 return MatchOperand_ParseFail;
2975 }
2976
2977 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00002978 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00002979 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
2980 Error(getLoc(), "index must be absent or #0");
2981 return MatchOperand_ParseFail;
2982 }
2983
Sander de Smalen50d87022018-04-19 07:35:08 +00002984 Operands.push_back(AArch64Operand::CreateReg(
2985 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002986 return MatchOperand_Success;
2987}
2988
Sander de Smalen149916d2018-04-20 07:24:20 +00002989template <bool ParseShiftExtend>
2990OperandMatchResultTy
2991AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
2992 SMLoc StartLoc = getLoc();
2993
2994 unsigned RegNum;
2995 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
2996 if (Res != MatchOperand_Success)
2997 return Res;
2998
2999 // No shift/extend is the default.
3000 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3001 Operands.push_back(AArch64Operand::CreateReg(
3002 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
3003 return MatchOperand_Success;
3004 }
3005
3006 // Eat the comma
3007 getParser().Lex();
3008
3009 // Match the shift
3010 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3011 Res = tryParseOptionalShiftExtend(ExtOpnd);
3012 if (Res != MatchOperand_Success)
3013 return Res;
3014
3015 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
3016 Operands.push_back(AArch64Operand::CreateReg(RegNum, RegKind::Scalar,
3017 StartLoc, Ext->getEndLoc(), getContext(),
3018 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3019 Ext->hasShiftExtendAmount()));
3020
3021 return MatchOperand_Success;
3022}
3023
Sander de Smalen5c625982018-04-13 12:56:14 +00003024bool AArch64AsmParser::parseOptionalMulVl(OperandVector &Operands) {
3025 MCAsmParser &Parser = getParser();
3026
3027 // Some SVE instructions have a decoration after the immediate, i.e.
3028 // "mul vl". We parse them here and add tokens, which must be present in the
3029 // asm string in the tablegen instruction.
3030 if (!Parser.getTok().getString().equals_lower("mul") ||
3031 !Parser.getLexer().peekTok().getString().equals_lower("vl"))
3032 return true;
3033
3034 SMLoc S = getLoc();
3035 Operands.push_back(
3036 AArch64Operand::CreateToken("mul", false, S, getContext()));
3037 Parser.Lex(); // Eat the "mul"
3038
3039 S = getLoc();
3040 Operands.push_back(
3041 AArch64Operand::CreateToken("vl", false, S, getContext()));
3042 Parser.Lex(); // Eat the "vl"
3043
3044 return false;
3045}
3046
Tim Northover3b0846e2014-05-24 12:50:23 +00003047/// parseOperand - Parse a arm instruction operand. For now this parses the
3048/// operand regardless of the mnemonic.
3049bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3050 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003051 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003052
3053 OperandMatchResultTy ResTy =
3054 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3055
Tim Northover3b0846e2014-05-24 12:50:23 +00003056 // Check if the current operand has a custom associated parser, if so, try to
3057 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003058 if (ResTy == MatchOperand_Success)
3059 return false;
3060 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3061 // there was a match, but an error occurred, in which case, just return that
3062 // the operand parsing failed.
3063 if (ResTy == MatchOperand_ParseFail)
3064 return true;
3065
3066 // Nothing custom, so do general case parsing.
3067 SMLoc S, E;
3068 switch (getLexer().getKind()) {
3069 default: {
3070 SMLoc S = getLoc();
3071 const MCExpr *Expr;
3072 if (parseSymbolicImmVal(Expr))
3073 return Error(S, "invalid operand");
3074
3075 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3076 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3077 return false;
3078 }
3079 case AsmToken::LBrac: {
3080 SMLoc Loc = Parser.getTok().getLoc();
3081 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3082 getContext()));
3083 Parser.Lex(); // Eat '['
3084
3085 // There's no comma after a '[', so we can parse the next operand
3086 // immediately.
3087 return parseOperand(Operands, false, false);
3088 }
3089 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003090 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003091 case AsmToken::Identifier: {
3092 // If we're expecting a Condition Code operand, then just parse that.
3093 if (isCondCode)
3094 return parseCondCode(Operands, invertCondCode);
3095
3096 // If it's a register name, parse it.
3097 if (!parseRegister(Operands))
3098 return false;
3099
Sander de Smalen5c625982018-04-13 12:56:14 +00003100 // See if this is a "mul vl" decoration used by SVE instructions.
3101 if (!parseOptionalMulVl(Operands))
3102 return false;
3103
Tim Northover3b0846e2014-05-24 12:50:23 +00003104 // This could be an optional "shift" or "extend" operand.
3105 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3106 // We can only continue if no tokens were eaten.
3107 if (GotShift != MatchOperand_NoMatch)
3108 return GotShift;
3109
3110 // This was not a register so parse other operands that start with an
3111 // identifier (like labels) as expressions and create them as immediates.
3112 const MCExpr *IdVal;
3113 S = getLoc();
3114 if (getParser().parseExpression(IdVal))
3115 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003116 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3117 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3118 return false;
3119 }
3120 case AsmToken::Integer:
3121 case AsmToken::Real:
3122 case AsmToken::Hash: {
3123 // #42 -> immediate.
3124 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003125
3126 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003127
3128 // Parse a negative sign
3129 bool isNegative = false;
3130 if (Parser.getTok().is(AsmToken::Minus)) {
3131 isNegative = true;
3132 // We need to consume this token only when we have a Real, otherwise
3133 // we let parseSymbolicImmVal take care of it
3134 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3135 Parser.Lex();
3136 }
3137
3138 // The only Real that should come through here is a literal #0.0 for
3139 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3140 // so convert the value.
3141 const AsmToken &Tok = Parser.getTok();
3142 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003143 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003144 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3145 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3146 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3147 Mnemonic != "fcmlt")
3148 return TokError("unexpected floating point literal");
3149 else if (IntVal != 0 || isNegative)
3150 return TokError("expected floating-point constant #0.0");
3151 Parser.Lex(); // Eat the token.
3152
3153 Operands.push_back(
3154 AArch64Operand::CreateToken("#0", false, S, getContext()));
3155 Operands.push_back(
3156 AArch64Operand::CreateToken(".0", false, S, getContext()));
3157 return false;
3158 }
3159
3160 const MCExpr *ImmVal;
3161 if (parseSymbolicImmVal(ImmVal))
3162 return true;
3163
3164 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3165 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3166 return false;
3167 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003168 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003169 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003170 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003171 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003172 Parser.Lex(); // Eat '='
3173 const MCExpr *SubExprVal;
3174 if (getParser().parseExpression(SubExprVal))
3175 return true;
3176
David Peixottoae5ba762014-07-18 16:05:14 +00003177 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003178 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003179 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003180
3181 bool IsXReg =
3182 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3183 Operands[1]->getReg());
3184
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003185 MCContext& Ctx = getContext();
3186 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3187 // 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 +00003188 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003189 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3190 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3191 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3192 ShiftAmt += 16;
3193 Imm >>= 16;
3194 }
3195 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3196 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3197 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003198 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003199 if (ShiftAmt)
3200 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3201 ShiftAmt, true, S, E, Ctx));
3202 return false;
3203 }
David Peixottoae5ba762014-07-18 16:05:14 +00003204 APInt Simm = APInt(64, Imm << ShiftAmt);
3205 // check if the immediate is an unsigned or signed 32-bit int for W regs
3206 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3207 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003208 }
3209 // 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 +00003210 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003211 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003212 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3213 return false;
3214 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003215 }
3216}
3217
3218/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3219/// operands.
3220bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3221 StringRef Name, SMLoc NameLoc,
3222 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003223 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003224 Name = StringSwitch<StringRef>(Name.lower())
3225 .Case("beq", "b.eq")
3226 .Case("bne", "b.ne")
3227 .Case("bhs", "b.hs")
3228 .Case("bcs", "b.cs")
3229 .Case("blo", "b.lo")
3230 .Case("bcc", "b.cc")
3231 .Case("bmi", "b.mi")
3232 .Case("bpl", "b.pl")
3233 .Case("bvs", "b.vs")
3234 .Case("bvc", "b.vc")
3235 .Case("bhi", "b.hi")
3236 .Case("bls", "b.ls")
3237 .Case("bge", "b.ge")
3238 .Case("blt", "b.lt")
3239 .Case("bgt", "b.gt")
3240 .Case("ble", "b.le")
3241 .Case("bal", "b.al")
3242 .Case("bnv", "b.nv")
3243 .Default(Name);
3244
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003245 // First check for the AArch64-specific .req directive.
3246 if (Parser.getTok().is(AsmToken::Identifier) &&
3247 Parser.getTok().getIdentifier() == ".req") {
3248 parseDirectiveReq(Name, NameLoc);
3249 // We always return 'error' for this, as we're done with this
3250 // statement and don't need to match the 'instruction."
3251 return true;
3252 }
3253
Tim Northover3b0846e2014-05-24 12:50:23 +00003254 // Create the leading tokens for the mnemonic, split by '.' characters.
3255 size_t Start = 0, Next = Name.find('.');
3256 StringRef Head = Name.slice(Start, Next);
3257
3258 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003259 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3260 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003261
3262 Operands.push_back(
3263 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3264 Mnemonic = Head;
3265
3266 // Handle condition codes for a branch mnemonic
3267 if (Head == "b" && Next != StringRef::npos) {
3268 Start = Next;
3269 Next = Name.find('.', Start + 1);
3270 Head = Name.slice(Start + 1, Next);
3271
3272 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3273 (Head.data() - Name.data()));
3274 AArch64CC::CondCode CC = parseCondCodeString(Head);
3275 if (CC == AArch64CC::Invalid)
3276 return Error(SuffixLoc, "invalid condition code");
3277 Operands.push_back(
3278 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3279 Operands.push_back(
3280 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3281 }
3282
3283 // Add the remaining tokens in the mnemonic.
3284 while (Next != StringRef::npos) {
3285 Start = Next;
3286 Next = Name.find('.', Start + 1);
3287 Head = Name.slice(Start, Next);
3288 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3289 (Head.data() - Name.data()) + 1);
3290 Operands.push_back(
3291 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3292 }
3293
3294 // Conditional compare instructions have a Condition Code operand, which needs
3295 // to be parsed and an immediate operand created.
3296 bool condCodeFourthOperand =
3297 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3298 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3299 Head == "csinc" || Head == "csinv" || Head == "csneg");
3300
3301 // These instructions are aliases to some of the conditional select
3302 // instructions. However, the condition code is inverted in the aliased
3303 // instruction.
3304 //
3305 // FIXME: Is this the correct way to handle these? Or should the parser
3306 // generate the aliased instructions directly?
3307 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3308 bool condCodeThirdOperand =
3309 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3310
3311 // Read the remaining operands.
3312 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3313 // Read the first operand.
3314 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003315 return true;
3316 }
3317
3318 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003319 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003320 // Parse and remember the operand.
3321 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3322 (N == 3 && condCodeThirdOperand) ||
3323 (N == 2 && condCodeSecondOperand),
3324 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003325 return true;
3326 }
3327
3328 // After successfully parsing some operands there are two special cases to
3329 // consider (i.e. notional operands not separated by commas). Both are due
3330 // to memory specifiers:
3331 // + An RBrac will end an address for load/store/prefetch
3332 // + An '!' will indicate a pre-indexed operation.
3333 //
3334 // It's someone else's responsibility to make sure these tokens are sane
3335 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003336
Nirav Davee833c6c2016-11-08 18:31:04 +00003337 SMLoc RLoc = Parser.getTok().getLoc();
3338 if (parseOptionalToken(AsmToken::RBrac))
3339 Operands.push_back(
3340 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3341 SMLoc ELoc = Parser.getTok().getLoc();
3342 if (parseOptionalToken(AsmToken::Exclaim))
3343 Operands.push_back(
3344 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003345
3346 ++N;
3347 }
3348 }
3349
Nirav Davee833c6c2016-11-08 18:31:04 +00003350 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3351 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003352
Tim Northover3b0846e2014-05-24 12:50:23 +00003353 return false;
3354}
3355
3356// FIXME: This entire function is a giant hack to provide us with decent
3357// operand range validation/diagnostics until TableGen/MC can be extended
3358// to support autogeneration of this kind of validation.
3359bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3360 SmallVectorImpl<SMLoc> &Loc) {
3361 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3362 // Check for indexed addressing modes w/ the base register being the
3363 // same as a destination/source register or pair load where
3364 // the Rt == Rt2. All of those are undefined behaviour.
3365 switch (Inst.getOpcode()) {
3366 case AArch64::LDPSWpre:
3367 case AArch64::LDPWpost:
3368 case AArch64::LDPWpre:
3369 case AArch64::LDPXpost:
3370 case AArch64::LDPXpre: {
3371 unsigned Rt = Inst.getOperand(1).getReg();
3372 unsigned Rt2 = Inst.getOperand(2).getReg();
3373 unsigned Rn = Inst.getOperand(3).getReg();
3374 if (RI->isSubRegisterEq(Rn, Rt))
3375 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3376 "is also a destination");
3377 if (RI->isSubRegisterEq(Rn, Rt2))
3378 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3379 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003380 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003381 }
3382 case AArch64::LDPDi:
3383 case AArch64::LDPQi:
3384 case AArch64::LDPSi:
3385 case AArch64::LDPSWi:
3386 case AArch64::LDPWi:
3387 case AArch64::LDPXi: {
3388 unsigned Rt = Inst.getOperand(0).getReg();
3389 unsigned Rt2 = Inst.getOperand(1).getReg();
3390 if (Rt == Rt2)
3391 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3392 break;
3393 }
3394 case AArch64::LDPDpost:
3395 case AArch64::LDPDpre:
3396 case AArch64::LDPQpost:
3397 case AArch64::LDPQpre:
3398 case AArch64::LDPSpost:
3399 case AArch64::LDPSpre:
3400 case AArch64::LDPSWpost: {
3401 unsigned Rt = Inst.getOperand(1).getReg();
3402 unsigned Rt2 = Inst.getOperand(2).getReg();
3403 if (Rt == Rt2)
3404 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3405 break;
3406 }
3407 case AArch64::STPDpost:
3408 case AArch64::STPDpre:
3409 case AArch64::STPQpost:
3410 case AArch64::STPQpre:
3411 case AArch64::STPSpost:
3412 case AArch64::STPSpre:
3413 case AArch64::STPWpost:
3414 case AArch64::STPWpre:
3415 case AArch64::STPXpost:
3416 case AArch64::STPXpre: {
3417 unsigned Rt = Inst.getOperand(1).getReg();
3418 unsigned Rt2 = Inst.getOperand(2).getReg();
3419 unsigned Rn = Inst.getOperand(3).getReg();
3420 if (RI->isSubRegisterEq(Rn, Rt))
3421 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3422 "is also a source");
3423 if (RI->isSubRegisterEq(Rn, Rt2))
3424 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3425 "is also a source");
3426 break;
3427 }
3428 case AArch64::LDRBBpre:
3429 case AArch64::LDRBpre:
3430 case AArch64::LDRHHpre:
3431 case AArch64::LDRHpre:
3432 case AArch64::LDRSBWpre:
3433 case AArch64::LDRSBXpre:
3434 case AArch64::LDRSHWpre:
3435 case AArch64::LDRSHXpre:
3436 case AArch64::LDRSWpre:
3437 case AArch64::LDRWpre:
3438 case AArch64::LDRXpre:
3439 case AArch64::LDRBBpost:
3440 case AArch64::LDRBpost:
3441 case AArch64::LDRHHpost:
3442 case AArch64::LDRHpost:
3443 case AArch64::LDRSBWpost:
3444 case AArch64::LDRSBXpost:
3445 case AArch64::LDRSHWpost:
3446 case AArch64::LDRSHXpost:
3447 case AArch64::LDRSWpost:
3448 case AArch64::LDRWpost:
3449 case AArch64::LDRXpost: {
3450 unsigned Rt = Inst.getOperand(1).getReg();
3451 unsigned Rn = Inst.getOperand(2).getReg();
3452 if (RI->isSubRegisterEq(Rn, Rt))
3453 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3454 "is also a source");
3455 break;
3456 }
3457 case AArch64::STRBBpost:
3458 case AArch64::STRBpost:
3459 case AArch64::STRHHpost:
3460 case AArch64::STRHpost:
3461 case AArch64::STRWpost:
3462 case AArch64::STRXpost:
3463 case AArch64::STRBBpre:
3464 case AArch64::STRBpre:
3465 case AArch64::STRHHpre:
3466 case AArch64::STRHpre:
3467 case AArch64::STRWpre:
3468 case AArch64::STRXpre: {
3469 unsigned Rt = Inst.getOperand(1).getReg();
3470 unsigned Rn = Inst.getOperand(2).getReg();
3471 if (RI->isSubRegisterEq(Rn, Rt))
3472 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3473 "is also a source");
3474 break;
3475 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003476 case AArch64::STXRB:
3477 case AArch64::STXRH:
3478 case AArch64::STXRW:
3479 case AArch64::STXRX:
3480 case AArch64::STLXRB:
3481 case AArch64::STLXRH:
3482 case AArch64::STLXRW:
3483 case AArch64::STLXRX: {
3484 unsigned Rs = Inst.getOperand(0).getReg();
3485 unsigned Rt = Inst.getOperand(1).getReg();
3486 unsigned Rn = Inst.getOperand(2).getReg();
3487 if (RI->isSubRegisterEq(Rt, Rs) ||
3488 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3489 return Error(Loc[0],
3490 "unpredictable STXR instruction, status is also a source");
3491 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003492 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003493 case AArch64::STXPW:
3494 case AArch64::STXPX:
3495 case AArch64::STLXPW:
3496 case AArch64::STLXPX: {
3497 unsigned Rs = Inst.getOperand(0).getReg();
3498 unsigned Rt1 = Inst.getOperand(1).getReg();
3499 unsigned Rt2 = Inst.getOperand(2).getReg();
3500 unsigned Rn = Inst.getOperand(3).getReg();
3501 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3502 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3503 return Error(Loc[0],
3504 "unpredictable STXP instruction, status is also a source");
3505 break;
3506 }
3507 }
3508
Tim Northover3b0846e2014-05-24 12:50:23 +00003509
3510 // Now check immediate ranges. Separate from the above as there is overlap
3511 // in the instructions being checked and this keeps the nested conditionals
3512 // to a minimum.
3513 switch (Inst.getOpcode()) {
3514 case AArch64::ADDSWri:
3515 case AArch64::ADDSXri:
3516 case AArch64::ADDWri:
3517 case AArch64::ADDXri:
3518 case AArch64::SUBSWri:
3519 case AArch64::SUBSXri:
3520 case AArch64::SUBWri:
3521 case AArch64::SUBXri: {
3522 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3523 // some slight duplication here.
3524 if (Inst.getOperand(2).isExpr()) {
3525 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3526 AArch64MCExpr::VariantKind ELFRefKind;
3527 MCSymbolRefExpr::VariantKind DarwinRefKind;
3528 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003529 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3530
3531 // Only allow these with ADDXri.
3532 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3533 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3534 Inst.getOpcode() == AArch64::ADDXri)
3535 return false;
3536
3537 // Only allow these with ADDXri/ADDWri
3538 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3539 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3540 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3541 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3542 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3543 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3544 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003545 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3546 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3547 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003548 (Inst.getOpcode() == AArch64::ADDXri ||
3549 Inst.getOpcode() == AArch64::ADDWri))
3550 return false;
3551
3552 // Don't allow symbol refs in the immediate field otherwise
3553 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3554 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3555 // 'cmp w0, 'borked')
3556 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003557 }
Diana Picusc93518d2016-10-11 09:17:47 +00003558 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003559 }
3560 return false;
3561 }
3562 default:
3563 return false;
3564 }
3565}
3566
Craig Topper05515562017-10-26 06:46:41 +00003567static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3568 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003569
3570bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3571 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003572 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003573 case Match_InvalidTiedOperand:
3574 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003575 case Match_MissingFeature:
3576 return Error(Loc,
3577 "instruction requires a CPU feature not currently enabled");
3578 case Match_InvalidOperand:
3579 return Error(Loc, "invalid operand for instruction");
3580 case Match_InvalidSuffix:
3581 return Error(Loc, "invalid type suffix for instruction");
3582 case Match_InvalidCondCode:
3583 return Error(Loc, "expected AArch64 condition code");
3584 case Match_AddSubRegExtendSmall:
3585 return Error(Loc,
3586 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3587 case Match_AddSubRegExtendLarge:
3588 return Error(Loc,
3589 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3590 case Match_AddSubSecondSource:
3591 return Error(Loc,
3592 "expected compatible register, symbol or integer in range [0, 4095]");
3593 case Match_LogicalSecondSource:
3594 return Error(Loc, "expected compatible register or logical immediate");
3595 case Match_InvalidMovImm32Shift:
3596 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3597 case Match_InvalidMovImm64Shift:
3598 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3599 case Match_AddSubRegShift32:
3600 return Error(Loc,
3601 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3602 case Match_AddSubRegShift64:
3603 return Error(Loc,
3604 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3605 case Match_InvalidFPImm:
3606 return Error(Loc,
3607 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003608 case Match_InvalidMemoryIndexedSImm6:
3609 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003610 case Match_InvalidMemoryIndexedSImm5:
3611 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003612 case Match_InvalidMemoryIndexed1SImm4:
3613 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003614 case Match_InvalidMemoryIndexed2SImm4:
3615 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003616 case Match_InvalidMemoryIndexed3SImm4:
3617 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003618 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00003619 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003620 case Match_InvalidMemoryIndexedSImm9:
3621 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00003622 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00003623 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003624 case Match_InvalidMemoryIndexed4SImm7:
3625 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3626 case Match_InvalidMemoryIndexed8SImm7:
3627 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3628 case Match_InvalidMemoryIndexed16SImm7:
3629 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00003630 case Match_InvalidMemoryIndexed8UImm5:
3631 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
3632 case Match_InvalidMemoryIndexed4UImm5:
3633 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
3634 case Match_InvalidMemoryIndexed2UImm5:
3635 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003636 case Match_InvalidMemoryWExtend8:
3637 return Error(Loc,
3638 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3639 case Match_InvalidMemoryWExtend16:
3640 return Error(Loc,
3641 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3642 case Match_InvalidMemoryWExtend32:
3643 return Error(Loc,
3644 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3645 case Match_InvalidMemoryWExtend64:
3646 return Error(Loc,
3647 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3648 case Match_InvalidMemoryWExtend128:
3649 return Error(Loc,
3650 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3651 case Match_InvalidMemoryXExtend8:
3652 return Error(Loc,
3653 "expected 'lsl' or 'sxtx' with optional shift of #0");
3654 case Match_InvalidMemoryXExtend16:
3655 return Error(Loc,
3656 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3657 case Match_InvalidMemoryXExtend32:
3658 return Error(Loc,
3659 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3660 case Match_InvalidMemoryXExtend64:
3661 return Error(Loc,
3662 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3663 case Match_InvalidMemoryXExtend128:
3664 return Error(Loc,
3665 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3666 case Match_InvalidMemoryIndexed1:
3667 return Error(Loc, "index must be an integer in range [0, 4095].");
3668 case Match_InvalidMemoryIndexed2:
3669 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3670 case Match_InvalidMemoryIndexed4:
3671 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3672 case Match_InvalidMemoryIndexed8:
3673 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3674 case Match_InvalidMemoryIndexed16:
3675 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003676 case Match_InvalidImm0_1:
3677 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003678 case Match_InvalidImm0_7:
3679 return Error(Loc, "immediate must be an integer in range [0, 7].");
3680 case Match_InvalidImm0_15:
3681 return Error(Loc, "immediate must be an integer in range [0, 15].");
3682 case Match_InvalidImm0_31:
3683 return Error(Loc, "immediate must be an integer in range [0, 31].");
3684 case Match_InvalidImm0_63:
3685 return Error(Loc, "immediate must be an integer in range [0, 63].");
3686 case Match_InvalidImm0_127:
3687 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003688 case Match_InvalidImm0_255:
3689 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003690 case Match_InvalidImm0_65535:
3691 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3692 case Match_InvalidImm1_8:
3693 return Error(Loc, "immediate must be an integer in range [1, 8].");
3694 case Match_InvalidImm1_16:
3695 return Error(Loc, "immediate must be an integer in range [1, 16].");
3696 case Match_InvalidImm1_32:
3697 return Error(Loc, "immediate must be an integer in range [1, 32].");
3698 case Match_InvalidImm1_64:
3699 return Error(Loc, "immediate must be an integer in range [1, 64].");
3700 case Match_InvalidIndex1:
3701 return Error(Loc, "expected lane specifier '[1]'");
3702 case Match_InvalidIndexB:
3703 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3704 case Match_InvalidIndexH:
3705 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3706 case Match_InvalidIndexS:
3707 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3708 case Match_InvalidIndexD:
3709 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3710 case Match_InvalidLabel:
3711 return Error(Loc, "expected label or encodable integer pc offset");
3712 case Match_MRS:
3713 return Error(Loc, "expected readable system register");
3714 case Match_MSR:
3715 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003716 case Match_InvalidComplexRotationEven:
3717 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3718 case Match_InvalidComplexRotationOdd:
3719 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003720 case Match_MnemonicFail: {
3721 std::string Suggestion = AArch64MnemonicSpellCheck(
3722 ((AArch64Operand &)*Operands[0]).getToken(),
3723 ComputeAvailableFeatures(STI->getFeatureBits()));
3724 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3725 }
Sander de Smalen367694b2018-04-20 08:54:49 +00003726 case Match_InvalidGPR64shifted8:
3727 return Error(Loc, "register must be x0..x30 or xzr, without shift");
3728 case Match_InvalidGPR64shifted16:
3729 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
3730 case Match_InvalidGPR64shifted32:
3731 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
3732 case Match_InvalidGPR64shifted64:
3733 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
3734 case Match_InvalidGPR64NoXZRshifted8:
3735 return Error(Loc, "register must be x0..x30 without shift");
3736 case Match_InvalidGPR64NoXZRshifted16:
3737 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
3738 case Match_InvalidGPR64NoXZRshifted32:
3739 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
3740 case Match_InvalidGPR64NoXZRshifted64:
3741 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00003742 case Match_InvalidZPR32UXTW8:
3743 case Match_InvalidZPR32SXTW8:
3744 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
3745 case Match_InvalidZPR32UXTW16:
3746 case Match_InvalidZPR32SXTW16:
3747 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
3748 case Match_InvalidZPR32UXTW32:
3749 case Match_InvalidZPR32SXTW32:
3750 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
3751 case Match_InvalidZPR32UXTW64:
3752 case Match_InvalidZPR32SXTW64:
3753 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
3754 case Match_InvalidZPR64UXTW8:
3755 case Match_InvalidZPR64SXTW8:
3756 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
3757 case Match_InvalidZPR64UXTW16:
3758 case Match_InvalidZPR64SXTW16:
3759 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
3760 case Match_InvalidZPR64UXTW32:
3761 case Match_InvalidZPR64SXTW32:
3762 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
3763 case Match_InvalidZPR64UXTW64:
3764 case Match_InvalidZPR64SXTW64:
3765 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
3766 case Match_InvalidZPR64LSL8:
3767 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
3768 case Match_InvalidZPR64LSL16:
3769 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
3770 case Match_InvalidZPR64LSL32:
3771 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
3772 case Match_InvalidZPR64LSL64:
3773 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003774 case Match_InvalidSVEPattern:
3775 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003776 case Match_InvalidSVEPredicateAnyReg:
3777 case Match_InvalidSVEPredicateBReg:
3778 case Match_InvalidSVEPredicateHReg:
3779 case Match_InvalidSVEPredicateSReg:
3780 case Match_InvalidSVEPredicateDReg:
3781 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003782 case Match_InvalidSVEPredicate3bAnyReg:
3783 case Match_InvalidSVEPredicate3bBReg:
3784 case Match_InvalidSVEPredicate3bHReg:
3785 case Match_InvalidSVEPredicate3bSReg:
3786 case Match_InvalidSVEPredicate3bDReg:
3787 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003788 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003789 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003790 }
3791}
3792
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003793static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003794
3795bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3796 OperandVector &Operands,
3797 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003798 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003799 bool MatchingInlineAsm) {
3800 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003801 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3802 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003803
David Blaikie960ea3f2014-06-08 16:18:35 +00003804 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003805 unsigned NumOperands = Operands.size();
3806
3807 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003808 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3809 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003810 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003811 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003812 if (Op3CE) {
3813 uint64_t Op3Val = Op3CE->getValue();
3814 uint64_t NewOp3Val = 0;
3815 uint64_t NewOp4Val = 0;
3816 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003817 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003818 NewOp3Val = (32 - Op3Val) & 0x1f;
3819 NewOp4Val = 31 - Op3Val;
3820 } else {
3821 NewOp3Val = (64 - Op3Val) & 0x3f;
3822 NewOp4Val = 63 - Op3Val;
3823 }
3824
Jim Grosbach13760bd2015-05-30 01:25:56 +00003825 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3826 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003827
3828 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003829 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003830 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003831 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3832 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3833 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003834 }
3835 }
Tim Northover03b99f62015-04-30 18:28:58 +00003836 } else if (NumOperands == 4 && Tok == "bfc") {
3837 // FIXME: Horrible hack to handle BFC->BFM alias.
3838 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3839 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3840 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3841
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003842 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003843 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3844 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3845
3846 if (LSBCE && WidthCE) {
3847 uint64_t LSB = LSBCE->getValue();
3848 uint64_t Width = WidthCE->getValue();
3849
3850 uint64_t RegWidth = 0;
3851 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3852 Op1.getReg()))
3853 RegWidth = 64;
3854 else
3855 RegWidth = 32;
3856
3857 if (LSB >= RegWidth)
3858 return Error(LSBOp.getStartLoc(),
3859 "expected integer in range [0, 31]");
3860 if (Width < 1 || Width > RegWidth)
3861 return Error(WidthOp.getStartLoc(),
3862 "expected integer in range [1, 32]");
3863
3864 uint64_t ImmR = 0;
3865 if (RegWidth == 32)
3866 ImmR = (32 - LSB) & 0x1f;
3867 else
3868 ImmR = (64 - LSB) & 0x3f;
3869
3870 uint64_t ImmS = Width - 1;
3871
3872 if (ImmR != 0 && ImmS >= ImmR)
3873 return Error(WidthOp.getStartLoc(),
3874 "requested insert overflows register");
3875
Jim Grosbach13760bd2015-05-30 01:25:56 +00003876 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3877 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003878 Operands[0] = AArch64Operand::CreateToken(
3879 "bfm", false, Op.getStartLoc(), getContext());
3880 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003881 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3882 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003883 Operands[3] = AArch64Operand::CreateImm(
3884 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3885 Operands.emplace_back(
3886 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3887 WidthOp.getEndLoc(), getContext()));
3888 }
3889 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003890 } else if (NumOperands == 5) {
3891 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3892 // UBFIZ -> UBFM aliases.
3893 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003894 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3895 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3896 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003897
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003898 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003899 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3900 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003901
3902 if (Op3CE && Op4CE) {
3903 uint64_t Op3Val = Op3CE->getValue();
3904 uint64_t Op4Val = Op4CE->getValue();
3905
3906 uint64_t RegWidth = 0;
3907 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003908 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003909 RegWidth = 64;
3910 else
3911 RegWidth = 32;
3912
3913 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003914 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003915 "expected integer in range [0, 31]");
3916 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003917 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003918 "expected integer in range [1, 32]");
3919
3920 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003921 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003922 NewOp3Val = (32 - Op3Val) & 0x1f;
3923 else
3924 NewOp3Val = (64 - Op3Val) & 0x3f;
3925
3926 uint64_t NewOp4Val = Op4Val - 1;
3927
3928 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003929 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003930 "requested insert overflows register");
3931
3932 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003933 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003934 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003935 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003936 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003937 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003938 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003939 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003940 if (Tok == "bfi")
3941 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003942 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003943 else if (Tok == "sbfiz")
3944 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003945 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003946 else if (Tok == "ubfiz")
3947 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003948 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003949 else
3950 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003951 }
3952 }
3953
3954 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3955 // UBFX -> UBFM aliases.
3956 } else if (NumOperands == 5 &&
3957 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003958 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3959 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3960 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003961
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003962 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003963 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3964 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003965
3966 if (Op3CE && Op4CE) {
3967 uint64_t Op3Val = Op3CE->getValue();
3968 uint64_t Op4Val = Op4CE->getValue();
3969
3970 uint64_t RegWidth = 0;
3971 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003972 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003973 RegWidth = 64;
3974 else
3975 RegWidth = 32;
3976
3977 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003978 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003979 "expected integer in range [0, 31]");
3980 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003981 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003982 "expected integer in range [1, 32]");
3983
3984 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3985
3986 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003987 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003988 "requested extract overflows register");
3989
3990 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003991 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003992 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003993 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003994 if (Tok == "bfxil")
3995 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003996 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003997 else if (Tok == "sbfx")
3998 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003999 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004000 else if (Tok == "ubfx")
4001 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004002 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004003 else
4004 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004005 }
4006 }
4007 }
4008 }
Tim Northover9097a072017-12-18 10:36:00 +00004009
4010 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4011 // instruction for FP registers correctly in some rare circumstances. Convert
4012 // it to a safe instruction and warn (because silently changing someone's
4013 // assembly is rude).
4014 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4015 NumOperands == 4 && Tok == "movi") {
4016 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4017 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4018 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4019 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4020 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4021 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4022 if (Suffix.lower() == ".2d" &&
4023 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4024 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4025 " correctly on this CPU, converting to equivalent movi.16b");
4026 // Switch the suffix to .16b.
4027 unsigned Idx = Op1.isToken() ? 1 : 2;
4028 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4029 getContext());
4030 }
4031 }
4032 }
4033
Tim Northover3b0846e2014-05-24 12:50:23 +00004034 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4035 // InstAlias can't quite handle this since the reg classes aren't
4036 // subclasses.
4037 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4038 // The source register can be Wn here, but the matcher expects a
4039 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004040 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004041 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004042 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004043 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4044 Op.getStartLoc(), Op.getEndLoc(),
4045 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004046 }
4047 }
4048 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4049 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004050 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004051 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004052 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004053 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004054 // The source register can be Wn here, but the matcher expects a
4055 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004056 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004057 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004058 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004059 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4060 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004061 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004062 }
4063 }
4064 }
4065 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4066 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004067 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004068 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004069 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004070 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004071 // The source register can be Wn here, but the matcher expects a
4072 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004073 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004074 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004075 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004076 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4077 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004078 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004079 }
4080 }
4081 }
4082
Tim Northover3b0846e2014-05-24 12:50:23 +00004083 MCInst Inst;
4084 // First try to match against the secondary set of tables containing the
4085 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4086 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004087 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004088
4089 // If that fails, try against the alternate table containing long-form NEON:
4090 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004091 if (MatchResult != Match_Success) {
4092 // But first, save the short-form match result: we can use it in case the
4093 // long-form match also fails.
4094 auto ShortFormNEONErrorInfo = ErrorInfo;
4095 auto ShortFormNEONMatchResult = MatchResult;
4096
Tim Northover3b0846e2014-05-24 12:50:23 +00004097 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004098 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004099
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004100 // Now, both matches failed, and the long-form match failed on the mnemonic
4101 // suffix token operand. The short-form match failure is probably more
4102 // relevant: use it instead.
4103 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004104 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004105 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4106 MatchResult = ShortFormNEONMatchResult;
4107 ErrorInfo = ShortFormNEONErrorInfo;
4108 }
4109 }
4110
Tim Northover3b0846e2014-05-24 12:50:23 +00004111 switch (MatchResult) {
4112 case Match_Success: {
4113 // Perform range checking and other semantic validations
4114 SmallVector<SMLoc, 8> OperandLocs;
4115 NumOperands = Operands.size();
4116 for (unsigned i = 1; i < NumOperands; ++i)
4117 OperandLocs.push_back(Operands[i]->getStartLoc());
4118 if (validateInstruction(Inst, OperandLocs))
4119 return true;
4120
4121 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004122 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004123 return false;
4124 }
4125 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004126 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004127 // Special case the error message for the very common case where only
4128 // a single subtarget feature is missing (neon, e.g.).
4129 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004130 uint64_t Mask = 1;
4131 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4132 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004133 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004134 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004135 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004136 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004137 }
4138 return Error(IDLoc, Msg);
4139 }
4140 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004141 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004142 case Match_InvalidOperand: {
4143 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004144
Tim Northover26bb14e2014-08-18 11:49:42 +00004145 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004146 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004147 return Error(IDLoc, "too few operands for instruction",
4148 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004149
David Blaikie960ea3f2014-06-08 16:18:35 +00004150 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004151 if (ErrorLoc == SMLoc())
4152 ErrorLoc = IDLoc;
4153 }
4154 // If the match failed on a suffix token operand, tweak the diagnostic
4155 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004156 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4157 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004158 MatchResult = Match_InvalidSuffix;
4159
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004160 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004161 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004162 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004163 case Match_InvalidMemoryIndexed1:
4164 case Match_InvalidMemoryIndexed2:
4165 case Match_InvalidMemoryIndexed4:
4166 case Match_InvalidMemoryIndexed8:
4167 case Match_InvalidMemoryIndexed16:
4168 case Match_InvalidCondCode:
4169 case Match_AddSubRegExtendSmall:
4170 case Match_AddSubRegExtendLarge:
4171 case Match_AddSubSecondSource:
4172 case Match_LogicalSecondSource:
4173 case Match_AddSubRegShift32:
4174 case Match_AddSubRegShift64:
4175 case Match_InvalidMovImm32Shift:
4176 case Match_InvalidMovImm64Shift:
4177 case Match_InvalidFPImm:
4178 case Match_InvalidMemoryWExtend8:
4179 case Match_InvalidMemoryWExtend16:
4180 case Match_InvalidMemoryWExtend32:
4181 case Match_InvalidMemoryWExtend64:
4182 case Match_InvalidMemoryWExtend128:
4183 case Match_InvalidMemoryXExtend8:
4184 case Match_InvalidMemoryXExtend16:
4185 case Match_InvalidMemoryXExtend32:
4186 case Match_InvalidMemoryXExtend64:
4187 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004188 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004189 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004190 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004191 case Match_InvalidMemoryIndexed4SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004192 case Match_InvalidMemoryIndexed4SImm7:
4193 case Match_InvalidMemoryIndexed8SImm7:
4194 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004195 case Match_InvalidMemoryIndexed8UImm5:
4196 case Match_InvalidMemoryIndexed4UImm5:
4197 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalen5c625982018-04-13 12:56:14 +00004198 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004199 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004200 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004201 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004202 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004203 case Match_InvalidImm0_7:
4204 case Match_InvalidImm0_15:
4205 case Match_InvalidImm0_31:
4206 case Match_InvalidImm0_63:
4207 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004208 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004209 case Match_InvalidImm0_65535:
4210 case Match_InvalidImm1_8:
4211 case Match_InvalidImm1_16:
4212 case Match_InvalidImm1_32:
4213 case Match_InvalidImm1_64:
4214 case Match_InvalidIndex1:
4215 case Match_InvalidIndexB:
4216 case Match_InvalidIndexH:
4217 case Match_InvalidIndexS:
4218 case Match_InvalidIndexD:
4219 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004220 case Match_InvalidComplexRotationEven:
4221 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004222 case Match_InvalidGPR64shifted8:
4223 case Match_InvalidGPR64shifted16:
4224 case Match_InvalidGPR64shifted32:
4225 case Match_InvalidGPR64shifted64:
4226 case Match_InvalidGPR64NoXZRshifted8:
4227 case Match_InvalidGPR64NoXZRshifted16:
4228 case Match_InvalidGPR64NoXZRshifted32:
4229 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004230 case Match_InvalidZPR32UXTW8:
4231 case Match_InvalidZPR32UXTW16:
4232 case Match_InvalidZPR32UXTW32:
4233 case Match_InvalidZPR32UXTW64:
4234 case Match_InvalidZPR32SXTW8:
4235 case Match_InvalidZPR32SXTW16:
4236 case Match_InvalidZPR32SXTW32:
4237 case Match_InvalidZPR32SXTW64:
4238 case Match_InvalidZPR64UXTW8:
4239 case Match_InvalidZPR64SXTW8:
4240 case Match_InvalidZPR64UXTW16:
4241 case Match_InvalidZPR64SXTW16:
4242 case Match_InvalidZPR64UXTW32:
4243 case Match_InvalidZPR64SXTW32:
4244 case Match_InvalidZPR64UXTW64:
4245 case Match_InvalidZPR64SXTW64:
4246 case Match_InvalidZPR64LSL8:
4247 case Match_InvalidZPR64LSL16:
4248 case Match_InvalidZPR64LSL32:
4249 case Match_InvalidZPR64LSL64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004250 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004251 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004252 case Match_InvalidSVEPredicateBReg:
4253 case Match_InvalidSVEPredicateHReg:
4254 case Match_InvalidSVEPredicateSReg:
4255 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004256 case Match_InvalidSVEPredicate3bAnyReg:
4257 case Match_InvalidSVEPredicate3bBReg:
4258 case Match_InvalidSVEPredicate3bHReg:
4259 case Match_InvalidSVEPredicate3bSReg:
4260 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004261 case Match_MSR:
4262 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004263 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004264 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004265 // Any time we get here, there's nothing fancy to do. Just get the
4266 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004267 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004268 if (ErrorLoc == SMLoc())
4269 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004270 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004271 }
4272 }
4273
4274 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004275}
4276
4277/// ParseDirective parses the arm specific directives
4278bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004279 const MCObjectFileInfo::Environment Format =
4280 getContext().getObjectFileInfo()->getObjectFileType();
4281 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4282 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004283
Tim Northover3b0846e2014-05-24 12:50:23 +00004284 StringRef IDVal = DirectiveID.getIdentifier();
4285 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004286 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004287 parseDirectiveArch(Loc);
4288 else if (IDVal == ".cpu")
4289 parseDirectiveCPU(Loc);
4290 else if (IDVal == ".hword")
4291 parseDirectiveWord(2, Loc);
4292 else if (IDVal == ".word")
4293 parseDirectiveWord(4, Loc);
4294 else if (IDVal == ".xword")
4295 parseDirectiveWord(8, Loc);
4296 else if (IDVal == ".tlsdesccall")
4297 parseDirectiveTLSDescCall(Loc);
4298 else if (IDVal == ".ltorg" || IDVal == ".pool")
4299 parseDirectiveLtorg(Loc);
4300 else if (IDVal == ".unreq")
4301 parseDirectiveUnreq(Loc);
4302 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004303 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004304 parseDirectiveInst(Loc);
4305 else
4306 return true;
4307 } else if (IDVal == MCLOHDirectiveName())
4308 parseDirectiveLOH(IDVal, Loc);
4309 else
4310 return true;
4311 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004312}
4313
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004314static const struct {
4315 const char *Name;
4316 const FeatureBitset Features;
4317} ExtensionMap[] = {
4318 { "crc", {AArch64::FeatureCRC} },
4319 { "crypto", {AArch64::FeatureCrypto} },
4320 { "fp", {AArch64::FeatureFPARMv8} },
4321 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004322 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004323 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004324
4325 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004326 { "pan", {} },
4327 { "lor", {} },
4328 { "rdma", {} },
4329 { "profile", {} },
4330};
4331
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004332/// parseDirectiveArch
4333/// ::= .arch token
4334bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4335 SMLoc ArchLoc = getLoc();
4336
4337 StringRef Arch, ExtensionString;
4338 std::tie(Arch, ExtensionString) =
4339 getParser().parseStringToEndOfStatement().trim().split('+');
4340
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004341 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4342 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004343 return Error(ArchLoc, "unknown arch name");
4344
4345 if (parseToken(AsmToken::EndOfStatement))
4346 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004347
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004348 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004349 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004350 AArch64::getArchFeatures(ID, AArch64Features);
4351 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4352 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004353
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004354 MCSubtargetInfo &STI = copySTI();
4355 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4356 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4357
4358 SmallVector<StringRef, 4> RequestedExtensions;
4359 if (!ExtensionString.empty())
4360 ExtensionString.split(RequestedExtensions, '+');
4361
4362 FeatureBitset Features = STI.getFeatureBits();
4363 for (auto Name : RequestedExtensions) {
4364 bool EnableFeature = true;
4365
4366 if (Name.startswith_lower("no")) {
4367 EnableFeature = false;
4368 Name = Name.substr(2);
4369 }
4370
4371 for (const auto &Extension : ExtensionMap) {
4372 if (Extension.Name != Name)
4373 continue;
4374
4375 if (Extension.Features.none())
4376 report_fatal_error("unsupported architectural extension: " + Name);
4377
4378 FeatureBitset ToggleFeatures = EnableFeature
4379 ? (~Features & Extension.Features)
4380 : ( Features & Extension.Features);
4381 uint64_t Features =
4382 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4383 setAvailableFeatures(Features);
4384 break;
4385 }
4386 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004387 return false;
4388}
4389
Tim Northover8b96c7e2017-05-15 19:42:15 +00004390static SMLoc incrementLoc(SMLoc L, int Offset) {
4391 return SMLoc::getFromPointer(L.getPointer() + Offset);
4392}
4393
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004394/// parseDirectiveCPU
4395/// ::= .cpu id
4396bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004397 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004398
4399 StringRef CPU, ExtensionString;
4400 std::tie(CPU, ExtensionString) =
4401 getParser().parseStringToEndOfStatement().trim().split('+');
4402
Nirav Davee833c6c2016-11-08 18:31:04 +00004403 if (parseToken(AsmToken::EndOfStatement))
4404 return true;
4405
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004406 SmallVector<StringRef, 4> RequestedExtensions;
4407 if (!ExtensionString.empty())
4408 ExtensionString.split(RequestedExtensions, '+');
4409
4410 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4411 // once that is tablegen'ed
4412 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004413 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004414 return false;
4415 }
4416
4417 MCSubtargetInfo &STI = copySTI();
4418 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004419 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004420
4421 FeatureBitset Features = STI.getFeatureBits();
4422 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004423 // Advance source location past '+'.
4424 CurLoc = incrementLoc(CurLoc, 1);
4425
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004426 bool EnableFeature = true;
4427
4428 if (Name.startswith_lower("no")) {
4429 EnableFeature = false;
4430 Name = Name.substr(2);
4431 }
4432
Tim Northover8b96c7e2017-05-15 19:42:15 +00004433 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004434 for (const auto &Extension : ExtensionMap) {
4435 if (Extension.Name != Name)
4436 continue;
4437
4438 if (Extension.Features.none())
4439 report_fatal_error("unsupported architectural extension: " + Name);
4440
4441 FeatureBitset ToggleFeatures = EnableFeature
4442 ? (~Features & Extension.Features)
4443 : ( Features & Extension.Features);
4444 uint64_t Features =
4445 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4446 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004447 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004448
4449 break;
4450 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004451
4452 if (!FoundExtension)
4453 Error(CurLoc, "unsupported architectural extension");
4454
4455 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004456 }
4457 return false;
4458}
4459
Tim Northover3b0846e2014-05-24 12:50:23 +00004460/// parseDirectiveWord
4461/// ::= .word [ expression (, expression)* ]
4462bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004463 auto parseOp = [&]() -> bool {
4464 const MCExpr *Value;
4465 if (getParser().parseExpression(Value))
4466 return true;
4467 getParser().getStreamer().EmitValue(Value, Size, L);
4468 return false;
4469 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004470
Nirav Davee833c6c2016-11-08 18:31:04 +00004471 if (parseMany(parseOp))
4472 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004473 return false;
4474}
4475
Chad Rosierdcd2a302014-10-22 20:35:57 +00004476/// parseDirectiveInst
4477/// ::= .inst opcode [, ...]
4478bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004479 if (getLexer().is(AsmToken::EndOfStatement))
4480 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004481
Nirav Davee833c6c2016-11-08 18:31:04 +00004482 auto parseOp = [&]() -> bool {
4483 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004484 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004485 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4486 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004487 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004488 if (check(!Value, L, "expected constant expression"))
4489 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004490 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004491 return false;
4492 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004493
Nirav Davee833c6c2016-11-08 18:31:04 +00004494 if (parseMany(parseOp))
4495 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004496 return false;
4497}
4498
Tim Northover3b0846e2014-05-24 12:50:23 +00004499// parseDirectiveTLSDescCall:
4500// ::= .tlsdesccall symbol
4501bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4502 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004503 if (check(getParser().parseIdentifier(Name), L,
4504 "expected symbol after directive") ||
4505 parseToken(AsmToken::EndOfStatement))
4506 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004507
Jim Grosbach6f482002015-05-18 18:43:14 +00004508 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004509 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4510 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004511
4512 MCInst Inst;
4513 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004514 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004515
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004516 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004517 return false;
4518}
4519
4520/// ::= .loh <lohName | lohId> label1, ..., labelN
4521/// The number of arguments depends on the loh identifier.
4522bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004523 MCLOHType Kind;
4524 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4525 if (getParser().getTok().isNot(AsmToken::Integer))
4526 return TokError("expected an identifier or a number in directive");
4527 // We successfully get a numeric value for the identifier.
4528 // Check if it is valid.
4529 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004530 if (Id <= -1U && !isValidMCLOHType(Id))
4531 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004532 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004533 } else {
4534 StringRef Name = getTok().getIdentifier();
4535 // We successfully parse an identifier.
4536 // Check if it is a recognized one.
4537 int Id = MCLOHNameToId(Name);
4538
4539 if (Id == -1)
4540 return TokError("invalid identifier in directive");
4541 Kind = (MCLOHType)Id;
4542 }
4543 // Consume the identifier.
4544 Lex();
4545 // Get the number of arguments of this LOH.
4546 int NbArgs = MCLOHIdToNbArgs(Kind);
4547
4548 assert(NbArgs != -1 && "Invalid number of arguments");
4549
4550 SmallVector<MCSymbol *, 3> Args;
4551 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4552 StringRef Name;
4553 if (getParser().parseIdentifier(Name))
4554 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004555 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004556
4557 if (Idx + 1 == NbArgs)
4558 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004559 if (parseToken(AsmToken::Comma,
4560 "unexpected token in '" + Twine(IDVal) + "' directive"))
4561 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004562 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004563 if (parseToken(AsmToken::EndOfStatement,
4564 "unexpected token in '" + Twine(IDVal) + "' directive"))
4565 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004566
4567 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4568 return false;
4569}
4570
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004571/// parseDirectiveLtorg
4572/// ::= .ltorg | .pool
4573bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004574 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4575 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004576 getTargetStreamer().emitCurrentConstantPool();
4577 return false;
4578}
4579
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004580/// parseDirectiveReq
4581/// ::= name .req registername
4582bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004583 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004584 Parser.Lex(); // Eat the '.req' token.
4585 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004586 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004587 unsigned RegNum;
4588 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004589
Sander de Smalen50d87022018-04-19 07:35:08 +00004590 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004591 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004592 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004593 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004594
Sander de Smalen50d87022018-04-19 07:35:08 +00004595 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004596 return true;
4597
Sander de Smalen50d87022018-04-19 07:35:08 +00004598 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004599 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004600 }
4601
Sander de Smalen50d87022018-04-19 07:35:08 +00004602 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004603 StringRef Kind;
4604 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004605 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004606 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004607
Sander de Smalen50d87022018-04-19 07:35:08 +00004608 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004609 return true;
4610
Sander de Smalen50d87022018-04-19 07:35:08 +00004611 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004612 return Error(SRegLoc,
4613 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004614 }
4615
Sander de Smalen50d87022018-04-19 07:35:08 +00004616 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00004617 StringRef Kind;
4618 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004619 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004620
Sander de Smalen50d87022018-04-19 07:35:08 +00004621 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00004622 return true;
4623
Sander de Smalen50d87022018-04-19 07:35:08 +00004624 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00004625 return Error(SRegLoc,
4626 "sve predicate register without type specifier expected");
4627 }
4628
Sander de Smalen50d87022018-04-19 07:35:08 +00004629 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00004630 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004631
4632 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004633 if (parseToken(AsmToken::EndOfStatement,
4634 "unexpected input in .req directive"))
4635 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004636
Sander de Smalen8e607342017-11-15 15:44:43 +00004637 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004638 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004639 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4640
Nirav Dave2364748a2016-09-16 18:30:20 +00004641 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004642}
4643
4644/// parseDirectiveUneq
4645/// ::= .unreq registername
4646bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004647 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004648 if (getTok().isNot(AsmToken::Identifier))
4649 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004650 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4651 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004652 if (parseToken(AsmToken::EndOfStatement))
4653 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004654 return false;
4655}
4656
Tim Northover3b0846e2014-05-24 12:50:23 +00004657bool
4658AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4659 AArch64MCExpr::VariantKind &ELFRefKind,
4660 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4661 int64_t &Addend) {
4662 ELFRefKind = AArch64MCExpr::VK_INVALID;
4663 DarwinRefKind = MCSymbolRefExpr::VK_None;
4664 Addend = 0;
4665
4666 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4667 ELFRefKind = AE->getKind();
4668 Expr = AE->getSubExpr();
4669 }
4670
4671 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4672 if (SE) {
4673 // It's a simple symbol reference with no addend.
4674 DarwinRefKind = SE->getKind();
4675 return true;
4676 }
4677
4678 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4679 if (!BE)
4680 return false;
4681
4682 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4683 if (!SE)
4684 return false;
4685 DarwinRefKind = SE->getKind();
4686
4687 if (BE->getOpcode() != MCBinaryExpr::Add &&
4688 BE->getOpcode() != MCBinaryExpr::Sub)
4689 return false;
4690
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004691 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004692 // on here than we can deal with.
4693 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4694 if (!AddendExpr)
4695 return false;
4696
4697 Addend = AddendExpr->getValue();
4698 if (BE->getOpcode() == MCBinaryExpr::Sub)
4699 Addend = -Addend;
4700
4701 // It's some symbol reference + a constant addend, but really
4702 // shouldn't use both Darwin and ELF syntax.
4703 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4704 DarwinRefKind == MCSymbolRefExpr::VK_None;
4705}
4706
4707/// Force static initialization.
4708extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004709 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4710 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4711 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004712}
4713
4714#define GET_REGISTER_MATCHER
4715#define GET_SUBTARGET_FEATURE_NAME
4716#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004717#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004718#include "AArch64GenAsmMatcher.inc"
4719
4720// Define this matcher function after the auto-generated include so we
4721// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004722unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004723 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004724 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004725 // If the kind is a token for a literal immediate, check if our asm
4726 // operand matches. This is for InstAliases which have a fixed-value
4727 // immediate in the syntax.
4728 int64_t ExpectedVal;
4729 switch (Kind) {
4730 default:
4731 return Match_InvalidOperand;
4732 case MCK__35_0:
4733 ExpectedVal = 0;
4734 break;
4735 case MCK__35_1:
4736 ExpectedVal = 1;
4737 break;
4738 case MCK__35_12:
4739 ExpectedVal = 12;
4740 break;
4741 case MCK__35_16:
4742 ExpectedVal = 16;
4743 break;
4744 case MCK__35_2:
4745 ExpectedVal = 2;
4746 break;
4747 case MCK__35_24:
4748 ExpectedVal = 24;
4749 break;
4750 case MCK__35_3:
4751 ExpectedVal = 3;
4752 break;
4753 case MCK__35_32:
4754 ExpectedVal = 32;
4755 break;
4756 case MCK__35_4:
4757 ExpectedVal = 4;
4758 break;
4759 case MCK__35_48:
4760 ExpectedVal = 48;
4761 break;
4762 case MCK__35_6:
4763 ExpectedVal = 6;
4764 break;
4765 case MCK__35_64:
4766 ExpectedVal = 64;
4767 break;
4768 case MCK__35_8:
4769 ExpectedVal = 8;
4770 break;
4771 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004772 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004773 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004774 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004775 if (!CE)
4776 return Match_InvalidOperand;
4777 if (CE->getValue() == ExpectedVal)
4778 return Match_Success;
4779 return Match_InvalidOperand;
4780}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004781
Alex Bradbury58eba092016-11-01 16:32:05 +00004782OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004783AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4784
4785 SMLoc S = getLoc();
4786
4787 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4788 Error(S, "expected register");
4789 return MatchOperand_ParseFail;
4790 }
4791
Sander de Smalen50d87022018-04-19 07:35:08 +00004792 unsigned FirstReg;
4793 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
4794 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004795 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00004796
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004797 const MCRegisterClass &WRegClass =
4798 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4799 const MCRegisterClass &XRegClass =
4800 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4801
4802 bool isXReg = XRegClass.contains(FirstReg),
4803 isWReg = WRegClass.contains(FirstReg);
4804 if (!isXReg && !isWReg) {
4805 Error(S, "expected first even register of a "
4806 "consecutive same-size even/odd register pair");
4807 return MatchOperand_ParseFail;
4808 }
4809
4810 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4811 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4812
4813 if (FirstEncoding & 0x1) {
4814 Error(S, "expected first even register of a "
4815 "consecutive same-size even/odd register pair");
4816 return MatchOperand_ParseFail;
4817 }
4818
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004819 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00004820 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004821 return MatchOperand_ParseFail;
4822 }
4823 // Eat the comma
4824 getParser().Lex();
4825
4826 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00004827 unsigned SecondReg;
4828 Res = tryParseScalarRegister(SecondReg);
4829 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004830 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004831
Eugene Zelenko049b0172017-01-06 00:30:53 +00004832 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004833 (isXReg && !XRegClass.contains(SecondReg)) ||
4834 (isWReg && !WRegClass.contains(SecondReg))) {
4835 Error(E,"expected second odd register of a "
4836 "consecutive same-size even/odd register pair");
4837 return MatchOperand_ParseFail;
4838 }
Joel Jones504bf332016-10-24 13:37:13 +00004839
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004840 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004841 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004842 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4843 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4844 } else {
4845 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4846 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4847 }
4848
Florian Hahnc4422242017-11-07 13:07:50 +00004849 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4850 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004851
4852 return MatchOperand_Success;
4853}
Florian Hahn91f11e52017-11-07 16:45:48 +00004854
Sander de Smaleneb896b12018-04-25 09:26:47 +00004855template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00004856OperandMatchResultTy
4857AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004858 const SMLoc S = getLoc();
4859 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00004860 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00004861 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004862
Sander de Smalen8e607342017-11-15 15:44:43 +00004863 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004864 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004865
4866 if (Res != MatchOperand_Success)
4867 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004868
4869 if (ParseSuffix && Kind.empty())
4870 return MatchOperand_NoMatch;
4871
Sander de Smalen73937b72018-04-11 07:36:10 +00004872 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
4873 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00004874 return MatchOperand_NoMatch;
4875
Sander de Smalen73937b72018-04-11 07:36:10 +00004876 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00004877
4878 // No shift/extend is the default.
4879 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
4880 Operands.push_back(AArch64Operand::CreateVectorReg(
4881 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
4882
4883 return MatchOperand_Success;
4884 }
4885
4886 // Eat the comma
4887 getParser().Lex();
4888
4889 // Match the shift
4890 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
4891 Res = tryParseOptionalShiftExtend(ExtOpnd);
4892 if (Res != MatchOperand_Success)
4893 return Res;
4894
4895 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00004896 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00004897 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
4898 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
4899 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00004900
4901 return MatchOperand_Success;
4902}
Sander de Smalen245e0e62018-01-22 10:46:00 +00004903
4904OperandMatchResultTy
4905AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
4906 MCAsmParser &Parser = getParser();
4907
4908 SMLoc SS = getLoc();
4909 const AsmToken &TokE = Parser.getTok();
4910 bool IsHash = TokE.is(AsmToken::Hash);
4911
4912 if (!IsHash && TokE.isNot(AsmToken::Identifier))
4913 return MatchOperand_NoMatch;
4914
4915 int64_t Pattern;
4916 if (IsHash) {
4917 Parser.Lex(); // Eat hash
4918
4919 // Parse the immediate operand.
4920 const MCExpr *ImmVal;
4921 SS = getLoc();
4922 if (Parser.parseExpression(ImmVal))
4923 return MatchOperand_ParseFail;
4924
4925 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4926 if (!MCE)
4927 return MatchOperand_ParseFail;
4928
4929 Pattern = MCE->getValue();
4930 } else {
4931 // Parse the pattern
4932 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
4933 if (!Pat)
4934 return MatchOperand_NoMatch;
4935
4936 Parser.Lex();
4937 Pattern = Pat->Encoding;
4938 assert(Pattern >= 0 && Pattern < 32);
4939 }
4940
4941 Operands.push_back(
4942 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
4943 SS, getLoc(), getContext()));
4944
4945 return MatchOperand_Success;
4946}