blob: 6af1207b58086b495c4ffa16ccac597f62c4641f [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
509 template <int Bits, int Scale> bool isSImmScaled() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000510 if (!isImm())
511 return false;
512 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
513 if (!MCE)
514 return false;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000515
516 int64_t Shift = Bits - 1;
517 int64_t MinVal = (int64_t(1) << Shift) * -Scale;
518 int64_t MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
519
Tim Northover3b0846e2014-05-24 12:50:23 +0000520 int64_t Val = MCE->getValue();
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000521 return Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0;
Tim Northover3b0846e2014-05-24 12:50:23 +0000522 }
523
Sander de Smalen245e0e62018-01-22 10:46:00 +0000524 bool isSVEPattern() const {
525 if (!isImm())
526 return false;
527 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
528 if (!MCE)
529 return false;
530 int64_t Val = MCE->getValue();
531 return Val >= 0 && Val < 32;
532 }
533
Tim Northover3b0846e2014-05-24 12:50:23 +0000534 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
535 AArch64MCExpr::VariantKind ELFRefKind;
536 MCSymbolRefExpr::VariantKind DarwinRefKind;
537 int64_t Addend;
538 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
539 Addend)) {
540 // If we don't understand the expression, assume the best and
541 // let the fixup and relocation code deal with it.
542 return true;
543 }
544
545 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
546 ELFRefKind == AArch64MCExpr::VK_LO12 ||
547 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
548 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
549 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
550 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
551 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
552 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000553 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
554 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
555 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000556 // Note that we don't range-check the addend. It's adjusted modulo page
557 // size when converted, so there is no "out of range" condition when using
558 // @pageoff.
559 return Addend >= 0 && (Addend % Scale) == 0;
560 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
561 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
562 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
563 return Addend == 0;
564 }
565
566 return false;
567 }
568
569 template <int Scale> bool isUImm12Offset() const {
570 if (!isImm())
571 return false;
572
573 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
574 if (!MCE)
575 return isSymbolicUImm12Offset(getImm(), Scale);
576
577 int64_t Val = MCE->getValue();
578 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
579 }
580
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000581 template <int N, int M>
582 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000583 if (!isImm())
584 return false;
585 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
586 if (!MCE)
587 return false;
588 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000589 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000590 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000591
Sander de Smalena1c259c2018-01-29 13:05:38 +0000592 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
593 // a logical immediate can always be represented when inverted.
594 template <typename T>
595 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000596 if (!isImm())
597 return false;
598 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
599 if (!MCE)
600 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000601
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000602 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000603 int64_t SVal = typename std::make_signed<T>::type(Val);
604 int64_t UVal = typename std::make_unsigned<T>::type(Val);
605 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000606 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000607
Sander de Smalena1c259c2018-01-29 13:05:38 +0000608 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000609 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000610
Tim Northover3b0846e2014-05-24 12:50:23 +0000611 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000612
Tim Northover3b0846e2014-05-24 12:50:23 +0000613 bool isAddSubImm() const {
614 if (!isShiftedImm() && !isImm())
615 return false;
616
617 const MCExpr *Expr;
618
619 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
620 if (isShiftedImm()) {
621 unsigned Shift = ShiftedImm.ShiftAmount;
622 Expr = ShiftedImm.Val;
623 if (Shift != 0 && Shift != 12)
624 return false;
625 } else {
626 Expr = getImm();
627 }
628
629 AArch64MCExpr::VariantKind ELFRefKind;
630 MCSymbolRefExpr::VariantKind DarwinRefKind;
631 int64_t Addend;
632 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
633 DarwinRefKind, Addend)) {
634 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
635 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
636 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
637 || ELFRefKind == AArch64MCExpr::VK_LO12
638 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
639 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
640 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
641 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
642 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
643 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000644 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
645 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
646 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000647 }
648
Diana Picusc93518d2016-10-11 09:17:47 +0000649 // If it's a constant, it should be a real immediate in range:
650 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
651 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
652
653 // If it's an expression, we hope for the best and let the fixup/relocation
654 // code deal with it.
655 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000656 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000657
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000658 bool isAddSubImmNeg() const {
659 if (!isShiftedImm() && !isImm())
660 return false;
661
662 const MCExpr *Expr;
663
664 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
665 if (isShiftedImm()) {
666 unsigned Shift = ShiftedImm.ShiftAmount;
667 Expr = ShiftedImm.Val;
668 if (Shift != 0 && Shift != 12)
669 return false;
670 } else
671 Expr = getImm();
672
673 // Otherwise it should be a real negative immediate in range:
674 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
675 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
676 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000677
Tim Northover3b0846e2014-05-24 12:50:23 +0000678 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000679
Tim Northover3b0846e2014-05-24 12:50:23 +0000680 bool isSIMDImmType10() const {
681 if (!isImm())
682 return false;
683 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
684 if (!MCE)
685 return false;
686 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
687 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000688
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000689 template<int N>
690 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000691 if (!isImm())
692 return false;
693 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
694 if (!MCE)
695 return true;
696 int64_t Val = MCE->getValue();
697 if (Val & 0x3)
698 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000699 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
700 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000701 }
702
703 bool
704 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
705 if (!isImm())
706 return false;
707
708 AArch64MCExpr::VariantKind ELFRefKind;
709 MCSymbolRefExpr::VariantKind DarwinRefKind;
710 int64_t Addend;
711 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
712 DarwinRefKind, Addend)) {
713 return false;
714 }
715 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
716 return false;
717
718 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
719 if (ELFRefKind == AllowedModifiers[i])
720 return Addend == 0;
721 }
722
723 return false;
724 }
725
726 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000727 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000728 }
729
730 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000731 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
732 AArch64MCExpr::VK_TPREL_G2,
733 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000734 }
735
736 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000737 return isMovWSymbol({
738 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000739 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
740 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000741 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000742 }
743
744 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000745 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
746 AArch64MCExpr::VK_TPREL_G0,
747 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000748 }
749
750 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000751 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000752 }
753
754 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000755 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000756 }
757
758 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000759 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
760 AArch64MCExpr::VK_TPREL_G1_NC,
761 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000762 }
763
764 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000765 return isMovWSymbol(
766 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
767 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000768 }
769
770 template<int RegWidth, int Shift>
771 bool isMOVZMovAlias() const {
772 if (!isImm()) return false;
773
774 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
775 if (!CE) return false;
776 uint64_t Value = CE->getValue();
777
Tim Northoverdaa1c012016-06-16 01:42:25 +0000778 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000779 }
780
781 template<int RegWidth, int Shift>
782 bool isMOVNMovAlias() const {
783 if (!isImm()) return false;
784
785 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
786 if (!CE) return false;
787 uint64_t Value = CE->getValue();
788
Tim Northoverdaa1c012016-06-16 01:42:25 +0000789 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000790 }
791
792 bool isFPImm() const { return Kind == k_FPImm; }
793 bool isBarrier() const { return Kind == k_Barrier; }
794 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000795
Tim Northover3b0846e2014-05-24 12:50:23 +0000796 bool isMRSSystemRegister() const {
797 if (!isSysReg()) return false;
798
Tim Northover7cd58932015-01-22 17:23:04 +0000799 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000800 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000801
Tim Northover3b0846e2014-05-24 12:50:23 +0000802 bool isMSRSystemRegister() const {
803 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000804 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000805 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000806
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000807 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000808 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000809 return (SysReg.PStateField == AArch64PState::PAN ||
810 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000811 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000812
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000813 bool isSystemPStateFieldWithImm0_15() const {
814 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000815 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000816 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000817
Florian Hahnc4422242017-11-07 13:07:50 +0000818 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000819 return Kind == k_Register;
820 }
821
822 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000823 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
824 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000825
Florian Hahnc4422242017-11-07 13:07:50 +0000826 bool isNeonVectorReg() const {
827 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
828 }
829
830 bool isNeonVectorRegLo() const {
831 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000832 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
833 Reg.RegNum);
834 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000835
Sander de Smalencd6be962017-12-20 11:02:42 +0000836 template <unsigned Class> bool isSVEVectorReg() const {
837 RegKind RK;
838 switch (Class) {
839 case AArch64::ZPRRegClassID:
840 RK = RegKind::SVEDataVector;
841 break;
842 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000843 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000844 RK = RegKind::SVEPredicateVector;
845 break;
846 default:
847 llvm_unreachable("Unsupport register class");
848 }
849
850 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000851 AArch64MCRegisterClasses[Class].contains(getReg());
852 }
853
Sander de Smalencd6be962017-12-20 11:02:42 +0000854 template <int ElementWidth, unsigned Class>
855 bool isSVEVectorRegOfWidth() const {
856 return isSVEVectorReg<Class>() &&
Sander de Smalen73937b72018-04-11 07:36:10 +0000857 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth);
Florian Hahn91f11e52017-11-07 16:45:48 +0000858 }
859
Sander de Smaleneb896b12018-04-25 09:26:47 +0000860 template <int ElementWidth, unsigned Class,
861 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth>
862 bool isSVEVectorRegWithShiftExtend() const {
863 return Kind == k_Register && isSVEVectorRegOfWidth<ElementWidth, Class>() &&
864 ShiftExtendTy == getShiftExtendType() &&
865 getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
866 }
867
Tim Northover3b0846e2014-05-24 12:50:23 +0000868 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000869 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000870 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
871 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000872
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000873 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000874 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000875 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
876 Reg.RegNum);
877 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000878
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000879 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000880 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000881 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
882 Reg.RegNum);
883 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000884
Sam Parker5f934642017-08-31 09:27:04 +0000885 template<int64_t Angle, int64_t Remainder>
886 bool isComplexRotation() const {
887 if (!isImm()) return false;
888
889 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
890 if (!CE) return false;
891 uint64_t Value = CE->getValue();
892
893 return (Value % Angle == Remainder && Value <= 270);
894 }
895
Sander de Smalen149916d2018-04-20 07:24:20 +0000896 template <unsigned RegClassID> bool isGPR64() const {
897 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
898 AArch64MCRegisterClasses[RegClassID].contains(getReg());
899 }
900
901 template <unsigned RegClassID, int ExtWidth>
902 bool isGPR64WithShiftExtend() const {
903 if (!isGPR64<RegClassID>())
904 return false;
905
906 return getShiftExtendType() == AArch64_AM::LSL &&
907 getShiftExtendAmount() == Log2_32(ExtWidth / 8);
908 }
909
Tim Northover3b0846e2014-05-24 12:50:23 +0000910 /// Is this a vector list with the type implicit (presumably attached to the
911 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +0000912 template <RegKind VectorKind, unsigned NumRegs>
913 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000914 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +0000915 VectorList.NumElements == 0 &&
916 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000917 }
918
Sander de Smalen650234b2018-04-12 11:40:52 +0000919 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
920 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +0000921 bool isTypedVectorList() const {
922 if (Kind != k_VectorList)
923 return false;
924 if (VectorList.Count != NumRegs)
925 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +0000926 if (VectorList.RegisterKind != VectorKind)
927 return false;
928 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +0000929 return false;
930 return VectorList.NumElements == NumElements;
931 }
932
933 bool isVectorIndex1() const {
934 return Kind == k_VectorIndex && VectorIndex.Val == 1;
935 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000936
Tim Northover3b0846e2014-05-24 12:50:23 +0000937 bool isVectorIndexB() const {
938 return Kind == k_VectorIndex && VectorIndex.Val < 16;
939 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000940
Tim Northover3b0846e2014-05-24 12:50:23 +0000941 bool isVectorIndexH() const {
942 return Kind == k_VectorIndex && VectorIndex.Val < 8;
943 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000944
Tim Northover3b0846e2014-05-24 12:50:23 +0000945 bool isVectorIndexS() const {
946 return Kind == k_VectorIndex && VectorIndex.Val < 4;
947 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000948
Tim Northover3b0846e2014-05-24 12:50:23 +0000949 bool isVectorIndexD() const {
950 return Kind == k_VectorIndex && VectorIndex.Val < 2;
951 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000952
Tim Northover3b0846e2014-05-24 12:50:23 +0000953 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000954
Tim Northover3b0846e2014-05-24 12:50:23 +0000955 bool isTokenEqual(StringRef Str) const {
956 return Kind == k_Token && getToken() == Str;
957 }
958 bool isSysCR() const { return Kind == k_SysCR; }
959 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000960 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000961 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
962 bool isShifter() const {
963 if (!isShiftExtend())
964 return false;
965
966 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
967 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
968 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
969 ST == AArch64_AM::MSL);
970 }
971 bool isExtend() const {
972 if (!isShiftExtend())
973 return false;
974
975 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
976 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
977 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
978 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
979 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
980 ET == AArch64_AM::LSL) &&
981 getShiftExtendAmount() <= 4;
982 }
983
984 bool isExtend64() const {
985 if (!isExtend())
986 return false;
987 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
988 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
989 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
990 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000991
Tim Northover3b0846e2014-05-24 12:50:23 +0000992 bool isExtendLSL64() const {
993 if (!isExtend())
994 return false;
995 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
996 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
997 ET == AArch64_AM::LSL) &&
998 getShiftExtendAmount() <= 4;
999 }
1000
1001 template<int Width> bool isMemXExtend() const {
1002 if (!isExtend())
1003 return false;
1004 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1005 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1006 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1007 getShiftExtendAmount() == 0);
1008 }
1009
1010 template<int Width> bool isMemWExtend() const {
1011 if (!isExtend())
1012 return false;
1013 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1014 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1015 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1016 getShiftExtendAmount() == 0);
1017 }
1018
1019 template <unsigned width>
1020 bool isArithmeticShifter() const {
1021 if (!isShifter())
1022 return false;
1023
1024 // An arithmetic shifter is LSL, LSR, or ASR.
1025 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1026 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1027 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1028 }
1029
1030 template <unsigned width>
1031 bool isLogicalShifter() const {
1032 if (!isShifter())
1033 return false;
1034
1035 // A logical shifter is LSL, LSR, ASR or ROR.
1036 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1037 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1038 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1039 getShiftExtendAmount() < width;
1040 }
1041
1042 bool isMovImm32Shifter() const {
1043 if (!isShifter())
1044 return false;
1045
1046 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1047 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1048 if (ST != AArch64_AM::LSL)
1049 return false;
1050 uint64_t Val = getShiftExtendAmount();
1051 return (Val == 0 || Val == 16);
1052 }
1053
1054 bool isMovImm64Shifter() const {
1055 if (!isShifter())
1056 return false;
1057
1058 // A MOVi shifter is LSL of 0 or 16.
1059 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1060 if (ST != AArch64_AM::LSL)
1061 return false;
1062 uint64_t Val = getShiftExtendAmount();
1063 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1064 }
1065
1066 bool isLogicalVecShifter() const {
1067 if (!isShifter())
1068 return false;
1069
1070 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1071 unsigned Shift = getShiftExtendAmount();
1072 return getShiftExtendType() == AArch64_AM::LSL &&
1073 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1074 }
1075
1076 bool isLogicalVecHalfWordShifter() const {
1077 if (!isLogicalVecShifter())
1078 return false;
1079
1080 // A logical vector shifter is a left shift by 0 or 8.
1081 unsigned Shift = getShiftExtendAmount();
1082 return getShiftExtendType() == AArch64_AM::LSL &&
1083 (Shift == 0 || Shift == 8);
1084 }
1085
1086 bool isMoveVecShifter() const {
1087 if (!isShiftExtend())
1088 return false;
1089
1090 // A logical vector shifter is a left shift by 8 or 16.
1091 unsigned Shift = getShiftExtendAmount();
1092 return getShiftExtendType() == AArch64_AM::MSL &&
1093 (Shift == 8 || Shift == 16);
1094 }
1095
1096 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1097 // to LDUR/STUR when the offset is not legal for the former but is for
1098 // the latter. As such, in addition to checking for being a legal unscaled
1099 // address, also check that it is not a legal scaled address. This avoids
1100 // ambiguity in the matcher.
1101 template<int Width>
1102 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001103 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001104 }
1105
1106 bool isAdrpLabel() const {
1107 // Validation was handled during parsing, so we just sanity check that
1108 // something didn't go haywire.
1109 if (!isImm())
1110 return false;
1111
1112 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1113 int64_t Val = CE->getValue();
1114 int64_t Min = - (4096 * (1LL << (21 - 1)));
1115 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1116 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1117 }
1118
1119 return true;
1120 }
1121
1122 bool isAdrLabel() const {
1123 // Validation was handled during parsing, so we just sanity check that
1124 // something didn't go haywire.
1125 if (!isImm())
1126 return false;
1127
1128 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1129 int64_t Val = CE->getValue();
1130 int64_t Min = - (1LL << (21 - 1));
1131 int64_t Max = ((1LL << (21 - 1)) - 1);
1132 return Val >= Min && Val <= Max;
1133 }
1134
1135 return true;
1136 }
1137
1138 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1139 // Add as immediates when possible. Null MCExpr = 0.
1140 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001141 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001142 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001143 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001144 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001145 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001146 }
1147
1148 void addRegOperands(MCInst &Inst, unsigned N) const {
1149 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001150 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001151 }
1152
1153 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1154 assert(N == 1 && "Invalid number of operands!");
1155 assert(
1156 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1157
1158 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1159 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1160 RI->getEncodingValue(getReg()));
1161
Jim Grosbache9119e42015-05-13 18:37:00 +00001162 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001163 }
1164
1165 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1166 assert(N == 1 && "Invalid number of operands!");
1167 assert(
1168 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001169 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001170 }
1171
1172 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1173 assert(N == 1 && "Invalid number of operands!");
1174 assert(
1175 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001176 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001177 }
1178
1179 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1180 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001181 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001182 }
1183
Sander de Smalen525e3222018-04-12 13:19:32 +00001184 enum VecListIndexType {
1185 VecListIdx_DReg = 0,
1186 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001187 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001188 };
1189
1190 template <VecListIndexType RegTy, unsigned NumRegs>
1191 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001192 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001193 static const unsigned FirstRegs[][5] = {
1194 /* DReg */ { AArch64::Q0,
1195 AArch64::D0, AArch64::D0_D1,
1196 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1197 /* QReg */ { AArch64::Q0,
1198 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001199 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1200 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001201 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001202 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001203 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001204
Sander de Smalen7a210db2018-04-16 10:46:18 +00001205 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1206 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001207
Sander de Smalen525e3222018-04-12 13:19:32 +00001208 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1209 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1210 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001211 }
1212
1213 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1214 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001215 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001216 }
1217
1218 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1219 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001220 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001221 }
1222
1223 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1224 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001225 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001226 }
1227
1228 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1229 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001230 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001231 }
1232
1233 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1234 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001235 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001236 }
1237
1238 void addImmOperands(MCInst &Inst, unsigned N) const {
1239 assert(N == 1 && "Invalid number of operands!");
1240 // If this is a pageoff symrefexpr with an addend, adjust the addend
1241 // to be only the page-offset portion. Otherwise, just add the expr
1242 // as-is.
1243 addExpr(Inst, getImm());
1244 }
1245
1246 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1247 assert(N == 2 && "Invalid number of operands!");
1248 if (isShiftedImm()) {
1249 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001250 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001251 } else {
1252 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001253 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001254 }
1255 }
1256
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001257 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1258 assert(N == 2 && "Invalid number of operands!");
1259
1260 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1261 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1262 int64_t Val = -CE->getValue();
1263 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1264
1265 Inst.addOperand(MCOperand::createImm(Val));
1266 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1267 }
1268
Tim Northover3b0846e2014-05-24 12:50:23 +00001269 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1270 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001271 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001272 }
1273
1274 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1275 assert(N == 1 && "Invalid number of operands!");
1276 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1277 if (!MCE)
1278 addExpr(Inst, getImm());
1279 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001280 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001281 }
1282
1283 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1284 addImmOperands(Inst, N);
1285 }
1286
1287 template<int Scale>
1288 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1289 assert(N == 1 && "Invalid number of operands!");
1290 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1291
1292 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001293 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001294 return;
1295 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001296 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001297 }
1298
1299 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1300 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001301 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001302 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001303 }
1304
Sam Parker6d42de72017-08-11 13:14:00 +00001305 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1306 assert(N == 1 && "Invalid number of operands!");
1307 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1308 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1309 }
1310
Tim Northover3b0846e2014-05-24 12:50:23 +00001311 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1312 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001313 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001314 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001315 }
1316
1317 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1318 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001319 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001320 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001321 }
1322
1323 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1324 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001325 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001326 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001327 }
1328
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001329 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1330 assert(N == 1 && "Invalid number of operands!");
1331 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1332 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1333 }
1334
Tim Northover3b0846e2014-05-24 12:50:23 +00001335 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1336 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001337 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001338 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001339 }
1340
1341 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1342 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001343 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001344 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001345 }
1346
1347 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1348 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001349 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001350 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001351 }
1352
1353 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1354 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001355 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001356 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001357 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001358 }
1359
1360 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1361 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001362 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001363 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001364 }
1365
1366 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1367 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001368 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001369 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001370 }
1371
1372 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1373 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001374 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001375 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001376 }
1377
1378 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1379 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001380 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001381 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001382 }
1383
1384 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1385 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001386 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001387 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001388 }
1389
1390 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1391 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001392 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001393 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001394 }
1395
1396 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1397 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001398 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001399 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001400 }
1401
1402 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1403 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001404 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001405 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001406 }
1407
1408 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1409 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001410 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001411 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001412 }
1413
1414 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1415 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001416 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001417 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001418 }
1419
Sander de Smalen5c625982018-04-13 12:56:14 +00001420 template <int Scale>
1421 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1422 assert(N == 1 && "Invalid number of operands!");
1423 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1424 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1425 }
1426
Sander de Smalena1c259c2018-01-29 13:05:38 +00001427 template <typename T>
1428 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001429 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001430 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001431 typename std::make_unsigned<T>::type Val = MCE->getValue();
1432 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001433 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 }
1435
Sander de Smalena1c259c2018-01-29 13:05:38 +00001436 template <typename T>
1437 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001438 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001439 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001440 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1441 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001442 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001443 }
1444
Tim Northover3b0846e2014-05-24 12:50:23 +00001445 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1446 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001447 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001448 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001449 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001450 }
1451
1452 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1453 // Branch operands don't encode the low bits, so shift them off
1454 // here. If it's a label, however, just put it on directly as there's
1455 // not enough information now to do anything.
1456 assert(N == 1 && "Invalid number of operands!");
1457 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1458 if (!MCE) {
1459 addExpr(Inst, getImm());
1460 return;
1461 }
1462 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001463 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001464 }
1465
1466 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1467 // Branch operands don't encode the low bits, so shift them off
1468 // here. If it's a label, however, just put it on directly as there's
1469 // not enough information now to do anything.
1470 assert(N == 1 && "Invalid number of operands!");
1471 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1472 if (!MCE) {
1473 addExpr(Inst, getImm());
1474 return;
1475 }
1476 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001477 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001478 }
1479
1480 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1481 // Branch operands don't encode the low bits, so shift them off
1482 // here. If it's a label, however, just put it on directly as there's
1483 // not enough information now to do anything.
1484 assert(N == 1 && "Invalid number of operands!");
1485 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1486 if (!MCE) {
1487 addExpr(Inst, getImm());
1488 return;
1489 }
1490 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001491 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001492 }
1493
1494 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1495 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001496 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001497 }
1498
1499 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1500 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001501 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001502 }
1503
1504 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1505 assert(N == 1 && "Invalid number of operands!");
1506
Jim Grosbache9119e42015-05-13 18:37:00 +00001507 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001508 }
1509
1510 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1511 assert(N == 1 && "Invalid number of operands!");
1512
Jim Grosbache9119e42015-05-13 18:37:00 +00001513 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001514 }
1515
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001516 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1517 assert(N == 1 && "Invalid number of operands!");
1518
1519 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1520 }
1521
1522 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001523 assert(N == 1 && "Invalid number of operands!");
1524
Jim Grosbache9119e42015-05-13 18:37:00 +00001525 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001526 }
1527
1528 void addSysCROperands(MCInst &Inst, unsigned N) const {
1529 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001530 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001531 }
1532
1533 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1534 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001535 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001536 }
1537
Oliver Stannarda34e4702015-12-01 10:48:51 +00001538 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1539 assert(N == 1 && "Invalid number of operands!");
1540 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1541 }
1542
Tim Northover3b0846e2014-05-24 12:50:23 +00001543 void addShifterOperands(MCInst &Inst, unsigned N) const {
1544 assert(N == 1 && "Invalid number of operands!");
1545 unsigned Imm =
1546 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001547 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001548 }
1549
1550 void addExtendOperands(MCInst &Inst, unsigned N) const {
1551 assert(N == 1 && "Invalid number of operands!");
1552 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1553 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1554 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001555 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001556 }
1557
1558 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1559 assert(N == 1 && "Invalid number of operands!");
1560 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1561 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1562 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001563 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001564 }
1565
1566 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1567 assert(N == 2 && "Invalid number of operands!");
1568 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1569 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001570 Inst.addOperand(MCOperand::createImm(IsSigned));
1571 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001572 }
1573
1574 // For 8-bit load/store instructions with a register offset, both the
1575 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1576 // they're disambiguated by whether the shift was explicit or implicit rather
1577 // than its size.
1578 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1579 assert(N == 2 && "Invalid number of operands!");
1580 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1581 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001582 Inst.addOperand(MCOperand::createImm(IsSigned));
1583 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001584 }
1585
1586 template<int Shift>
1587 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1588 assert(N == 1 && "Invalid number of operands!");
1589
1590 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1591 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001592 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001593 }
1594
1595 template<int Shift>
1596 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1597 assert(N == 1 && "Invalid number of operands!");
1598
1599 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1600 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001601 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001602 }
1603
Sam Parker5f934642017-08-31 09:27:04 +00001604 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1605 assert(N == 1 && "Invalid number of operands!");
1606 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1607 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1608 }
1609
1610 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1611 assert(N == 1 && "Invalid number of operands!");
1612 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1613 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1614 }
1615
Tim Northover3b0846e2014-05-24 12:50:23 +00001616 void print(raw_ostream &OS) const override;
1617
David Blaikie960ea3f2014-06-08 16:18:35 +00001618 static std::unique_ptr<AArch64Operand>
1619 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1620 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001621 Op->Tok.Data = Str.data();
1622 Op->Tok.Length = Str.size();
1623 Op->Tok.IsSuffix = IsSuffix;
1624 Op->StartLoc = S;
1625 Op->EndLoc = S;
1626 return Op;
1627 }
1628
David Blaikie960ea3f2014-06-08 16:18:35 +00001629 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001630 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
1631 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1632 unsigned ShiftAmount = 0,
1633 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001634 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001635 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001636 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001637 Op->Reg.ElementWidth = 0;
1638 Op->Reg.ShiftExtend.Type = ExtTy;
1639 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1640 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001641 Op->StartLoc = S;
1642 Op->EndLoc = E;
1643 return Op;
1644 }
1645
David Blaikie960ea3f2014-06-08 16:18:35 +00001646 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001647 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001648 SMLoc S, SMLoc E, MCContext &Ctx,
1649 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1650 unsigned ShiftAmount = 0,
1651 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001652 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1653 Kind == RegKind::SVEPredicateVector) &&
1654 "Invalid vector kind");
Sander de Smalen149916d2018-04-20 07:24:20 +00001655 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, ExtTy, ShiftAmount,
1656 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001657 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001658 return Op;
1659 }
1660
1661 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001662 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001663 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1664 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001665 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001666 Op->VectorList.RegNum = RegNum;
1667 Op->VectorList.Count = Count;
1668 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001669 Op->VectorList.ElementWidth = ElementWidth;
1670 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001671 Op->StartLoc = S;
1672 Op->EndLoc = E;
1673 return Op;
1674 }
1675
David Blaikie960ea3f2014-06-08 16:18:35 +00001676 static std::unique_ptr<AArch64Operand>
1677 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1678 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001679 Op->VectorIndex.Val = Idx;
1680 Op->StartLoc = S;
1681 Op->EndLoc = E;
1682 return Op;
1683 }
1684
David Blaikie960ea3f2014-06-08 16:18:35 +00001685 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1686 SMLoc E, MCContext &Ctx) {
1687 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001688 Op->Imm.Val = Val;
1689 Op->StartLoc = S;
1690 Op->EndLoc = E;
1691 return Op;
1692 }
1693
David Blaikie960ea3f2014-06-08 16:18:35 +00001694 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1695 unsigned ShiftAmount,
1696 SMLoc S, SMLoc E,
1697 MCContext &Ctx) {
1698 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001699 Op->ShiftedImm .Val = Val;
1700 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1701 Op->StartLoc = S;
1702 Op->EndLoc = E;
1703 return Op;
1704 }
1705
David Blaikie960ea3f2014-06-08 16:18:35 +00001706 static std::unique_ptr<AArch64Operand>
1707 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1708 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001709 Op->CondCode.Code = Code;
1710 Op->StartLoc = S;
1711 Op->EndLoc = E;
1712 return Op;
1713 }
1714
David Blaikie960ea3f2014-06-08 16:18:35 +00001715 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1716 MCContext &Ctx) {
1717 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001718 Op->FPImm.Val = Val;
1719 Op->StartLoc = S;
1720 Op->EndLoc = S;
1721 return Op;
1722 }
1723
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001724 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1725 StringRef Str,
1726 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001727 MCContext &Ctx) {
1728 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001729 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001730 Op->Barrier.Data = Str.data();
1731 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001732 Op->StartLoc = S;
1733 Op->EndLoc = S;
1734 return Op;
1735 }
1736
Tim Northover7cd58932015-01-22 17:23:04 +00001737 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1738 uint32_t MRSReg,
1739 uint32_t MSRReg,
1740 uint32_t PStateField,
1741 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001742 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001743 Op->SysReg.Data = Str.data();
1744 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001745 Op->SysReg.MRSReg = MRSReg;
1746 Op->SysReg.MSRReg = MSRReg;
1747 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001748 Op->StartLoc = S;
1749 Op->EndLoc = S;
1750 return Op;
1751 }
1752
David Blaikie960ea3f2014-06-08 16:18:35 +00001753 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1754 SMLoc E, MCContext &Ctx) {
1755 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001756 Op->SysCRImm.Val = Val;
1757 Op->StartLoc = S;
1758 Op->EndLoc = E;
1759 return Op;
1760 }
1761
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001762 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1763 StringRef Str,
1764 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001765 MCContext &Ctx) {
1766 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001767 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001768 Op->Barrier.Data = Str.data();
1769 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001770 Op->StartLoc = S;
1771 Op->EndLoc = S;
1772 return Op;
1773 }
1774
Oliver Stannarda34e4702015-12-01 10:48:51 +00001775 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1776 StringRef Str,
1777 SMLoc S,
1778 MCContext &Ctx) {
1779 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1780 Op->PSBHint.Val = Val;
1781 Op->PSBHint.Data = Str.data();
1782 Op->PSBHint.Length = Str.size();
1783 Op->StartLoc = S;
1784 Op->EndLoc = S;
1785 return Op;
1786 }
1787
David Blaikie960ea3f2014-06-08 16:18:35 +00001788 static std::unique_ptr<AArch64Operand>
1789 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1790 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1791 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001792 Op->ShiftExtend.Type = ShOp;
1793 Op->ShiftExtend.Amount = Val;
1794 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1795 Op->StartLoc = S;
1796 Op->EndLoc = E;
1797 return Op;
1798 }
1799};
1800
1801} // end anonymous namespace.
1802
1803void AArch64Operand::print(raw_ostream &OS) const {
1804 switch (Kind) {
1805 case k_FPImm:
1806 OS << "<fpimm " << getFPImm() << "("
1807 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1808 break;
1809 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001810 StringRef Name = getBarrierName();
1811 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001812 OS << "<barrier " << Name << ">";
1813 else
1814 OS << "<barrier invalid #" << getBarrier() << ">";
1815 break;
1816 }
1817 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001818 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001819 break;
1820 case k_ShiftedImm: {
1821 unsigned Shift = getShiftedImmShift();
1822 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001823 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001824 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1825 break;
1826 }
1827 case k_CondCode:
1828 OS << "<condcode " << getCondCode() << ">";
1829 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001830 case k_VectorList: {
1831 OS << "<vectorlist ";
1832 unsigned Reg = getVectorListStart();
1833 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1834 OS << Reg + i << " ";
1835 OS << ">";
1836 break;
1837 }
1838 case k_VectorIndex:
1839 OS << "<vectorindex " << getVectorIndex() << ">";
1840 break;
1841 case k_SysReg:
1842 OS << "<sysreg: " << getSysReg() << '>';
1843 break;
1844 case k_Token:
1845 OS << "'" << getToken() << "'";
1846 break;
1847 case k_SysCR:
1848 OS << "c" << getSysCR();
1849 break;
1850 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001851 StringRef Name = getPrefetchName();
1852 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001853 OS << "<prfop " << Name << ">";
1854 else
1855 OS << "<prfop invalid #" << getPrefetch() << ">";
1856 break;
1857 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001858 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001859 OS << getPSBHintName();
1860 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00001861 case k_Register:
1862 OS << "<register " << getReg() << ">";
1863 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
1864 break;
1865 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001866 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001867 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1868 << getShiftExtendAmount();
1869 if (!hasShiftExtendAmount())
1870 OS << "<imp>";
1871 OS << '>';
1872 break;
1873 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001874}
1875
1876/// @name Auto-generated Match Functions
1877/// {
1878
1879static unsigned MatchRegisterName(StringRef Name);
1880
1881/// }
1882
Florian Hahnc4422242017-11-07 13:07:50 +00001883static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001884 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001885 .Case("v0", AArch64::Q0)
1886 .Case("v1", AArch64::Q1)
1887 .Case("v2", AArch64::Q2)
1888 .Case("v3", AArch64::Q3)
1889 .Case("v4", AArch64::Q4)
1890 .Case("v5", AArch64::Q5)
1891 .Case("v6", AArch64::Q6)
1892 .Case("v7", AArch64::Q7)
1893 .Case("v8", AArch64::Q8)
1894 .Case("v9", AArch64::Q9)
1895 .Case("v10", AArch64::Q10)
1896 .Case("v11", AArch64::Q11)
1897 .Case("v12", AArch64::Q12)
1898 .Case("v13", AArch64::Q13)
1899 .Case("v14", AArch64::Q14)
1900 .Case("v15", AArch64::Q15)
1901 .Case("v16", AArch64::Q16)
1902 .Case("v17", AArch64::Q17)
1903 .Case("v18", AArch64::Q18)
1904 .Case("v19", AArch64::Q19)
1905 .Case("v20", AArch64::Q20)
1906 .Case("v21", AArch64::Q21)
1907 .Case("v22", AArch64::Q22)
1908 .Case("v23", AArch64::Q23)
1909 .Case("v24", AArch64::Q24)
1910 .Case("v25", AArch64::Q25)
1911 .Case("v26", AArch64::Q26)
1912 .Case("v27", AArch64::Q27)
1913 .Case("v28", AArch64::Q28)
1914 .Case("v29", AArch64::Q29)
1915 .Case("v30", AArch64::Q30)
1916 .Case("v31", AArch64::Q31)
1917 .Default(0);
1918}
1919
Sander de Smalen73937b72018-04-11 07:36:10 +00001920/// Returns an optional pair of (#elements, element-width) if Suffix
1921/// is a valid vector kind. Where the number of elements in a vector
1922/// or the vector width is implicit or explicitly unknown (but still a
1923/// valid suffix kind), 0 is used.
1924static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1925 RegKind VectorKind) {
1926 std::pair<int, int> Res = {-1, -1};
1927
1928 switch (VectorKind) {
1929 case RegKind::NeonVector:
1930 Res =
1931 StringSwitch<std::pair<int, int>>(Suffix.lower())
1932 .Case("", {0, 0})
1933 .Case(".1d", {1, 64})
1934 .Case(".1q", {1, 128})
1935 // '.2h' needed for fp16 scalar pairwise reductions
1936 .Case(".2h", {2, 16})
1937 .Case(".2s", {2, 32})
1938 .Case(".2d", {2, 64})
1939 // '.4b' is another special case for the ARMv8.2a dot product
1940 // operand
1941 .Case(".4b", {4, 8})
1942 .Case(".4h", {4, 16})
1943 .Case(".4s", {4, 32})
1944 .Case(".8b", {8, 8})
1945 .Case(".8h", {8, 16})
1946 .Case(".16b", {16, 8})
1947 // Accept the width neutral ones, too, for verbose syntax. If those
1948 // aren't used in the right places, the token operand won't match so
1949 // all will work out.
1950 .Case(".b", {0, 8})
1951 .Case(".h", {0, 16})
1952 .Case(".s", {0, 32})
1953 .Case(".d", {0, 64})
1954 .Default({-1, -1});
1955 break;
1956 case RegKind::SVEPredicateVector:
1957 case RegKind::SVEDataVector:
1958 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1959 .Case("", {0, 0})
1960 .Case(".b", {0, 8})
1961 .Case(".h", {0, 16})
1962 .Case(".s", {0, 32})
1963 .Case(".d", {0, 64})
1964 .Case(".q", {0, 128})
1965 .Default({-1, -1});
1966 break;
1967 default:
1968 llvm_unreachable("Unsupported RegKind");
1969 }
1970
1971 if (Res == std::make_pair(-1, -1))
1972 return Optional<std::pair<int, int>>();
1973
1974 return Optional<std::pair<int, int>>(Res);
1975}
1976
1977static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1978 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001979}
1980
Florian Hahn91f11e52017-11-07 16:45:48 +00001981static unsigned matchSVEDataVectorRegName(StringRef Name) {
1982 return StringSwitch<unsigned>(Name.lower())
1983 .Case("z0", AArch64::Z0)
1984 .Case("z1", AArch64::Z1)
1985 .Case("z2", AArch64::Z2)
1986 .Case("z3", AArch64::Z3)
1987 .Case("z4", AArch64::Z4)
1988 .Case("z5", AArch64::Z5)
1989 .Case("z6", AArch64::Z6)
1990 .Case("z7", AArch64::Z7)
1991 .Case("z8", AArch64::Z8)
1992 .Case("z9", AArch64::Z9)
1993 .Case("z10", AArch64::Z10)
1994 .Case("z11", AArch64::Z11)
1995 .Case("z12", AArch64::Z12)
1996 .Case("z13", AArch64::Z13)
1997 .Case("z14", AArch64::Z14)
1998 .Case("z15", AArch64::Z15)
1999 .Case("z16", AArch64::Z16)
2000 .Case("z17", AArch64::Z17)
2001 .Case("z18", AArch64::Z18)
2002 .Case("z19", AArch64::Z19)
2003 .Case("z20", AArch64::Z20)
2004 .Case("z21", AArch64::Z21)
2005 .Case("z22", AArch64::Z22)
2006 .Case("z23", AArch64::Z23)
2007 .Case("z24", AArch64::Z24)
2008 .Case("z25", AArch64::Z25)
2009 .Case("z26", AArch64::Z26)
2010 .Case("z27", AArch64::Z27)
2011 .Case("z28", AArch64::Z28)
2012 .Case("z29", AArch64::Z29)
2013 .Case("z30", AArch64::Z30)
2014 .Case("z31", AArch64::Z31)
2015 .Default(0);
2016}
2017
Sander de Smalencd6be962017-12-20 11:02:42 +00002018static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2019 return StringSwitch<unsigned>(Name.lower())
2020 .Case("p0", AArch64::P0)
2021 .Case("p1", AArch64::P1)
2022 .Case("p2", AArch64::P2)
2023 .Case("p3", AArch64::P3)
2024 .Case("p4", AArch64::P4)
2025 .Case("p5", AArch64::P5)
2026 .Case("p6", AArch64::P6)
2027 .Case("p7", AArch64::P7)
2028 .Case("p8", AArch64::P8)
2029 .Case("p9", AArch64::P9)
2030 .Case("p10", AArch64::P10)
2031 .Case("p11", AArch64::P11)
2032 .Case("p12", AArch64::P12)
2033 .Case("p13", AArch64::P13)
2034 .Case("p14", AArch64::P14)
2035 .Case("p15", AArch64::P15)
2036 .Default(0);
2037}
2038
Tim Northover3b0846e2014-05-24 12:50:23 +00002039bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2040 SMLoc &EndLoc) {
2041 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002042 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002043 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002044 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002045}
2046
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002047// Matches a register name or register alias previously defined by '.req'
2048unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002049 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002050 unsigned RegNum = 0;
2051 if ((RegNum = matchSVEDataVectorRegName(Name)))
2052 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2053
Sander de Smalencd6be962017-12-20 11:02:42 +00002054 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2055 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2056
Sander de Smalenc067c302017-12-20 09:45:45 +00002057 if ((RegNum = MatchNeonVectorRegName(Name)))
2058 return Kind == RegKind::NeonVector ? RegNum : 0;
2059
2060 // The parsed register must be of RegKind Scalar
2061 if ((RegNum = MatchRegisterName(Name)))
2062 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002063
Florian Hahnc4422242017-11-07 13:07:50 +00002064 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002065 // Handle a few common aliases of registers.
2066 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2067 .Case("fp", AArch64::FP)
2068 .Case("lr", AArch64::LR)
2069 .Case("x31", AArch64::XZR)
2070 .Case("w31", AArch64::WZR)
2071 .Default(0))
2072 return Kind == RegKind::Scalar ? RegNum : 0;
2073
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002074 // Check for aliases registered via .req. Canonicalize to lower case.
2075 // That's more consistent since register names are case insensitive, and
2076 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2077 auto Entry = RegisterReqs.find(Name.lower());
2078 if (Entry == RegisterReqs.end())
2079 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002080
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002081 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002082 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002083 RegNum = Entry->getValue().second;
2084 }
2085 return RegNum;
2086}
2087
Sander de Smalen50d87022018-04-19 07:35:08 +00002088/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002089/// Identifier when called, and if it is a register name the token is eaten and
2090/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002091OperandMatchResultTy
2092AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002093 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002094 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002095 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002096 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002097
2098 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002099 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2100 if (Reg == 0)
2101 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002102
Sander de Smalen50d87022018-04-19 07:35:08 +00002103 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002104 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002105 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002106}
2107
Tim Northover3b0846e2014-05-24 12:50:23 +00002108/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002109OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002110AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002111 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002112 SMLoc S = getLoc();
2113
2114 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2115 Error(S, "Expected cN operand where 0 <= N <= 15");
2116 return MatchOperand_ParseFail;
2117 }
2118
2119 StringRef Tok = Parser.getTok().getIdentifier();
2120 if (Tok[0] != 'c' && Tok[0] != 'C') {
2121 Error(S, "Expected cN operand where 0 <= N <= 15");
2122 return MatchOperand_ParseFail;
2123 }
2124
2125 uint32_t CRNum;
2126 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2127 if (BadNum || CRNum > 15) {
2128 Error(S, "Expected cN operand where 0 <= N <= 15");
2129 return MatchOperand_ParseFail;
2130 }
2131
2132 Parser.Lex(); // Eat identifier token.
2133 Operands.push_back(
2134 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2135 return MatchOperand_Success;
2136}
2137
2138/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002139OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002140AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002141 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002142 SMLoc S = getLoc();
2143 const AsmToken &Tok = Parser.getTok();
2144 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002145 // Eat optional hash.
2146 if (parseOptionalToken(AsmToken::Hash) ||
2147 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002148 const MCExpr *ImmVal;
2149 if (getParser().parseExpression(ImmVal))
2150 return MatchOperand_ParseFail;
2151
2152 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2153 if (!MCE) {
2154 TokError("immediate value expected for prefetch operand");
2155 return MatchOperand_ParseFail;
2156 }
2157 unsigned prfop = MCE->getValue();
2158 if (prfop > 31) {
2159 TokError("prefetch operand out of range, [0,31] expected");
2160 return MatchOperand_ParseFail;
2161 }
2162
Tim Northovere6ae6762016-07-05 21:23:04 +00002163 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2164 Operands.push_back(AArch64Operand::CreatePrefetch(
2165 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002166 return MatchOperand_Success;
2167 }
2168
2169 if (Tok.isNot(AsmToken::Identifier)) {
2170 TokError("pre-fetch hint expected");
2171 return MatchOperand_ParseFail;
2172 }
2173
Tim Northovere6ae6762016-07-05 21:23:04 +00002174 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2175 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002176 TokError("pre-fetch hint expected");
2177 return MatchOperand_ParseFail;
2178 }
2179
2180 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002181 Operands.push_back(AArch64Operand::CreatePrefetch(
2182 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002183 return MatchOperand_Success;
2184}
2185
Oliver Stannarda34e4702015-12-01 10:48:51 +00002186/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002187OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002188AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2189 MCAsmParser &Parser = getParser();
2190 SMLoc S = getLoc();
2191 const AsmToken &Tok = Parser.getTok();
2192 if (Tok.isNot(AsmToken::Identifier)) {
2193 TokError("invalid operand for instruction");
2194 return MatchOperand_ParseFail;
2195 }
2196
Tim Northovere6ae6762016-07-05 21:23:04 +00002197 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2198 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002199 TokError("invalid operand for instruction");
2200 return MatchOperand_ParseFail;
2201 }
2202
2203 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002204 Operands.push_back(AArch64Operand::CreatePSBHint(
2205 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002206 return MatchOperand_Success;
2207}
2208
Tim Northover3b0846e2014-05-24 12:50:23 +00002209/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2210/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002211OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002212AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002213 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002214 SMLoc S = getLoc();
2215 const MCExpr *Expr;
2216
2217 if (Parser.getTok().is(AsmToken::Hash)) {
2218 Parser.Lex(); // Eat hash token.
2219 }
2220
2221 if (parseSymbolicImmVal(Expr))
2222 return MatchOperand_ParseFail;
2223
2224 AArch64MCExpr::VariantKind ELFRefKind;
2225 MCSymbolRefExpr::VariantKind DarwinRefKind;
2226 int64_t Addend;
2227 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2228 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2229 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2230 // No modifier was specified at all; this is the syntax for an ELF basic
2231 // ADRP relocation (unfortunately).
2232 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002233 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002234 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2235 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2236 Addend != 0) {
2237 Error(S, "gotpage label reference not allowed an addend");
2238 return MatchOperand_ParseFail;
2239 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2240 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2241 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2242 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2243 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2244 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2245 // The operand must be an @page or @gotpage qualified symbolref.
2246 Error(S, "page or gotpage label reference expected");
2247 return MatchOperand_ParseFail;
2248 }
2249 }
2250
2251 // We have either a label reference possibly with addend or an immediate. The
2252 // addend is a raw value here. The linker will adjust it to only reference the
2253 // page.
2254 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2255 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2256
2257 return MatchOperand_Success;
2258}
2259
2260/// tryParseAdrLabel - Parse and validate a source label for the ADR
2261/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002262OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002263AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2264 SMLoc S = getLoc();
2265 const MCExpr *Expr;
2266
Nirav Davee833c6c2016-11-08 18:31:04 +00002267 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002268 if (getParser().parseExpression(Expr))
2269 return MatchOperand_ParseFail;
2270
2271 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2272 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2273
2274 return MatchOperand_Success;
2275}
2276
2277/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002278OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002279AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002280 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002281 SMLoc S = getLoc();
2282
Nirav Davee833c6c2016-11-08 18:31:04 +00002283 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002284
2285 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002286 bool isNegative = parseOptionalToken(AsmToken::Minus);
2287
Tim Northover3b0846e2014-05-24 12:50:23 +00002288 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002289 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002290 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002291 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002292 Val = Tok.getIntVal();
2293 if (Val > 255 || Val < 0) {
2294 TokError("encoded floating point value out of range");
2295 return MatchOperand_ParseFail;
2296 }
2297 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002298 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002299 if (isNegative)
2300 RealVal.changeSign();
2301
Tim Northover3b0846e2014-05-24 12:50:23 +00002302 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002303 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002304
John Brawn5ca5daa2017-04-20 10:13:54 +00002305 // Check for out of range values. As an exception we let Zero through,
2306 // but as tokens instead of an FPImm so that it can be matched by the
2307 // appropriate alias if one exists.
2308 if (RealVal.isPosZero()) {
2309 Parser.Lex(); // Eat the token.
2310 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2311 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2312 return MatchOperand_Success;
2313 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002314 TokError("expected compatible register or floating-point constant");
2315 return MatchOperand_ParseFail;
2316 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002317 }
2318 Parser.Lex(); // Eat the token.
2319 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2320 return MatchOperand_Success;
2321 }
2322
2323 if (!Hash)
2324 return MatchOperand_NoMatch;
2325
2326 TokError("invalid floating point immediate");
2327 return MatchOperand_ParseFail;
2328}
2329
2330/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002331OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002332AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002333 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002334 SMLoc S = getLoc();
2335
2336 if (Parser.getTok().is(AsmToken::Hash))
2337 Parser.Lex(); // Eat '#'
2338 else if (Parser.getTok().isNot(AsmToken::Integer))
2339 // Operand should start from # or should be integer, emit error otherwise.
2340 return MatchOperand_NoMatch;
2341
2342 const MCExpr *Imm;
2343 if (parseSymbolicImmVal(Imm))
2344 return MatchOperand_ParseFail;
2345 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2346 uint64_t ShiftAmount = 0;
2347 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2348 if (MCE) {
2349 int64_t Val = MCE->getValue();
2350 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002351 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002352 ShiftAmount = 12;
2353 }
2354 }
2355 SMLoc E = Parser.getTok().getLoc();
2356 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2357 getContext()));
2358 return MatchOperand_Success;
2359 }
2360
2361 // Eat ','
2362 Parser.Lex();
2363
2364 // The optional operand must be "lsl #N" where N is non-negative.
2365 if (!Parser.getTok().is(AsmToken::Identifier) ||
2366 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2367 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2368 return MatchOperand_ParseFail;
2369 }
2370
2371 // Eat 'lsl'
2372 Parser.Lex();
2373
Nirav Davee833c6c2016-11-08 18:31:04 +00002374 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002375
2376 if (Parser.getTok().isNot(AsmToken::Integer)) {
2377 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2378 return MatchOperand_ParseFail;
2379 }
2380
2381 int64_t ShiftAmount = Parser.getTok().getIntVal();
2382
2383 if (ShiftAmount < 0) {
2384 Error(Parser.getTok().getLoc(), "positive shift amount required");
2385 return MatchOperand_ParseFail;
2386 }
2387 Parser.Lex(); // Eat the number
2388
2389 SMLoc E = Parser.getTok().getLoc();
2390 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2391 S, E, getContext()));
2392 return MatchOperand_Success;
2393}
2394
2395/// parseCondCodeString - Parse a Condition Code string.
2396AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2397 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2398 .Case("eq", AArch64CC::EQ)
2399 .Case("ne", AArch64CC::NE)
2400 .Case("cs", AArch64CC::HS)
2401 .Case("hs", AArch64CC::HS)
2402 .Case("cc", AArch64CC::LO)
2403 .Case("lo", AArch64CC::LO)
2404 .Case("mi", AArch64CC::MI)
2405 .Case("pl", AArch64CC::PL)
2406 .Case("vs", AArch64CC::VS)
2407 .Case("vc", AArch64CC::VC)
2408 .Case("hi", AArch64CC::HI)
2409 .Case("ls", AArch64CC::LS)
2410 .Case("ge", AArch64CC::GE)
2411 .Case("lt", AArch64CC::LT)
2412 .Case("gt", AArch64CC::GT)
2413 .Case("le", AArch64CC::LE)
2414 .Case("al", AArch64CC::AL)
2415 .Case("nv", AArch64CC::NV)
2416 .Default(AArch64CC::Invalid);
2417 return CC;
2418}
2419
2420/// parseCondCode - Parse a Condition Code operand.
2421bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2422 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002423 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002424 SMLoc S = getLoc();
2425 const AsmToken &Tok = Parser.getTok();
2426 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2427
2428 StringRef Cond = Tok.getString();
2429 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2430 if (CC == AArch64CC::Invalid)
2431 return TokError("invalid condition code");
2432 Parser.Lex(); // Eat identifier token.
2433
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002434 if (invertCondCode) {
2435 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2436 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002437 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002438 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002439
2440 Operands.push_back(
2441 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2442 return false;
2443}
2444
2445/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2446/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002447OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002448AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002449 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002450 const AsmToken &Tok = Parser.getTok();
2451 std::string LowerID = Tok.getString().lower();
2452 AArch64_AM::ShiftExtendType ShOp =
2453 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2454 .Case("lsl", AArch64_AM::LSL)
2455 .Case("lsr", AArch64_AM::LSR)
2456 .Case("asr", AArch64_AM::ASR)
2457 .Case("ror", AArch64_AM::ROR)
2458 .Case("msl", AArch64_AM::MSL)
2459 .Case("uxtb", AArch64_AM::UXTB)
2460 .Case("uxth", AArch64_AM::UXTH)
2461 .Case("uxtw", AArch64_AM::UXTW)
2462 .Case("uxtx", AArch64_AM::UXTX)
2463 .Case("sxtb", AArch64_AM::SXTB)
2464 .Case("sxth", AArch64_AM::SXTH)
2465 .Case("sxtw", AArch64_AM::SXTW)
2466 .Case("sxtx", AArch64_AM::SXTX)
2467 .Default(AArch64_AM::InvalidShiftExtend);
2468
2469 if (ShOp == AArch64_AM::InvalidShiftExtend)
2470 return MatchOperand_NoMatch;
2471
2472 SMLoc S = Tok.getLoc();
2473 Parser.Lex();
2474
Nirav Davee833c6c2016-11-08 18:31:04 +00002475 bool Hash = parseOptionalToken(AsmToken::Hash);
2476
Tim Northover3b0846e2014-05-24 12:50:23 +00002477 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2478 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2479 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2480 ShOp == AArch64_AM::MSL) {
2481 // We expect a number here.
2482 TokError("expected #imm after shift specifier");
2483 return MatchOperand_ParseFail;
2484 }
2485
Chad Rosier2ff37b82016-12-27 16:58:09 +00002486 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002487 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2488 Operands.push_back(
2489 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2490 return MatchOperand_Success;
2491 }
2492
Chad Rosier2ff37b82016-12-27 16:58:09 +00002493 // Make sure we do actually have a number, identifier or a parenthesized
2494 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002495 SMLoc E = Parser.getTok().getLoc();
2496 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002497 !Parser.getTok().is(AsmToken::LParen) &&
2498 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002499 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002500 return MatchOperand_ParseFail;
2501 }
2502
2503 const MCExpr *ImmVal;
2504 if (getParser().parseExpression(ImmVal))
2505 return MatchOperand_ParseFail;
2506
2507 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2508 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002509 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002510 return MatchOperand_ParseFail;
2511 }
2512
Jim Grosbach57fd2622014-09-23 22:16:02 +00002513 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002514 Operands.push_back(AArch64Operand::CreateShiftExtend(
2515 ShOp, MCE->getValue(), true, S, E, getContext()));
2516 return MatchOperand_Success;
2517}
2518
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002519static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2520 if (FBS[AArch64::HasV8_1aOps])
2521 Str += "ARMv8.1a";
2522 else if (FBS[AArch64::HasV8_2aOps])
2523 Str += "ARMv8.2a";
2524 else
2525 Str += "(unknown)";
2526}
2527
2528void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2529 SMLoc S) {
2530 const uint16_t Op2 = Encoding & 7;
2531 const uint16_t Cm = (Encoding & 0x78) >> 3;
2532 const uint16_t Cn = (Encoding & 0x780) >> 7;
2533 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2534
2535 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2536
2537 Operands.push_back(
2538 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2539 Operands.push_back(
2540 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2541 Operands.push_back(
2542 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2543 Expr = MCConstantExpr::create(Op2, getContext());
2544 Operands.push_back(
2545 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2546}
2547
Tim Northover3b0846e2014-05-24 12:50:23 +00002548/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2549/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2550bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2551 OperandVector &Operands) {
2552 if (Name.find('.') != StringRef::npos)
2553 return TokError("invalid operand");
2554
2555 Mnemonic = Name;
2556 Operands.push_back(
2557 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2558
Rafael Espindola961d4692014-11-11 05:18:41 +00002559 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002560 const AsmToken &Tok = Parser.getTok();
2561 StringRef Op = Tok.getString();
2562 SMLoc S = Tok.getLoc();
2563
Tim Northover3b0846e2014-05-24 12:50:23 +00002564 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002565 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2566 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002567 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002568 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2569 std::string Str("IC " + std::string(IC->Name) + " requires ");
2570 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2571 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002572 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002573 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002574 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002575 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2576 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002577 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002578 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2579 std::string Str("DC " + std::string(DC->Name) + " requires ");
2580 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2581 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002582 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002583 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002584 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002585 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2586 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002587 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002588 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2589 std::string Str("AT " + std::string(AT->Name) + " requires ");
2590 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2591 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002592 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002593 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002594 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002595 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2596 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002597 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002598 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2599 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2600 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2601 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002602 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002603 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002604 }
2605
Tim Northover3b0846e2014-05-24 12:50:23 +00002606 Parser.Lex(); // Eat operand.
2607
2608 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2609 bool HasRegister = false;
2610
2611 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002612 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002613 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2614 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002615 HasRegister = true;
2616 }
2617
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002618 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002619 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002620 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002621 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002622
Nirav Davee833c6c2016-11-08 18:31:04 +00002623 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2624 return true;
2625
Tim Northover3b0846e2014-05-24 12:50:23 +00002626 return false;
2627}
2628
Alex Bradbury58eba092016-11-01 16:32:05 +00002629OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002630AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002631 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002632 const AsmToken &Tok = Parser.getTok();
2633
2634 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002635 if (parseOptionalToken(AsmToken::Hash) ||
2636 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002637 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002638 const MCExpr *ImmVal;
2639 SMLoc ExprLoc = getLoc();
2640 if (getParser().parseExpression(ImmVal))
2641 return MatchOperand_ParseFail;
2642 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2643 if (!MCE) {
2644 Error(ExprLoc, "immediate value expected for barrier operand");
2645 return MatchOperand_ParseFail;
2646 }
2647 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2648 Error(ExprLoc, "barrier operand out of range");
2649 return MatchOperand_ParseFail;
2650 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002651 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2652 Operands.push_back(AArch64Operand::CreateBarrier(
2653 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002654 return MatchOperand_Success;
2655 }
2656
2657 if (Tok.isNot(AsmToken::Identifier)) {
2658 TokError("invalid operand for instruction");
2659 return MatchOperand_ParseFail;
2660 }
2661
Tim Northover3b0846e2014-05-24 12:50:23 +00002662 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002663 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2664 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002665 TokError("'sy' or #imm operand expected");
2666 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002667 } else if (!DB) {
2668 TokError("invalid barrier option name");
2669 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002670 }
2671
Tim Northovere6ae6762016-07-05 21:23:04 +00002672 Operands.push_back(AArch64Operand::CreateBarrier(
2673 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002674 Parser.Lex(); // Consume the option
2675
2676 return MatchOperand_Success;
2677}
2678
Alex Bradbury58eba092016-11-01 16:32:05 +00002679OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002680AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002681 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002682 const AsmToken &Tok = Parser.getTok();
2683
2684 if (Tok.isNot(AsmToken::Identifier))
2685 return MatchOperand_NoMatch;
2686
Tim Northovere6ae6762016-07-05 21:23:04 +00002687 int MRSReg, MSRReg;
2688 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2689 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2690 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2691 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2692 } else
2693 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002694
Tim Northovere6ae6762016-07-05 21:23:04 +00002695 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2696 unsigned PStateImm = -1;
2697 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2698 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002699
Tim Northovere6ae6762016-07-05 21:23:04 +00002700 Operands.push_back(
2701 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2702 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002703 Parser.Lex(); // Eat identifier
2704
2705 return MatchOperand_Success;
2706}
2707
Florian Hahnc4422242017-11-07 13:07:50 +00002708/// tryParseNeonVectorRegister - Parse a vector register operand.
2709bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002710 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002711 if (Parser.getTok().isNot(AsmToken::Identifier))
2712 return true;
2713
2714 SMLoc S = getLoc();
2715 // Check for a vector register specifier first.
2716 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002717 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002718 OperandMatchResultTy Res =
2719 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2720 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002721 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002722
2723 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2724 if (!KindRes)
2725 return true;
2726
2727 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002728 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002729 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2730 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002731
Tim Northover3b0846e2014-05-24 12:50:23 +00002732 // If there was an explicit qualifier, that goes on as a literal text
2733 // operand.
2734 if (!Kind.empty())
2735 Operands.push_back(
2736 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2737
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002738 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2739}
2740
2741OperandMatchResultTy
2742AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002743 SMLoc SIdx = getLoc();
2744 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002745 const MCExpr *ImmVal;
2746 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002747 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002748 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2749 if (!MCE) {
2750 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002751 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002752 }
2753
2754 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002755
Nirav Davee833c6c2016-11-08 18:31:04 +00002756 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002757 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002758
2759 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2760 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002761 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002762 }
2763
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002764 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002765}
2766
Sander de Smalen73937b72018-04-11 07:36:10 +00002767// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002768// optional kind specifier. If it is a register specifier, eat the token
2769// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002770OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002771AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002772 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002773 MCAsmParser &Parser = getParser();
2774 const AsmToken &Tok = Parser.getTok();
2775
Florian Hahn91f11e52017-11-07 16:45:48 +00002776 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002777 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002778
2779 StringRef Name = Tok.getString();
2780 // If there is a kind specifier, it's separated from the register name by
2781 // a '.'.
2782 size_t Start = 0, Next = Name.find('.');
2783 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002784 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002785
2786 if (RegNum) {
2787 if (Next != StringRef::npos) {
2788 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002789 if (!isValidVectorKind(Kind, MatchKind)) {
2790 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002791 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002792 }
2793 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002794 Parser.Lex(); // Eat the register token.
2795
2796 Reg = RegNum;
2797 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002798 }
2799
Sander de Smalen8e607342017-11-15 15:44:43 +00002800 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002801}
2802
Sander de Smalencd6be962017-12-20 11:02:42 +00002803/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2804OperandMatchResultTy
2805AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2806 // Check for a SVE predicate register specifier first.
2807 const SMLoc S = getLoc();
2808 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002809 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00002810 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002811 if (Res != MatchOperand_Success)
2812 return Res;
2813
Sander de Smalen73937b72018-04-11 07:36:10 +00002814 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2815 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002816 return MatchOperand_NoMatch;
2817
Sander de Smalen73937b72018-04-11 07:36:10 +00002818 unsigned ElementWidth = KindRes->second;
2819 Operands.push_back(AArch64Operand::CreateVectorReg(
2820 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2821 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002822
Sander de Smalen7868e742018-01-09 11:17:06 +00002823 // Not all predicates are followed by a '/m' or '/z'.
2824 MCAsmParser &Parser = getParser();
2825 if (Parser.getTok().isNot(AsmToken::Slash))
2826 return MatchOperand_Success;
2827
2828 // But when they do they shouldn't have an element type suffix.
2829 if (!Kind.empty()) {
2830 Error(S, "not expecting size suffix");
2831 return MatchOperand_ParseFail;
2832 }
2833
2834 // Add a literal slash as operand
2835 Operands.push_back(
2836 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2837
2838 Parser.Lex(); // Eat the slash.
2839
2840 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002841 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002842 if (Pred != "z" && Pred != "m") {
2843 Error(getLoc(), "expecting 'm' or 'z' predication");
2844 return MatchOperand_ParseFail;
2845 }
2846
2847 // Add zero/merge token.
2848 const char *ZM = Pred == "z" ? "z" : "m";
2849 Operands.push_back(
2850 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2851
2852 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002853 return MatchOperand_Success;
2854}
2855
Sander de Smalen50d87022018-04-19 07:35:08 +00002856/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002857bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002858 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00002859 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002860 return false;
2861
Sander de Smalen149916d2018-04-20 07:24:20 +00002862 // Otherwise try for a scalar register.
2863 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
2864 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002865
Sander de Smalen149916d2018-04-20 07:24:20 +00002866 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002867}
2868
2869bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002870 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002871 bool HasELFModifier = false;
2872 AArch64MCExpr::VariantKind RefKind;
2873
Nirav Davee833c6c2016-11-08 18:31:04 +00002874 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002875 HasELFModifier = true;
2876
Nirav Davee833c6c2016-11-08 18:31:04 +00002877 if (Parser.getTok().isNot(AsmToken::Identifier))
2878 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002879
2880 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2881 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2882 .Case("lo12", AArch64MCExpr::VK_LO12)
2883 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2884 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2885 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2886 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2887 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2888 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2889 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2890 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2891 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2892 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2893 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2894 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2895 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2896 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2897 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2898 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2899 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2900 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2901 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2902 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2903 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2904 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2905 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2906 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2907 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2908 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2909 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2910 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2911 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2912 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2913 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2914 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2915 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2916 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002917 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2918 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002919 .Default(AArch64MCExpr::VK_INVALID);
2920
Nirav Davee833c6c2016-11-08 18:31:04 +00002921 if (RefKind == AArch64MCExpr::VK_INVALID)
2922 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002923
2924 Parser.Lex(); // Eat identifier
2925
Nirav Davee833c6c2016-11-08 18:31:04 +00002926 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002927 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002928 }
2929
2930 if (getParser().parseExpression(ImmVal))
2931 return true;
2932
2933 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002934 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002935
2936 return false;
2937}
2938
Sander de Smalen650234b2018-04-12 11:40:52 +00002939template <RegKind VectorKind>
2940OperandMatchResultTy
2941AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
2942 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002943 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00002944 if (!Parser.getTok().is(AsmToken::LCurly))
2945 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002946
2947 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00002948 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00002949 bool NoMatchIsError) {
2950 auto RegTok = Parser.getTok();
2951 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
2952 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002953 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00002954 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002955 llvm_unreachable("Expected a valid vector kind");
2956 }
2957
Sander de Smalen650234b2018-04-12 11:40:52 +00002958 if (RegTok.isNot(AsmToken::Identifier) ||
2959 ParseRes == MatchOperand_ParseFail ||
2960 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
2961 Error(Loc, "vector register expected");
2962 return MatchOperand_ParseFail;
2963 }
2964
2965 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002966 };
2967
Tim Northover3b0846e2014-05-24 12:50:23 +00002968 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00002969 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00002970 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00002971
Tim Northover3b0846e2014-05-24 12:50:23 +00002972 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002973 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002974 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
2975
2976 // Put back the original left bracket if there was no match, so that
2977 // different types of list-operands can be matched (e.g. SVE, Neon).
2978 if (ParseRes == MatchOperand_NoMatch)
2979 Parser.getLexer().UnLex(LCurly);
2980
2981 if (ParseRes != MatchOperand_Success)
2982 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002983
Tim Northover3b0846e2014-05-24 12:50:23 +00002984 int64_t PrevReg = FirstReg;
2985 unsigned Count = 1;
2986
Nirav Davee833c6c2016-11-08 18:31:04 +00002987 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002988 SMLoc Loc = getLoc();
2989 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002990
Sander de Smalen50d87022018-04-19 07:35:08 +00002991 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002992 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2993 if (ParseRes != MatchOperand_Success)
2994 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002995
Tim Northover3b0846e2014-05-24 12:50:23 +00002996 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002997 if (Kind != NextKind) {
2998 Error(Loc, "mismatched register size suffix");
2999 return MatchOperand_ParseFail;
3000 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003001
3002 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3003
3004 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003005 Error(Loc, "invalid number of vectors");
3006 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003007 }
3008
3009 Count += Space;
3010 }
3011 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003012 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003013 SMLoc Loc = getLoc();
3014 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003015 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003016 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3017 if (ParseRes != MatchOperand_Success)
3018 return ParseRes;
3019
Tim Northover3b0846e2014-05-24 12:50:23 +00003020 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003021 if (Kind != NextKind) {
3022 Error(Loc, "mismatched register size suffix");
3023 return MatchOperand_ParseFail;
3024 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003025
3026 // Registers must be incremental (with wraparound at 31)
3027 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003028 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3029 Error(Loc, "registers must be sequential");
3030 return MatchOperand_ParseFail;
3031 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003032
3033 PrevReg = Reg;
3034 ++Count;
3035 }
3036 }
3037
Nirav Davee833c6c2016-11-08 18:31:04 +00003038 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003039 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003040
Sander de Smalen650234b2018-04-12 11:40:52 +00003041 if (Count > 4) {
3042 Error(S, "invalid number of vectors");
3043 return MatchOperand_ParseFail;
3044 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003045
3046 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003047 unsigned ElementWidth = 0;
3048 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003049 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003050 std::tie(NumElements, ElementWidth) = *VK;
3051 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003052
3053 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003054 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3055 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003056
Sander de Smalen650234b2018-04-12 11:40:52 +00003057 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003058}
3059
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003060/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3061bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003062 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3063 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003064 return true;
3065
3066 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3067}
3068
Alex Bradbury58eba092016-11-01 16:32:05 +00003069OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003070AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003071 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003072
Sander de Smalen50d87022018-04-19 07:35:08 +00003073 unsigned RegNum;
3074 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3075 if (Res != MatchOperand_Success)
3076 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003077
Nirav Davee833c6c2016-11-08 18:31:04 +00003078 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003079 Operands.push_back(AArch64Operand::CreateReg(
3080 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003081 return MatchOperand_Success;
3082 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003083
Nirav Davee833c6c2016-11-08 18:31:04 +00003084 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003085
Sander de Smalen50d87022018-04-19 07:35:08 +00003086 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003087 Error(getLoc(), "index must be absent or #0");
3088 return MatchOperand_ParseFail;
3089 }
3090
3091 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003092 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003093 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3094 Error(getLoc(), "index must be absent or #0");
3095 return MatchOperand_ParseFail;
3096 }
3097
Sander de Smalen50d87022018-04-19 07:35:08 +00003098 Operands.push_back(AArch64Operand::CreateReg(
3099 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003100 return MatchOperand_Success;
3101}
3102
Sander de Smalen149916d2018-04-20 07:24:20 +00003103template <bool ParseShiftExtend>
3104OperandMatchResultTy
3105AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3106 SMLoc StartLoc = getLoc();
3107
3108 unsigned RegNum;
3109 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3110 if (Res != MatchOperand_Success)
3111 return Res;
3112
3113 // No shift/extend is the default.
3114 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3115 Operands.push_back(AArch64Operand::CreateReg(
3116 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
3117 return MatchOperand_Success;
3118 }
3119
3120 // Eat the comma
3121 getParser().Lex();
3122
3123 // Match the shift
3124 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3125 Res = tryParseOptionalShiftExtend(ExtOpnd);
3126 if (Res != MatchOperand_Success)
3127 return Res;
3128
3129 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
3130 Operands.push_back(AArch64Operand::CreateReg(RegNum, RegKind::Scalar,
3131 StartLoc, Ext->getEndLoc(), getContext(),
3132 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3133 Ext->hasShiftExtendAmount()));
3134
3135 return MatchOperand_Success;
3136}
3137
Sander de Smalen5c625982018-04-13 12:56:14 +00003138bool AArch64AsmParser::parseOptionalMulVl(OperandVector &Operands) {
3139 MCAsmParser &Parser = getParser();
3140
3141 // Some SVE instructions have a decoration after the immediate, i.e.
3142 // "mul vl". We parse them here and add tokens, which must be present in the
3143 // asm string in the tablegen instruction.
3144 if (!Parser.getTok().getString().equals_lower("mul") ||
3145 !Parser.getLexer().peekTok().getString().equals_lower("vl"))
3146 return true;
3147
3148 SMLoc S = getLoc();
3149 Operands.push_back(
3150 AArch64Operand::CreateToken("mul", false, S, getContext()));
3151 Parser.Lex(); // Eat the "mul"
3152
3153 S = getLoc();
3154 Operands.push_back(
3155 AArch64Operand::CreateToken("vl", false, S, getContext()));
3156 Parser.Lex(); // Eat the "vl"
3157
3158 return false;
3159}
3160
Tim Northover3b0846e2014-05-24 12:50:23 +00003161/// parseOperand - Parse a arm instruction operand. For now this parses the
3162/// operand regardless of the mnemonic.
3163bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3164 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003165 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003166
3167 OperandMatchResultTy ResTy =
3168 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3169
Tim Northover3b0846e2014-05-24 12:50:23 +00003170 // Check if the current operand has a custom associated parser, if so, try to
3171 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003172 if (ResTy == MatchOperand_Success)
3173 return false;
3174 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3175 // there was a match, but an error occurred, in which case, just return that
3176 // the operand parsing failed.
3177 if (ResTy == MatchOperand_ParseFail)
3178 return true;
3179
3180 // Nothing custom, so do general case parsing.
3181 SMLoc S, E;
3182 switch (getLexer().getKind()) {
3183 default: {
3184 SMLoc S = getLoc();
3185 const MCExpr *Expr;
3186 if (parseSymbolicImmVal(Expr))
3187 return Error(S, "invalid operand");
3188
3189 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3190 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3191 return false;
3192 }
3193 case AsmToken::LBrac: {
3194 SMLoc Loc = Parser.getTok().getLoc();
3195 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3196 getContext()));
3197 Parser.Lex(); // Eat '['
3198
3199 // There's no comma after a '[', so we can parse the next operand
3200 // immediately.
3201 return parseOperand(Operands, false, false);
3202 }
3203 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003204 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003205 case AsmToken::Identifier: {
3206 // If we're expecting a Condition Code operand, then just parse that.
3207 if (isCondCode)
3208 return parseCondCode(Operands, invertCondCode);
3209
3210 // If it's a register name, parse it.
3211 if (!parseRegister(Operands))
3212 return false;
3213
Sander de Smalen5c625982018-04-13 12:56:14 +00003214 // See if this is a "mul vl" decoration used by SVE instructions.
3215 if (!parseOptionalMulVl(Operands))
3216 return false;
3217
Tim Northover3b0846e2014-05-24 12:50:23 +00003218 // This could be an optional "shift" or "extend" operand.
3219 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3220 // We can only continue if no tokens were eaten.
3221 if (GotShift != MatchOperand_NoMatch)
3222 return GotShift;
3223
3224 // This was not a register so parse other operands that start with an
3225 // identifier (like labels) as expressions and create them as immediates.
3226 const MCExpr *IdVal;
3227 S = getLoc();
3228 if (getParser().parseExpression(IdVal))
3229 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003230 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3231 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3232 return false;
3233 }
3234 case AsmToken::Integer:
3235 case AsmToken::Real:
3236 case AsmToken::Hash: {
3237 // #42 -> immediate.
3238 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003239
3240 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003241
3242 // Parse a negative sign
3243 bool isNegative = false;
3244 if (Parser.getTok().is(AsmToken::Minus)) {
3245 isNegative = true;
3246 // We need to consume this token only when we have a Real, otherwise
3247 // we let parseSymbolicImmVal take care of it
3248 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3249 Parser.Lex();
3250 }
3251
3252 // The only Real that should come through here is a literal #0.0 for
3253 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3254 // so convert the value.
3255 const AsmToken &Tok = Parser.getTok();
3256 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003257 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003258 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3259 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3260 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3261 Mnemonic != "fcmlt")
3262 return TokError("unexpected floating point literal");
3263 else if (IntVal != 0 || isNegative)
3264 return TokError("expected floating-point constant #0.0");
3265 Parser.Lex(); // Eat the token.
3266
3267 Operands.push_back(
3268 AArch64Operand::CreateToken("#0", false, S, getContext()));
3269 Operands.push_back(
3270 AArch64Operand::CreateToken(".0", false, S, getContext()));
3271 return false;
3272 }
3273
3274 const MCExpr *ImmVal;
3275 if (parseSymbolicImmVal(ImmVal))
3276 return true;
3277
3278 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3279 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3280 return false;
3281 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003282 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003283 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003284 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003285 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003286 Parser.Lex(); // Eat '='
3287 const MCExpr *SubExprVal;
3288 if (getParser().parseExpression(SubExprVal))
3289 return true;
3290
David Peixottoae5ba762014-07-18 16:05:14 +00003291 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003292 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003293 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003294
3295 bool IsXReg =
3296 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3297 Operands[1]->getReg());
3298
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003299 MCContext& Ctx = getContext();
3300 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3301 // 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 +00003302 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003303 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3304 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3305 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3306 ShiftAmt += 16;
3307 Imm >>= 16;
3308 }
3309 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3310 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3311 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003312 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003313 if (ShiftAmt)
3314 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3315 ShiftAmt, true, S, E, Ctx));
3316 return false;
3317 }
David Peixottoae5ba762014-07-18 16:05:14 +00003318 APInt Simm = APInt(64, Imm << ShiftAmt);
3319 // check if the immediate is an unsigned or signed 32-bit int for W regs
3320 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3321 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003322 }
3323 // 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 +00003324 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003325 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003326 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3327 return false;
3328 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003329 }
3330}
3331
3332/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3333/// operands.
3334bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3335 StringRef Name, SMLoc NameLoc,
3336 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003337 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003338 Name = StringSwitch<StringRef>(Name.lower())
3339 .Case("beq", "b.eq")
3340 .Case("bne", "b.ne")
3341 .Case("bhs", "b.hs")
3342 .Case("bcs", "b.cs")
3343 .Case("blo", "b.lo")
3344 .Case("bcc", "b.cc")
3345 .Case("bmi", "b.mi")
3346 .Case("bpl", "b.pl")
3347 .Case("bvs", "b.vs")
3348 .Case("bvc", "b.vc")
3349 .Case("bhi", "b.hi")
3350 .Case("bls", "b.ls")
3351 .Case("bge", "b.ge")
3352 .Case("blt", "b.lt")
3353 .Case("bgt", "b.gt")
3354 .Case("ble", "b.le")
3355 .Case("bal", "b.al")
3356 .Case("bnv", "b.nv")
3357 .Default(Name);
3358
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003359 // First check for the AArch64-specific .req directive.
3360 if (Parser.getTok().is(AsmToken::Identifier) &&
3361 Parser.getTok().getIdentifier() == ".req") {
3362 parseDirectiveReq(Name, NameLoc);
3363 // We always return 'error' for this, as we're done with this
3364 // statement and don't need to match the 'instruction."
3365 return true;
3366 }
3367
Tim Northover3b0846e2014-05-24 12:50:23 +00003368 // Create the leading tokens for the mnemonic, split by '.' characters.
3369 size_t Start = 0, Next = Name.find('.');
3370 StringRef Head = Name.slice(Start, Next);
3371
3372 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003373 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3374 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003375
3376 Operands.push_back(
3377 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3378 Mnemonic = Head;
3379
3380 // Handle condition codes for a branch mnemonic
3381 if (Head == "b" && Next != StringRef::npos) {
3382 Start = Next;
3383 Next = Name.find('.', Start + 1);
3384 Head = Name.slice(Start + 1, Next);
3385
3386 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3387 (Head.data() - Name.data()));
3388 AArch64CC::CondCode CC = parseCondCodeString(Head);
3389 if (CC == AArch64CC::Invalid)
3390 return Error(SuffixLoc, "invalid condition code");
3391 Operands.push_back(
3392 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3393 Operands.push_back(
3394 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3395 }
3396
3397 // Add the remaining tokens in the mnemonic.
3398 while (Next != StringRef::npos) {
3399 Start = Next;
3400 Next = Name.find('.', Start + 1);
3401 Head = Name.slice(Start, Next);
3402 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3403 (Head.data() - Name.data()) + 1);
3404 Operands.push_back(
3405 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3406 }
3407
3408 // Conditional compare instructions have a Condition Code operand, which needs
3409 // to be parsed and an immediate operand created.
3410 bool condCodeFourthOperand =
3411 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3412 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3413 Head == "csinc" || Head == "csinv" || Head == "csneg");
3414
3415 // These instructions are aliases to some of the conditional select
3416 // instructions. However, the condition code is inverted in the aliased
3417 // instruction.
3418 //
3419 // FIXME: Is this the correct way to handle these? Or should the parser
3420 // generate the aliased instructions directly?
3421 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3422 bool condCodeThirdOperand =
3423 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3424
3425 // Read the remaining operands.
3426 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3427 // Read the first operand.
3428 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003429 return true;
3430 }
3431
3432 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003433 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003434 // Parse and remember the operand.
3435 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3436 (N == 3 && condCodeThirdOperand) ||
3437 (N == 2 && condCodeSecondOperand),
3438 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003439 return true;
3440 }
3441
3442 // After successfully parsing some operands there are two special cases to
3443 // consider (i.e. notional operands not separated by commas). Both are due
3444 // to memory specifiers:
3445 // + An RBrac will end an address for load/store/prefetch
3446 // + An '!' will indicate a pre-indexed operation.
3447 //
3448 // It's someone else's responsibility to make sure these tokens are sane
3449 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003450
Nirav Davee833c6c2016-11-08 18:31:04 +00003451 SMLoc RLoc = Parser.getTok().getLoc();
3452 if (parseOptionalToken(AsmToken::RBrac))
3453 Operands.push_back(
3454 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3455 SMLoc ELoc = Parser.getTok().getLoc();
3456 if (parseOptionalToken(AsmToken::Exclaim))
3457 Operands.push_back(
3458 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003459
3460 ++N;
3461 }
3462 }
3463
Nirav Davee833c6c2016-11-08 18:31:04 +00003464 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3465 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003466
Tim Northover3b0846e2014-05-24 12:50:23 +00003467 return false;
3468}
3469
3470// FIXME: This entire function is a giant hack to provide us with decent
3471// operand range validation/diagnostics until TableGen/MC can be extended
3472// to support autogeneration of this kind of validation.
3473bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3474 SmallVectorImpl<SMLoc> &Loc) {
3475 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3476 // Check for indexed addressing modes w/ the base register being the
3477 // same as a destination/source register or pair load where
3478 // the Rt == Rt2. All of those are undefined behaviour.
3479 switch (Inst.getOpcode()) {
3480 case AArch64::LDPSWpre:
3481 case AArch64::LDPWpost:
3482 case AArch64::LDPWpre:
3483 case AArch64::LDPXpost:
3484 case AArch64::LDPXpre: {
3485 unsigned Rt = Inst.getOperand(1).getReg();
3486 unsigned Rt2 = Inst.getOperand(2).getReg();
3487 unsigned Rn = Inst.getOperand(3).getReg();
3488 if (RI->isSubRegisterEq(Rn, Rt))
3489 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3490 "is also a destination");
3491 if (RI->isSubRegisterEq(Rn, Rt2))
3492 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3493 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003494 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003495 }
3496 case AArch64::LDPDi:
3497 case AArch64::LDPQi:
3498 case AArch64::LDPSi:
3499 case AArch64::LDPSWi:
3500 case AArch64::LDPWi:
3501 case AArch64::LDPXi: {
3502 unsigned Rt = Inst.getOperand(0).getReg();
3503 unsigned Rt2 = Inst.getOperand(1).getReg();
3504 if (Rt == Rt2)
3505 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3506 break;
3507 }
3508 case AArch64::LDPDpost:
3509 case AArch64::LDPDpre:
3510 case AArch64::LDPQpost:
3511 case AArch64::LDPQpre:
3512 case AArch64::LDPSpost:
3513 case AArch64::LDPSpre:
3514 case AArch64::LDPSWpost: {
3515 unsigned Rt = Inst.getOperand(1).getReg();
3516 unsigned Rt2 = Inst.getOperand(2).getReg();
3517 if (Rt == Rt2)
3518 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3519 break;
3520 }
3521 case AArch64::STPDpost:
3522 case AArch64::STPDpre:
3523 case AArch64::STPQpost:
3524 case AArch64::STPQpre:
3525 case AArch64::STPSpost:
3526 case AArch64::STPSpre:
3527 case AArch64::STPWpost:
3528 case AArch64::STPWpre:
3529 case AArch64::STPXpost:
3530 case AArch64::STPXpre: {
3531 unsigned Rt = Inst.getOperand(1).getReg();
3532 unsigned Rt2 = Inst.getOperand(2).getReg();
3533 unsigned Rn = Inst.getOperand(3).getReg();
3534 if (RI->isSubRegisterEq(Rn, Rt))
3535 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3536 "is also a source");
3537 if (RI->isSubRegisterEq(Rn, Rt2))
3538 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3539 "is also a source");
3540 break;
3541 }
3542 case AArch64::LDRBBpre:
3543 case AArch64::LDRBpre:
3544 case AArch64::LDRHHpre:
3545 case AArch64::LDRHpre:
3546 case AArch64::LDRSBWpre:
3547 case AArch64::LDRSBXpre:
3548 case AArch64::LDRSHWpre:
3549 case AArch64::LDRSHXpre:
3550 case AArch64::LDRSWpre:
3551 case AArch64::LDRWpre:
3552 case AArch64::LDRXpre:
3553 case AArch64::LDRBBpost:
3554 case AArch64::LDRBpost:
3555 case AArch64::LDRHHpost:
3556 case AArch64::LDRHpost:
3557 case AArch64::LDRSBWpost:
3558 case AArch64::LDRSBXpost:
3559 case AArch64::LDRSHWpost:
3560 case AArch64::LDRSHXpost:
3561 case AArch64::LDRSWpost:
3562 case AArch64::LDRWpost:
3563 case AArch64::LDRXpost: {
3564 unsigned Rt = Inst.getOperand(1).getReg();
3565 unsigned Rn = Inst.getOperand(2).getReg();
3566 if (RI->isSubRegisterEq(Rn, Rt))
3567 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3568 "is also a source");
3569 break;
3570 }
3571 case AArch64::STRBBpost:
3572 case AArch64::STRBpost:
3573 case AArch64::STRHHpost:
3574 case AArch64::STRHpost:
3575 case AArch64::STRWpost:
3576 case AArch64::STRXpost:
3577 case AArch64::STRBBpre:
3578 case AArch64::STRBpre:
3579 case AArch64::STRHHpre:
3580 case AArch64::STRHpre:
3581 case AArch64::STRWpre:
3582 case AArch64::STRXpre: {
3583 unsigned Rt = Inst.getOperand(1).getReg();
3584 unsigned Rn = Inst.getOperand(2).getReg();
3585 if (RI->isSubRegisterEq(Rn, Rt))
3586 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3587 "is also a source");
3588 break;
3589 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003590 case AArch64::STXRB:
3591 case AArch64::STXRH:
3592 case AArch64::STXRW:
3593 case AArch64::STXRX:
3594 case AArch64::STLXRB:
3595 case AArch64::STLXRH:
3596 case AArch64::STLXRW:
3597 case AArch64::STLXRX: {
3598 unsigned Rs = Inst.getOperand(0).getReg();
3599 unsigned Rt = Inst.getOperand(1).getReg();
3600 unsigned Rn = Inst.getOperand(2).getReg();
3601 if (RI->isSubRegisterEq(Rt, Rs) ||
3602 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3603 return Error(Loc[0],
3604 "unpredictable STXR instruction, status is also a source");
3605 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003606 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003607 case AArch64::STXPW:
3608 case AArch64::STXPX:
3609 case AArch64::STLXPW:
3610 case AArch64::STLXPX: {
3611 unsigned Rs = Inst.getOperand(0).getReg();
3612 unsigned Rt1 = Inst.getOperand(1).getReg();
3613 unsigned Rt2 = Inst.getOperand(2).getReg();
3614 unsigned Rn = Inst.getOperand(3).getReg();
3615 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3616 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3617 return Error(Loc[0],
3618 "unpredictable STXP instruction, status is also a source");
3619 break;
3620 }
3621 }
3622
Tim Northover3b0846e2014-05-24 12:50:23 +00003623
3624 // Now check immediate ranges. Separate from the above as there is overlap
3625 // in the instructions being checked and this keeps the nested conditionals
3626 // to a minimum.
3627 switch (Inst.getOpcode()) {
3628 case AArch64::ADDSWri:
3629 case AArch64::ADDSXri:
3630 case AArch64::ADDWri:
3631 case AArch64::ADDXri:
3632 case AArch64::SUBSWri:
3633 case AArch64::SUBSXri:
3634 case AArch64::SUBWri:
3635 case AArch64::SUBXri: {
3636 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3637 // some slight duplication here.
3638 if (Inst.getOperand(2).isExpr()) {
3639 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3640 AArch64MCExpr::VariantKind ELFRefKind;
3641 MCSymbolRefExpr::VariantKind DarwinRefKind;
3642 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003643 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3644
3645 // Only allow these with ADDXri.
3646 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3647 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3648 Inst.getOpcode() == AArch64::ADDXri)
3649 return false;
3650
3651 // Only allow these with ADDXri/ADDWri
3652 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3653 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3654 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3655 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3656 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3657 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3658 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003659 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3660 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3661 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003662 (Inst.getOpcode() == AArch64::ADDXri ||
3663 Inst.getOpcode() == AArch64::ADDWri))
3664 return false;
3665
3666 // Don't allow symbol refs in the immediate field otherwise
3667 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3668 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3669 // 'cmp w0, 'borked')
3670 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003671 }
Diana Picusc93518d2016-10-11 09:17:47 +00003672 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003673 }
3674 return false;
3675 }
3676 default:
3677 return false;
3678 }
3679}
3680
Craig Topper05515562017-10-26 06:46:41 +00003681static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3682 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003683
3684bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3685 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003686 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003687 case Match_InvalidTiedOperand:
3688 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003689 case Match_MissingFeature:
3690 return Error(Loc,
3691 "instruction requires a CPU feature not currently enabled");
3692 case Match_InvalidOperand:
3693 return Error(Loc, "invalid operand for instruction");
3694 case Match_InvalidSuffix:
3695 return Error(Loc, "invalid type suffix for instruction");
3696 case Match_InvalidCondCode:
3697 return Error(Loc, "expected AArch64 condition code");
3698 case Match_AddSubRegExtendSmall:
3699 return Error(Loc,
3700 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3701 case Match_AddSubRegExtendLarge:
3702 return Error(Loc,
3703 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3704 case Match_AddSubSecondSource:
3705 return Error(Loc,
3706 "expected compatible register, symbol or integer in range [0, 4095]");
3707 case Match_LogicalSecondSource:
3708 return Error(Loc, "expected compatible register or logical immediate");
3709 case Match_InvalidMovImm32Shift:
3710 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3711 case Match_InvalidMovImm64Shift:
3712 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3713 case Match_AddSubRegShift32:
3714 return Error(Loc,
3715 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3716 case Match_AddSubRegShift64:
3717 return Error(Loc,
3718 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3719 case Match_InvalidFPImm:
3720 return Error(Loc,
3721 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003722 case Match_InvalidMemoryIndexedSImm6:
3723 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003724 case Match_InvalidMemoryIndexedSImm5:
3725 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003726 case Match_InvalidMemoryIndexed1SImm4:
3727 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003728 case Match_InvalidMemoryIndexed2SImm4:
3729 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003730 case Match_InvalidMemoryIndexed3SImm4:
3731 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003732 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00003733 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003734 case Match_InvalidMemoryIndexedSImm9:
3735 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003736 case Match_InvalidMemoryIndexedSImm10:
3737 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003738 case Match_InvalidMemoryIndexed4SImm7:
3739 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3740 case Match_InvalidMemoryIndexed8SImm7:
3741 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3742 case Match_InvalidMemoryIndexed16SImm7:
3743 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3744 case Match_InvalidMemoryWExtend8:
3745 return Error(Loc,
3746 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3747 case Match_InvalidMemoryWExtend16:
3748 return Error(Loc,
3749 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3750 case Match_InvalidMemoryWExtend32:
3751 return Error(Loc,
3752 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3753 case Match_InvalidMemoryWExtend64:
3754 return Error(Loc,
3755 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3756 case Match_InvalidMemoryWExtend128:
3757 return Error(Loc,
3758 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3759 case Match_InvalidMemoryXExtend8:
3760 return Error(Loc,
3761 "expected 'lsl' or 'sxtx' with optional shift of #0");
3762 case Match_InvalidMemoryXExtend16:
3763 return Error(Loc,
3764 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3765 case Match_InvalidMemoryXExtend32:
3766 return Error(Loc,
3767 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3768 case Match_InvalidMemoryXExtend64:
3769 return Error(Loc,
3770 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3771 case Match_InvalidMemoryXExtend128:
3772 return Error(Loc,
3773 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3774 case Match_InvalidMemoryIndexed1:
3775 return Error(Loc, "index must be an integer in range [0, 4095].");
3776 case Match_InvalidMemoryIndexed2:
3777 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3778 case Match_InvalidMemoryIndexed4:
3779 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3780 case Match_InvalidMemoryIndexed8:
3781 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3782 case Match_InvalidMemoryIndexed16:
3783 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003784 case Match_InvalidImm0_1:
3785 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003786 case Match_InvalidImm0_7:
3787 return Error(Loc, "immediate must be an integer in range [0, 7].");
3788 case Match_InvalidImm0_15:
3789 return Error(Loc, "immediate must be an integer in range [0, 15].");
3790 case Match_InvalidImm0_31:
3791 return Error(Loc, "immediate must be an integer in range [0, 31].");
3792 case Match_InvalidImm0_63:
3793 return Error(Loc, "immediate must be an integer in range [0, 63].");
3794 case Match_InvalidImm0_127:
3795 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003796 case Match_InvalidImm0_255:
3797 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003798 case Match_InvalidImm0_65535:
3799 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3800 case Match_InvalidImm1_8:
3801 return Error(Loc, "immediate must be an integer in range [1, 8].");
3802 case Match_InvalidImm1_16:
3803 return Error(Loc, "immediate must be an integer in range [1, 16].");
3804 case Match_InvalidImm1_32:
3805 return Error(Loc, "immediate must be an integer in range [1, 32].");
3806 case Match_InvalidImm1_64:
3807 return Error(Loc, "immediate must be an integer in range [1, 64].");
3808 case Match_InvalidIndex1:
3809 return Error(Loc, "expected lane specifier '[1]'");
3810 case Match_InvalidIndexB:
3811 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3812 case Match_InvalidIndexH:
3813 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3814 case Match_InvalidIndexS:
3815 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3816 case Match_InvalidIndexD:
3817 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3818 case Match_InvalidLabel:
3819 return Error(Loc, "expected label or encodable integer pc offset");
3820 case Match_MRS:
3821 return Error(Loc, "expected readable system register");
3822 case Match_MSR:
3823 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003824 case Match_InvalidComplexRotationEven:
3825 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3826 case Match_InvalidComplexRotationOdd:
3827 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003828 case Match_MnemonicFail: {
3829 std::string Suggestion = AArch64MnemonicSpellCheck(
3830 ((AArch64Operand &)*Operands[0]).getToken(),
3831 ComputeAvailableFeatures(STI->getFeatureBits()));
3832 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3833 }
Sander de Smalen367694b2018-04-20 08:54:49 +00003834 case Match_InvalidGPR64shifted8:
3835 return Error(Loc, "register must be x0..x30 or xzr, without shift");
3836 case Match_InvalidGPR64shifted16:
3837 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
3838 case Match_InvalidGPR64shifted32:
3839 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
3840 case Match_InvalidGPR64shifted64:
3841 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
3842 case Match_InvalidGPR64NoXZRshifted8:
3843 return Error(Loc, "register must be x0..x30 without shift");
3844 case Match_InvalidGPR64NoXZRshifted16:
3845 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
3846 case Match_InvalidGPR64NoXZRshifted32:
3847 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
3848 case Match_InvalidGPR64NoXZRshifted64:
3849 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00003850 case Match_InvalidZPR32UXTW8:
3851 case Match_InvalidZPR32SXTW8:
3852 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
3853 case Match_InvalidZPR32UXTW16:
3854 case Match_InvalidZPR32SXTW16:
3855 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
3856 case Match_InvalidZPR32UXTW32:
3857 case Match_InvalidZPR32SXTW32:
3858 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
3859 case Match_InvalidZPR32UXTW64:
3860 case Match_InvalidZPR32SXTW64:
3861 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
3862 case Match_InvalidZPR64UXTW8:
3863 case Match_InvalidZPR64SXTW8:
3864 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
3865 case Match_InvalidZPR64UXTW16:
3866 case Match_InvalidZPR64SXTW16:
3867 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
3868 case Match_InvalidZPR64UXTW32:
3869 case Match_InvalidZPR64SXTW32:
3870 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
3871 case Match_InvalidZPR64UXTW64:
3872 case Match_InvalidZPR64SXTW64:
3873 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
3874 case Match_InvalidZPR64LSL8:
3875 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
3876 case Match_InvalidZPR64LSL16:
3877 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
3878 case Match_InvalidZPR64LSL32:
3879 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
3880 case Match_InvalidZPR64LSL64:
3881 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003882 case Match_InvalidSVEPattern:
3883 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003884 case Match_InvalidSVEPredicateAnyReg:
3885 case Match_InvalidSVEPredicateBReg:
3886 case Match_InvalidSVEPredicateHReg:
3887 case Match_InvalidSVEPredicateSReg:
3888 case Match_InvalidSVEPredicateDReg:
3889 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003890 case Match_InvalidSVEPredicate3bAnyReg:
3891 case Match_InvalidSVEPredicate3bBReg:
3892 case Match_InvalidSVEPredicate3bHReg:
3893 case Match_InvalidSVEPredicate3bSReg:
3894 case Match_InvalidSVEPredicate3bDReg:
3895 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003896 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003897 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003898 }
3899}
3900
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003901static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003902
3903bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3904 OperandVector &Operands,
3905 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003906 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003907 bool MatchingInlineAsm) {
3908 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003909 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3910 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003911
David Blaikie960ea3f2014-06-08 16:18:35 +00003912 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003913 unsigned NumOperands = Operands.size();
3914
3915 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003916 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3917 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003918 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003919 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003920 if (Op3CE) {
3921 uint64_t Op3Val = Op3CE->getValue();
3922 uint64_t NewOp3Val = 0;
3923 uint64_t NewOp4Val = 0;
3924 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003925 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003926 NewOp3Val = (32 - Op3Val) & 0x1f;
3927 NewOp4Val = 31 - Op3Val;
3928 } else {
3929 NewOp3Val = (64 - Op3Val) & 0x3f;
3930 NewOp4Val = 63 - Op3Val;
3931 }
3932
Jim Grosbach13760bd2015-05-30 01:25:56 +00003933 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3934 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003935
3936 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003937 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003938 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003939 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3940 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3941 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003942 }
3943 }
Tim Northover03b99f62015-04-30 18:28:58 +00003944 } else if (NumOperands == 4 && Tok == "bfc") {
3945 // FIXME: Horrible hack to handle BFC->BFM alias.
3946 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3947 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3948 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3949
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003950 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003951 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3952 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3953
3954 if (LSBCE && WidthCE) {
3955 uint64_t LSB = LSBCE->getValue();
3956 uint64_t Width = WidthCE->getValue();
3957
3958 uint64_t RegWidth = 0;
3959 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3960 Op1.getReg()))
3961 RegWidth = 64;
3962 else
3963 RegWidth = 32;
3964
3965 if (LSB >= RegWidth)
3966 return Error(LSBOp.getStartLoc(),
3967 "expected integer in range [0, 31]");
3968 if (Width < 1 || Width > RegWidth)
3969 return Error(WidthOp.getStartLoc(),
3970 "expected integer in range [1, 32]");
3971
3972 uint64_t ImmR = 0;
3973 if (RegWidth == 32)
3974 ImmR = (32 - LSB) & 0x1f;
3975 else
3976 ImmR = (64 - LSB) & 0x3f;
3977
3978 uint64_t ImmS = Width - 1;
3979
3980 if (ImmR != 0 && ImmS >= ImmR)
3981 return Error(WidthOp.getStartLoc(),
3982 "requested insert overflows register");
3983
Jim Grosbach13760bd2015-05-30 01:25:56 +00003984 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3985 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003986 Operands[0] = AArch64Operand::CreateToken(
3987 "bfm", false, Op.getStartLoc(), getContext());
3988 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003989 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3990 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003991 Operands[3] = AArch64Operand::CreateImm(
3992 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3993 Operands.emplace_back(
3994 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3995 WidthOp.getEndLoc(), getContext()));
3996 }
3997 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003998 } else if (NumOperands == 5) {
3999 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4000 // UBFIZ -> UBFM aliases.
4001 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004002 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4003 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4004 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004005
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004006 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004007 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4008 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004009
4010 if (Op3CE && Op4CE) {
4011 uint64_t Op3Val = Op3CE->getValue();
4012 uint64_t Op4Val = Op4CE->getValue();
4013
4014 uint64_t RegWidth = 0;
4015 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004016 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004017 RegWidth = 64;
4018 else
4019 RegWidth = 32;
4020
4021 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004022 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004023 "expected integer in range [0, 31]");
4024 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004025 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004026 "expected integer in range [1, 32]");
4027
4028 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004029 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004030 NewOp3Val = (32 - Op3Val) & 0x1f;
4031 else
4032 NewOp3Val = (64 - Op3Val) & 0x3f;
4033
4034 uint64_t NewOp4Val = Op4Val - 1;
4035
4036 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004037 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004038 "requested insert overflows register");
4039
4040 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004041 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004042 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004043 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004044 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004045 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004046 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004047 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004048 if (Tok == "bfi")
4049 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004050 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004051 else if (Tok == "sbfiz")
4052 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004053 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004054 else if (Tok == "ubfiz")
4055 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004056 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004057 else
4058 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004059 }
4060 }
4061
4062 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4063 // UBFX -> UBFM aliases.
4064 } else if (NumOperands == 5 &&
4065 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004066 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4067 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4068 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004069
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004070 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004071 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4072 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004073
4074 if (Op3CE && Op4CE) {
4075 uint64_t Op3Val = Op3CE->getValue();
4076 uint64_t Op4Val = Op4CE->getValue();
4077
4078 uint64_t RegWidth = 0;
4079 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004080 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004081 RegWidth = 64;
4082 else
4083 RegWidth = 32;
4084
4085 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004086 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004087 "expected integer in range [0, 31]");
4088 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004089 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004090 "expected integer in range [1, 32]");
4091
4092 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4093
4094 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004095 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004096 "requested extract overflows register");
4097
4098 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004099 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004100 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004101 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004102 if (Tok == "bfxil")
4103 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004104 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004105 else if (Tok == "sbfx")
4106 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004107 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004108 else if (Tok == "ubfx")
4109 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004110 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004111 else
4112 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004113 }
4114 }
4115 }
4116 }
Tim Northover9097a072017-12-18 10:36:00 +00004117
4118 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4119 // instruction for FP registers correctly in some rare circumstances. Convert
4120 // it to a safe instruction and warn (because silently changing someone's
4121 // assembly is rude).
4122 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4123 NumOperands == 4 && Tok == "movi") {
4124 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4125 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4126 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4127 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4128 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4129 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4130 if (Suffix.lower() == ".2d" &&
4131 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4132 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4133 " correctly on this CPU, converting to equivalent movi.16b");
4134 // Switch the suffix to .16b.
4135 unsigned Idx = Op1.isToken() ? 1 : 2;
4136 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4137 getContext());
4138 }
4139 }
4140 }
4141
Tim Northover3b0846e2014-05-24 12:50:23 +00004142 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4143 // InstAlias can't quite handle this since the reg classes aren't
4144 // subclasses.
4145 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4146 // The source register can be Wn here, but the matcher expects a
4147 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004148 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004149 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004150 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004151 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4152 Op.getStartLoc(), Op.getEndLoc(),
4153 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004154 }
4155 }
4156 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4157 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004158 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004159 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004160 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004161 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004162 // The source register can be Wn here, but the matcher expects a
4163 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004164 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004165 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004166 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004167 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4168 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004169 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004170 }
4171 }
4172 }
4173 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4174 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004175 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004176 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004177 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004178 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004179 // The source register can be Wn here, but the matcher expects a
4180 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004181 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004182 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004183 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004184 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4185 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004186 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004187 }
4188 }
4189 }
4190
Tim Northover3b0846e2014-05-24 12:50:23 +00004191 MCInst Inst;
4192 // First try to match against the secondary set of tables containing the
4193 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4194 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004195 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004196
4197 // If that fails, try against the alternate table containing long-form NEON:
4198 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004199 if (MatchResult != Match_Success) {
4200 // But first, save the short-form match result: we can use it in case the
4201 // long-form match also fails.
4202 auto ShortFormNEONErrorInfo = ErrorInfo;
4203 auto ShortFormNEONMatchResult = MatchResult;
4204
Tim Northover3b0846e2014-05-24 12:50:23 +00004205 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004206 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004207
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004208 // Now, both matches failed, and the long-form match failed on the mnemonic
4209 // suffix token operand. The short-form match failure is probably more
4210 // relevant: use it instead.
4211 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004212 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004213 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4214 MatchResult = ShortFormNEONMatchResult;
4215 ErrorInfo = ShortFormNEONErrorInfo;
4216 }
4217 }
4218
Tim Northover3b0846e2014-05-24 12:50:23 +00004219 switch (MatchResult) {
4220 case Match_Success: {
4221 // Perform range checking and other semantic validations
4222 SmallVector<SMLoc, 8> OperandLocs;
4223 NumOperands = Operands.size();
4224 for (unsigned i = 1; i < NumOperands; ++i)
4225 OperandLocs.push_back(Operands[i]->getStartLoc());
4226 if (validateInstruction(Inst, OperandLocs))
4227 return true;
4228
4229 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004230 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004231 return false;
4232 }
4233 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004234 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004235 // Special case the error message for the very common case where only
4236 // a single subtarget feature is missing (neon, e.g.).
4237 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004238 uint64_t Mask = 1;
4239 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4240 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004241 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004242 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004243 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004244 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004245 }
4246 return Error(IDLoc, Msg);
4247 }
4248 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004249 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004250 case Match_InvalidOperand: {
4251 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004252
Tim Northover26bb14e2014-08-18 11:49:42 +00004253 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004254 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004255 return Error(IDLoc, "too few operands for instruction",
4256 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004257
David Blaikie960ea3f2014-06-08 16:18:35 +00004258 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004259 if (ErrorLoc == SMLoc())
4260 ErrorLoc = IDLoc;
4261 }
4262 // If the match failed on a suffix token operand, tweak the diagnostic
4263 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004264 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4265 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004266 MatchResult = Match_InvalidSuffix;
4267
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004268 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004269 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004270 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004271 case Match_InvalidMemoryIndexed1:
4272 case Match_InvalidMemoryIndexed2:
4273 case Match_InvalidMemoryIndexed4:
4274 case Match_InvalidMemoryIndexed8:
4275 case Match_InvalidMemoryIndexed16:
4276 case Match_InvalidCondCode:
4277 case Match_AddSubRegExtendSmall:
4278 case Match_AddSubRegExtendLarge:
4279 case Match_AddSubSecondSource:
4280 case Match_LogicalSecondSource:
4281 case Match_AddSubRegShift32:
4282 case Match_AddSubRegShift64:
4283 case Match_InvalidMovImm32Shift:
4284 case Match_InvalidMovImm64Shift:
4285 case Match_InvalidFPImm:
4286 case Match_InvalidMemoryWExtend8:
4287 case Match_InvalidMemoryWExtend16:
4288 case Match_InvalidMemoryWExtend32:
4289 case Match_InvalidMemoryWExtend64:
4290 case Match_InvalidMemoryWExtend128:
4291 case Match_InvalidMemoryXExtend8:
4292 case Match_InvalidMemoryXExtend16:
4293 case Match_InvalidMemoryXExtend32:
4294 case Match_InvalidMemoryXExtend64:
4295 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004296 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004297 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004298 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004299 case Match_InvalidMemoryIndexed4SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004300 case Match_InvalidMemoryIndexed4SImm7:
4301 case Match_InvalidMemoryIndexed8SImm7:
4302 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen5c625982018-04-13 12:56:14 +00004303 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004304 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004305 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004306 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004307 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004308 case Match_InvalidImm0_7:
4309 case Match_InvalidImm0_15:
4310 case Match_InvalidImm0_31:
4311 case Match_InvalidImm0_63:
4312 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004313 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004314 case Match_InvalidImm0_65535:
4315 case Match_InvalidImm1_8:
4316 case Match_InvalidImm1_16:
4317 case Match_InvalidImm1_32:
4318 case Match_InvalidImm1_64:
4319 case Match_InvalidIndex1:
4320 case Match_InvalidIndexB:
4321 case Match_InvalidIndexH:
4322 case Match_InvalidIndexS:
4323 case Match_InvalidIndexD:
4324 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004325 case Match_InvalidComplexRotationEven:
4326 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004327 case Match_InvalidGPR64shifted8:
4328 case Match_InvalidGPR64shifted16:
4329 case Match_InvalidGPR64shifted32:
4330 case Match_InvalidGPR64shifted64:
4331 case Match_InvalidGPR64NoXZRshifted8:
4332 case Match_InvalidGPR64NoXZRshifted16:
4333 case Match_InvalidGPR64NoXZRshifted32:
4334 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004335 case Match_InvalidZPR32UXTW8:
4336 case Match_InvalidZPR32UXTW16:
4337 case Match_InvalidZPR32UXTW32:
4338 case Match_InvalidZPR32UXTW64:
4339 case Match_InvalidZPR32SXTW8:
4340 case Match_InvalidZPR32SXTW16:
4341 case Match_InvalidZPR32SXTW32:
4342 case Match_InvalidZPR32SXTW64:
4343 case Match_InvalidZPR64UXTW8:
4344 case Match_InvalidZPR64SXTW8:
4345 case Match_InvalidZPR64UXTW16:
4346 case Match_InvalidZPR64SXTW16:
4347 case Match_InvalidZPR64UXTW32:
4348 case Match_InvalidZPR64SXTW32:
4349 case Match_InvalidZPR64UXTW64:
4350 case Match_InvalidZPR64SXTW64:
4351 case Match_InvalidZPR64LSL8:
4352 case Match_InvalidZPR64LSL16:
4353 case Match_InvalidZPR64LSL32:
4354 case Match_InvalidZPR64LSL64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004355 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004356 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004357 case Match_InvalidSVEPredicateBReg:
4358 case Match_InvalidSVEPredicateHReg:
4359 case Match_InvalidSVEPredicateSReg:
4360 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004361 case Match_InvalidSVEPredicate3bAnyReg:
4362 case Match_InvalidSVEPredicate3bBReg:
4363 case Match_InvalidSVEPredicate3bHReg:
4364 case Match_InvalidSVEPredicate3bSReg:
4365 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004366 case Match_MSR:
4367 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004368 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004369 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004370 // Any time we get here, there's nothing fancy to do. Just get the
4371 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004372 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004373 if (ErrorLoc == SMLoc())
4374 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004375 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004376 }
4377 }
4378
4379 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004380}
4381
4382/// ParseDirective parses the arm specific directives
4383bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004384 const MCObjectFileInfo::Environment Format =
4385 getContext().getObjectFileInfo()->getObjectFileType();
4386 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4387 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004388
Tim Northover3b0846e2014-05-24 12:50:23 +00004389 StringRef IDVal = DirectiveID.getIdentifier();
4390 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004391 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004392 parseDirectiveArch(Loc);
4393 else if (IDVal == ".cpu")
4394 parseDirectiveCPU(Loc);
4395 else if (IDVal == ".hword")
4396 parseDirectiveWord(2, Loc);
4397 else if (IDVal == ".word")
4398 parseDirectiveWord(4, Loc);
4399 else if (IDVal == ".xword")
4400 parseDirectiveWord(8, Loc);
4401 else if (IDVal == ".tlsdesccall")
4402 parseDirectiveTLSDescCall(Loc);
4403 else if (IDVal == ".ltorg" || IDVal == ".pool")
4404 parseDirectiveLtorg(Loc);
4405 else if (IDVal == ".unreq")
4406 parseDirectiveUnreq(Loc);
4407 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004408 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004409 parseDirectiveInst(Loc);
4410 else
4411 return true;
4412 } else if (IDVal == MCLOHDirectiveName())
4413 parseDirectiveLOH(IDVal, Loc);
4414 else
4415 return true;
4416 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004417}
4418
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004419static const struct {
4420 const char *Name;
4421 const FeatureBitset Features;
4422} ExtensionMap[] = {
4423 { "crc", {AArch64::FeatureCRC} },
4424 { "crypto", {AArch64::FeatureCrypto} },
4425 { "fp", {AArch64::FeatureFPARMv8} },
4426 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004427 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004428 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004429
4430 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004431 { "pan", {} },
4432 { "lor", {} },
4433 { "rdma", {} },
4434 { "profile", {} },
4435};
4436
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004437/// parseDirectiveArch
4438/// ::= .arch token
4439bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4440 SMLoc ArchLoc = getLoc();
4441
4442 StringRef Arch, ExtensionString;
4443 std::tie(Arch, ExtensionString) =
4444 getParser().parseStringToEndOfStatement().trim().split('+');
4445
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004446 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4447 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004448 return Error(ArchLoc, "unknown arch name");
4449
4450 if (parseToken(AsmToken::EndOfStatement))
4451 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004452
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004453 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004454 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004455 AArch64::getArchFeatures(ID, AArch64Features);
4456 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4457 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004458
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004459 MCSubtargetInfo &STI = copySTI();
4460 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4461 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4462
4463 SmallVector<StringRef, 4> RequestedExtensions;
4464 if (!ExtensionString.empty())
4465 ExtensionString.split(RequestedExtensions, '+');
4466
4467 FeatureBitset Features = STI.getFeatureBits();
4468 for (auto Name : RequestedExtensions) {
4469 bool EnableFeature = true;
4470
4471 if (Name.startswith_lower("no")) {
4472 EnableFeature = false;
4473 Name = Name.substr(2);
4474 }
4475
4476 for (const auto &Extension : ExtensionMap) {
4477 if (Extension.Name != Name)
4478 continue;
4479
4480 if (Extension.Features.none())
4481 report_fatal_error("unsupported architectural extension: " + Name);
4482
4483 FeatureBitset ToggleFeatures = EnableFeature
4484 ? (~Features & Extension.Features)
4485 : ( Features & Extension.Features);
4486 uint64_t Features =
4487 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4488 setAvailableFeatures(Features);
4489 break;
4490 }
4491 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004492 return false;
4493}
4494
Tim Northover8b96c7e2017-05-15 19:42:15 +00004495static SMLoc incrementLoc(SMLoc L, int Offset) {
4496 return SMLoc::getFromPointer(L.getPointer() + Offset);
4497}
4498
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004499/// parseDirectiveCPU
4500/// ::= .cpu id
4501bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004502 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004503
4504 StringRef CPU, ExtensionString;
4505 std::tie(CPU, ExtensionString) =
4506 getParser().parseStringToEndOfStatement().trim().split('+');
4507
Nirav Davee833c6c2016-11-08 18:31:04 +00004508 if (parseToken(AsmToken::EndOfStatement))
4509 return true;
4510
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004511 SmallVector<StringRef, 4> RequestedExtensions;
4512 if (!ExtensionString.empty())
4513 ExtensionString.split(RequestedExtensions, '+');
4514
4515 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4516 // once that is tablegen'ed
4517 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004518 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004519 return false;
4520 }
4521
4522 MCSubtargetInfo &STI = copySTI();
4523 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004524 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004525
4526 FeatureBitset Features = STI.getFeatureBits();
4527 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004528 // Advance source location past '+'.
4529 CurLoc = incrementLoc(CurLoc, 1);
4530
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004531 bool EnableFeature = true;
4532
4533 if (Name.startswith_lower("no")) {
4534 EnableFeature = false;
4535 Name = Name.substr(2);
4536 }
4537
Tim Northover8b96c7e2017-05-15 19:42:15 +00004538 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004539 for (const auto &Extension : ExtensionMap) {
4540 if (Extension.Name != Name)
4541 continue;
4542
4543 if (Extension.Features.none())
4544 report_fatal_error("unsupported architectural extension: " + Name);
4545
4546 FeatureBitset ToggleFeatures = EnableFeature
4547 ? (~Features & Extension.Features)
4548 : ( Features & Extension.Features);
4549 uint64_t Features =
4550 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4551 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004552 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004553
4554 break;
4555 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004556
4557 if (!FoundExtension)
4558 Error(CurLoc, "unsupported architectural extension");
4559
4560 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004561 }
4562 return false;
4563}
4564
Tim Northover3b0846e2014-05-24 12:50:23 +00004565/// parseDirectiveWord
4566/// ::= .word [ expression (, expression)* ]
4567bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004568 auto parseOp = [&]() -> bool {
4569 const MCExpr *Value;
4570 if (getParser().parseExpression(Value))
4571 return true;
4572 getParser().getStreamer().EmitValue(Value, Size, L);
4573 return false;
4574 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004575
Nirav Davee833c6c2016-11-08 18:31:04 +00004576 if (parseMany(parseOp))
4577 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004578 return false;
4579}
4580
Chad Rosierdcd2a302014-10-22 20:35:57 +00004581/// parseDirectiveInst
4582/// ::= .inst opcode [, ...]
4583bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004584 if (getLexer().is(AsmToken::EndOfStatement))
4585 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004586
Nirav Davee833c6c2016-11-08 18:31:04 +00004587 auto parseOp = [&]() -> bool {
4588 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004589 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004590 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4591 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004592 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004593 if (check(!Value, L, "expected constant expression"))
4594 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004595 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004596 return false;
4597 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004598
Nirav Davee833c6c2016-11-08 18:31:04 +00004599 if (parseMany(parseOp))
4600 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004601 return false;
4602}
4603
Tim Northover3b0846e2014-05-24 12:50:23 +00004604// parseDirectiveTLSDescCall:
4605// ::= .tlsdesccall symbol
4606bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4607 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004608 if (check(getParser().parseIdentifier(Name), L,
4609 "expected symbol after directive") ||
4610 parseToken(AsmToken::EndOfStatement))
4611 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004612
Jim Grosbach6f482002015-05-18 18:43:14 +00004613 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004614 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4615 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004616
4617 MCInst Inst;
4618 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004619 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004620
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004621 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004622 return false;
4623}
4624
4625/// ::= .loh <lohName | lohId> label1, ..., labelN
4626/// The number of arguments depends on the loh identifier.
4627bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004628 MCLOHType Kind;
4629 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4630 if (getParser().getTok().isNot(AsmToken::Integer))
4631 return TokError("expected an identifier or a number in directive");
4632 // We successfully get a numeric value for the identifier.
4633 // Check if it is valid.
4634 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004635 if (Id <= -1U && !isValidMCLOHType(Id))
4636 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004637 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004638 } else {
4639 StringRef Name = getTok().getIdentifier();
4640 // We successfully parse an identifier.
4641 // Check if it is a recognized one.
4642 int Id = MCLOHNameToId(Name);
4643
4644 if (Id == -1)
4645 return TokError("invalid identifier in directive");
4646 Kind = (MCLOHType)Id;
4647 }
4648 // Consume the identifier.
4649 Lex();
4650 // Get the number of arguments of this LOH.
4651 int NbArgs = MCLOHIdToNbArgs(Kind);
4652
4653 assert(NbArgs != -1 && "Invalid number of arguments");
4654
4655 SmallVector<MCSymbol *, 3> Args;
4656 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4657 StringRef Name;
4658 if (getParser().parseIdentifier(Name))
4659 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004660 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004661
4662 if (Idx + 1 == NbArgs)
4663 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004664 if (parseToken(AsmToken::Comma,
4665 "unexpected token in '" + Twine(IDVal) + "' directive"))
4666 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004667 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004668 if (parseToken(AsmToken::EndOfStatement,
4669 "unexpected token in '" + Twine(IDVal) + "' directive"))
4670 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004671
4672 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4673 return false;
4674}
4675
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004676/// parseDirectiveLtorg
4677/// ::= .ltorg | .pool
4678bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004679 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4680 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004681 getTargetStreamer().emitCurrentConstantPool();
4682 return false;
4683}
4684
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004685/// parseDirectiveReq
4686/// ::= name .req registername
4687bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004688 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004689 Parser.Lex(); // Eat the '.req' token.
4690 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00004691 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00004692 unsigned RegNum;
4693 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004694
Sander de Smalen50d87022018-04-19 07:35:08 +00004695 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004696 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004697 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004698 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00004699
Sander de Smalen50d87022018-04-19 07:35:08 +00004700 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00004701 return true;
4702
Sander de Smalen50d87022018-04-19 07:35:08 +00004703 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004704 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004705 }
4706
Sander de Smalen50d87022018-04-19 07:35:08 +00004707 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004708 StringRef Kind;
4709 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004710 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00004711 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004712
Sander de Smalen50d87022018-04-19 07:35:08 +00004713 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00004714 return true;
4715
Sander de Smalen50d87022018-04-19 07:35:08 +00004716 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00004717 return Error(SRegLoc,
4718 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004719 }
4720
Sander de Smalen50d87022018-04-19 07:35:08 +00004721 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00004722 StringRef Kind;
4723 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00004724 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004725
Sander de Smalen50d87022018-04-19 07:35:08 +00004726 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00004727 return true;
4728
Sander de Smalen50d87022018-04-19 07:35:08 +00004729 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00004730 return Error(SRegLoc,
4731 "sve predicate register without type specifier expected");
4732 }
4733
Sander de Smalen50d87022018-04-19 07:35:08 +00004734 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00004735 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004736
4737 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004738 if (parseToken(AsmToken::EndOfStatement,
4739 "unexpected input in .req directive"))
4740 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004741
Sander de Smalen8e607342017-11-15 15:44:43 +00004742 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004743 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004744 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4745
Nirav Dave2364748a2016-09-16 18:30:20 +00004746 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004747}
4748
4749/// parseDirectiveUneq
4750/// ::= .unreq registername
4751bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004752 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004753 if (getTok().isNot(AsmToken::Identifier))
4754 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004755 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4756 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004757 if (parseToken(AsmToken::EndOfStatement))
4758 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004759 return false;
4760}
4761
Tim Northover3b0846e2014-05-24 12:50:23 +00004762bool
4763AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4764 AArch64MCExpr::VariantKind &ELFRefKind,
4765 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4766 int64_t &Addend) {
4767 ELFRefKind = AArch64MCExpr::VK_INVALID;
4768 DarwinRefKind = MCSymbolRefExpr::VK_None;
4769 Addend = 0;
4770
4771 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4772 ELFRefKind = AE->getKind();
4773 Expr = AE->getSubExpr();
4774 }
4775
4776 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4777 if (SE) {
4778 // It's a simple symbol reference with no addend.
4779 DarwinRefKind = SE->getKind();
4780 return true;
4781 }
4782
4783 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4784 if (!BE)
4785 return false;
4786
4787 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4788 if (!SE)
4789 return false;
4790 DarwinRefKind = SE->getKind();
4791
4792 if (BE->getOpcode() != MCBinaryExpr::Add &&
4793 BE->getOpcode() != MCBinaryExpr::Sub)
4794 return false;
4795
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004796 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004797 // on here than we can deal with.
4798 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4799 if (!AddendExpr)
4800 return false;
4801
4802 Addend = AddendExpr->getValue();
4803 if (BE->getOpcode() == MCBinaryExpr::Sub)
4804 Addend = -Addend;
4805
4806 // It's some symbol reference + a constant addend, but really
4807 // shouldn't use both Darwin and ELF syntax.
4808 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4809 DarwinRefKind == MCSymbolRefExpr::VK_None;
4810}
4811
4812/// Force static initialization.
4813extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004814 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4815 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4816 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004817}
4818
4819#define GET_REGISTER_MATCHER
4820#define GET_SUBTARGET_FEATURE_NAME
4821#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004822#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004823#include "AArch64GenAsmMatcher.inc"
4824
4825// Define this matcher function after the auto-generated include so we
4826// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004827unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004828 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004829 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004830 // If the kind is a token for a literal immediate, check if our asm
4831 // operand matches. This is for InstAliases which have a fixed-value
4832 // immediate in the syntax.
4833 int64_t ExpectedVal;
4834 switch (Kind) {
4835 default:
4836 return Match_InvalidOperand;
4837 case MCK__35_0:
4838 ExpectedVal = 0;
4839 break;
4840 case MCK__35_1:
4841 ExpectedVal = 1;
4842 break;
4843 case MCK__35_12:
4844 ExpectedVal = 12;
4845 break;
4846 case MCK__35_16:
4847 ExpectedVal = 16;
4848 break;
4849 case MCK__35_2:
4850 ExpectedVal = 2;
4851 break;
4852 case MCK__35_24:
4853 ExpectedVal = 24;
4854 break;
4855 case MCK__35_3:
4856 ExpectedVal = 3;
4857 break;
4858 case MCK__35_32:
4859 ExpectedVal = 32;
4860 break;
4861 case MCK__35_4:
4862 ExpectedVal = 4;
4863 break;
4864 case MCK__35_48:
4865 ExpectedVal = 48;
4866 break;
4867 case MCK__35_6:
4868 ExpectedVal = 6;
4869 break;
4870 case MCK__35_64:
4871 ExpectedVal = 64;
4872 break;
4873 case MCK__35_8:
4874 ExpectedVal = 8;
4875 break;
4876 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004877 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004878 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004879 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004880 if (!CE)
4881 return Match_InvalidOperand;
4882 if (CE->getValue() == ExpectedVal)
4883 return Match_Success;
4884 return Match_InvalidOperand;
4885}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004886
Alex Bradbury58eba092016-11-01 16:32:05 +00004887OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004888AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4889
4890 SMLoc S = getLoc();
4891
4892 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4893 Error(S, "expected register");
4894 return MatchOperand_ParseFail;
4895 }
4896
Sander de Smalen50d87022018-04-19 07:35:08 +00004897 unsigned FirstReg;
4898 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
4899 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004900 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00004901
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004902 const MCRegisterClass &WRegClass =
4903 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4904 const MCRegisterClass &XRegClass =
4905 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4906
4907 bool isXReg = XRegClass.contains(FirstReg),
4908 isWReg = WRegClass.contains(FirstReg);
4909 if (!isXReg && !isWReg) {
4910 Error(S, "expected first even register of a "
4911 "consecutive same-size even/odd register pair");
4912 return MatchOperand_ParseFail;
4913 }
4914
4915 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4916 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4917
4918 if (FirstEncoding & 0x1) {
4919 Error(S, "expected first even register of a "
4920 "consecutive same-size even/odd register pair");
4921 return MatchOperand_ParseFail;
4922 }
4923
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004924 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00004925 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004926 return MatchOperand_ParseFail;
4927 }
4928 // Eat the comma
4929 getParser().Lex();
4930
4931 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00004932 unsigned SecondReg;
4933 Res = tryParseScalarRegister(SecondReg);
4934 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004935 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004936
Eugene Zelenko049b0172017-01-06 00:30:53 +00004937 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004938 (isXReg && !XRegClass.contains(SecondReg)) ||
4939 (isWReg && !WRegClass.contains(SecondReg))) {
4940 Error(E,"expected second odd register of a "
4941 "consecutive same-size even/odd register pair");
4942 return MatchOperand_ParseFail;
4943 }
Joel Jones504bf332016-10-24 13:37:13 +00004944
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004945 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004946 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004947 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4948 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4949 } else {
4950 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4951 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4952 }
4953
Florian Hahnc4422242017-11-07 13:07:50 +00004954 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4955 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004956
4957 return MatchOperand_Success;
4958}
Florian Hahn91f11e52017-11-07 16:45:48 +00004959
Sander de Smaleneb896b12018-04-25 09:26:47 +00004960template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00004961OperandMatchResultTy
4962AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004963 const SMLoc S = getLoc();
4964 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00004965 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00004966 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004967
Sander de Smalen8e607342017-11-15 15:44:43 +00004968 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004969 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004970
4971 if (Res != MatchOperand_Success)
4972 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004973
4974 if (ParseSuffix && Kind.empty())
4975 return MatchOperand_NoMatch;
4976
Sander de Smalen73937b72018-04-11 07:36:10 +00004977 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
4978 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00004979 return MatchOperand_NoMatch;
4980
Sander de Smalen73937b72018-04-11 07:36:10 +00004981 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00004982
4983 // No shift/extend is the default.
4984 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
4985 Operands.push_back(AArch64Operand::CreateVectorReg(
4986 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
4987
4988 return MatchOperand_Success;
4989 }
4990
4991 // Eat the comma
4992 getParser().Lex();
4993
4994 // Match the shift
4995 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
4996 Res = tryParseOptionalShiftExtend(ExtOpnd);
4997 if (Res != MatchOperand_Success)
4998 return Res;
4999
5000 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005001 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005002 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5003 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5004 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005005
5006 return MatchOperand_Success;
5007}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005008
5009OperandMatchResultTy
5010AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5011 MCAsmParser &Parser = getParser();
5012
5013 SMLoc SS = getLoc();
5014 const AsmToken &TokE = Parser.getTok();
5015 bool IsHash = TokE.is(AsmToken::Hash);
5016
5017 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5018 return MatchOperand_NoMatch;
5019
5020 int64_t Pattern;
5021 if (IsHash) {
5022 Parser.Lex(); // Eat hash
5023
5024 // Parse the immediate operand.
5025 const MCExpr *ImmVal;
5026 SS = getLoc();
5027 if (Parser.parseExpression(ImmVal))
5028 return MatchOperand_ParseFail;
5029
5030 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5031 if (!MCE)
5032 return MatchOperand_ParseFail;
5033
5034 Pattern = MCE->getValue();
5035 } else {
5036 // Parse the pattern
5037 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5038 if (!Pat)
5039 return MatchOperand_NoMatch;
5040
5041 Parser.Lex();
5042 Pattern = Pat->Encoding;
5043 assert(Pattern >= 0 && Pattern < 32);
5044 }
5045
5046 Operands.push_back(
5047 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5048 SS, getLoc(), getContext()));
5049
5050 return MatchOperand_Success;
5051}