blob: d21881fd99c9e88e756d0f94f6684abe758a4805 [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/AArch64AddressingModes.h"
11#include "MCTargetDesc/AArch64MCExpr.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000012#include "MCTargetDesc/AArch64MCTargetDesc.h"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000013#include "MCTargetDesc/AArch64TargetStreamer.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000014#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000015#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000016#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000017#include "llvm/ADT/ArrayRef.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000018#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "llvm/ADT/SmallVector.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000020#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000021#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000023#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000025#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000028#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000029#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000030#include "llvm/MC/MCParser/MCAsmLexer.h"
31#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000032#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000033#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000034#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000035#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSubtargetInfo.h"
38#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000039#include "llvm/MC/MCTargetOptions.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000043#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000044#include "llvm/Support/MathExtras.h"
45#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000046#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000047#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000049#include <cassert>
50#include <cctype>
51#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000052#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000053#include <string>
54#include <tuple>
55#include <utility>
56#include <vector>
57
Tim Northover3b0846e2014-05-24 12:50:23 +000058using namespace llvm;
59
60namespace {
61
Sander de Smalencd6be962017-12-20 11:02:42 +000062enum class RegKind {
63 Scalar,
64 NeonVector,
65 SVEDataVector,
66 SVEPredicateVector
67};
Florian Hahnc4422242017-11-07 13:07:50 +000068
Tim Northover3b0846e2014-05-24 12:50:23 +000069class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000070private:
71 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000072
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000073 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000074 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000075
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000076 AArch64TargetStreamer &getTargetStreamer() {
77 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
78 return static_cast<AArch64TargetStreamer &>(TS);
79 }
80
Rafael Espindola961d4692014-11-11 05:18:41 +000081 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000082
83 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +000084 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +000085 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
86 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +000087 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +000088 int tryParseRegister();
Tim Northover3b0846e2014-05-24 12:50:23 +000089 bool parseRegister(OperandVector &Operands);
90 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
Sander de Smalenc88f9a12018-04-11 14:10:37 +000091 bool parseNeonVectorList(OperandVector &Operands);
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 Smalen73937b72018-04-11 07:36:10 +0000123 OperandMatchResultTy tryParseVectorRegister(int &Reg, StringRef &Kind,
124 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000125 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
126 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
127 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
128 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
129 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
130 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000131 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000132 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
133 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
134 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
135 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
136 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000137 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000138 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000139 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Florian Hahn91f11e52017-11-07 16:45:48 +0000140 template <bool ParseSuffix>
141 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000142 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000143 template <RegKind VectorKind>
144 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
145 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000146 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000147
148public:
149 enum AArch64MatchResultTy {
150 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
151#define GET_OPERAND_DIAGNOSTIC_TYPES
152#include "AArch64GenAsmMatcher.inc"
153 };
Joel Jones504bf332016-10-24 13:37:13 +0000154 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000155
Akira Hatanakab11ef082015-11-14 06:35:56 +0000156 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000157 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000158 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000159 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000160 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000161 MCStreamer &S = getParser().getStreamer();
162 if (S.getTargetStreamer() == nullptr)
163 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000164
165 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000166 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000167 }
168
169 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
170 SMLoc NameLoc, OperandVector &Operands) override;
171 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
172 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000173 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000174 unsigned Kind) override;
175
176 static bool classifySymbolRef(const MCExpr *Expr,
177 AArch64MCExpr::VariantKind &ELFRefKind,
178 MCSymbolRefExpr::VariantKind &DarwinRefKind,
179 int64_t &Addend);
180};
Tim Northover3b0846e2014-05-24 12:50:23 +0000181
182/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
183/// instruction.
184class AArch64Operand : public MCParsedAsmOperand {
185private:
186 enum KindTy {
187 k_Immediate,
188 k_ShiftedImm,
189 k_CondCode,
190 k_Register,
191 k_VectorList,
192 k_VectorIndex,
193 k_Token,
194 k_SysReg,
195 k_SysCR,
196 k_Prefetch,
197 k_ShiftExtend,
198 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000199 k_Barrier,
200 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000201 } Kind;
202
203 SMLoc StartLoc, EndLoc;
204
205 struct TokOp {
206 const char *Data;
207 unsigned Length;
208 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
209 };
210
211 struct RegOp {
212 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000213 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000214
215 int ElementWidth;
Tim Northover3b0846e2014-05-24 12:50:23 +0000216 };
217
218 struct VectorListOp {
219 unsigned RegNum;
220 unsigned Count;
221 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000222 unsigned ElementWidth;
223 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000224 };
225
226 struct VectorIndexOp {
227 unsigned Val;
228 };
229
230 struct ImmOp {
231 const MCExpr *Val;
232 };
233
234 struct ShiftedImmOp {
235 const MCExpr *Val;
236 unsigned ShiftAmount;
237 };
238
239 struct CondCodeOp {
240 AArch64CC::CondCode Code;
241 };
242
243 struct FPImmOp {
244 unsigned Val; // Encoded 8-bit representation.
245 };
246
247 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000248 const char *Data;
249 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000250 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000251 };
252
253 struct SysRegOp {
254 const char *Data;
255 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000256 uint32_t MRSReg;
257 uint32_t MSRReg;
258 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000259 };
260
261 struct SysCRImmOp {
262 unsigned Val;
263 };
264
265 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000266 const char *Data;
267 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000268 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000269 };
270
Oliver Stannarda34e4702015-12-01 10:48:51 +0000271 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000272 const char *Data;
273 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000274 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000275 };
276
Tim Northover3b0846e2014-05-24 12:50:23 +0000277 struct ShiftExtendOp {
278 AArch64_AM::ShiftExtendType Type;
279 unsigned Amount;
280 bool HasExplicitAmount;
281 };
282
283 struct ExtendOp {
284 unsigned Val;
285 };
286
287 union {
288 struct TokOp Tok;
289 struct RegOp Reg;
290 struct VectorListOp VectorList;
291 struct VectorIndexOp VectorIndex;
292 struct ImmOp Imm;
293 struct ShiftedImmOp ShiftedImm;
294 struct CondCodeOp CondCode;
295 struct FPImmOp FPImm;
296 struct BarrierOp Barrier;
297 struct SysRegOp SysReg;
298 struct SysCRImmOp SysCRImm;
299 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000300 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000301 struct ShiftExtendOp ShiftExtend;
302 };
303
304 // Keep the MCContext around as the MCExprs may need manipulated during
305 // the add<>Operands() calls.
306 MCContext &Ctx;
307
David Blaikie960ea3f2014-06-08 16:18:35 +0000308public:
David Blaikie9f380a32015-03-16 18:06:57 +0000309 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000310
Tim Northover3b0846e2014-05-24 12:50:23 +0000311 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
312 Kind = o.Kind;
313 StartLoc = o.StartLoc;
314 EndLoc = o.EndLoc;
315 switch (Kind) {
316 case k_Token:
317 Tok = o.Tok;
318 break;
319 case k_Immediate:
320 Imm = o.Imm;
321 break;
322 case k_ShiftedImm:
323 ShiftedImm = o.ShiftedImm;
324 break;
325 case k_CondCode:
326 CondCode = o.CondCode;
327 break;
328 case k_FPImm:
329 FPImm = o.FPImm;
330 break;
331 case k_Barrier:
332 Barrier = o.Barrier;
333 break;
334 case k_Register:
335 Reg = o.Reg;
336 break;
337 case k_VectorList:
338 VectorList = o.VectorList;
339 break;
340 case k_VectorIndex:
341 VectorIndex = o.VectorIndex;
342 break;
343 case k_SysReg:
344 SysReg = o.SysReg;
345 break;
346 case k_SysCR:
347 SysCRImm = o.SysCRImm;
348 break;
349 case k_Prefetch:
350 Prefetch = o.Prefetch;
351 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000352 case k_PSBHint:
353 PSBHint = o.PSBHint;
354 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000355 case k_ShiftExtend:
356 ShiftExtend = o.ShiftExtend;
357 break;
358 }
359 }
360
361 /// getStartLoc - Get the location of the first token of this operand.
362 SMLoc getStartLoc() const override { return StartLoc; }
363 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000364 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000365
366 StringRef getToken() const {
367 assert(Kind == k_Token && "Invalid access!");
368 return StringRef(Tok.Data, Tok.Length);
369 }
370
371 bool isTokenSuffix() const {
372 assert(Kind == k_Token && "Invalid access!");
373 return Tok.IsSuffix;
374 }
375
376 const MCExpr *getImm() const {
377 assert(Kind == k_Immediate && "Invalid access!");
378 return Imm.Val;
379 }
380
381 const MCExpr *getShiftedImmVal() const {
382 assert(Kind == k_ShiftedImm && "Invalid access!");
383 return ShiftedImm.Val;
384 }
385
386 unsigned getShiftedImmShift() const {
387 assert(Kind == k_ShiftedImm && "Invalid access!");
388 return ShiftedImm.ShiftAmount;
389 }
390
391 AArch64CC::CondCode getCondCode() const {
392 assert(Kind == k_CondCode && "Invalid access!");
393 return CondCode.Code;
394 }
395
396 unsigned getFPImm() const {
397 assert(Kind == k_FPImm && "Invalid access!");
398 return FPImm.Val;
399 }
400
401 unsigned getBarrier() const {
402 assert(Kind == k_Barrier && "Invalid access!");
403 return Barrier.Val;
404 }
405
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000406 StringRef getBarrierName() const {
407 assert(Kind == k_Barrier && "Invalid access!");
408 return StringRef(Barrier.Data, Barrier.Length);
409 }
410
Tim Northover3b0846e2014-05-24 12:50:23 +0000411 unsigned getReg() const override {
412 assert(Kind == k_Register && "Invalid access!");
413 return Reg.RegNum;
414 }
415
416 unsigned getVectorListStart() const {
417 assert(Kind == k_VectorList && "Invalid access!");
418 return VectorList.RegNum;
419 }
420
421 unsigned getVectorListCount() const {
422 assert(Kind == k_VectorList && "Invalid access!");
423 return VectorList.Count;
424 }
425
426 unsigned getVectorIndex() const {
427 assert(Kind == k_VectorIndex && "Invalid access!");
428 return VectorIndex.Val;
429 }
430
431 StringRef getSysReg() const {
432 assert(Kind == k_SysReg && "Invalid access!");
433 return StringRef(SysReg.Data, SysReg.Length);
434 }
435
Tim Northover3b0846e2014-05-24 12:50:23 +0000436 unsigned getSysCR() const {
437 assert(Kind == k_SysCR && "Invalid access!");
438 return SysCRImm.Val;
439 }
440
441 unsigned getPrefetch() const {
442 assert(Kind == k_Prefetch && "Invalid access!");
443 return Prefetch.Val;
444 }
445
Oliver Stannarda34e4702015-12-01 10:48:51 +0000446 unsigned getPSBHint() const {
447 assert(Kind == k_PSBHint && "Invalid access!");
448 return PSBHint.Val;
449 }
450
451 StringRef getPSBHintName() const {
452 assert(Kind == k_PSBHint && "Invalid access!");
453 return StringRef(PSBHint.Data, PSBHint.Length);
454 }
455
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000456 StringRef getPrefetchName() const {
457 assert(Kind == k_Prefetch && "Invalid access!");
458 return StringRef(Prefetch.Data, Prefetch.Length);
459 }
460
Tim Northover3b0846e2014-05-24 12:50:23 +0000461 AArch64_AM::ShiftExtendType getShiftExtendType() const {
462 assert(Kind == k_ShiftExtend && "Invalid access!");
463 return ShiftExtend.Type;
464 }
465
466 unsigned getShiftExtendAmount() const {
467 assert(Kind == k_ShiftExtend && "Invalid access!");
468 return ShiftExtend.Amount;
469 }
470
471 bool hasShiftExtendAmount() const {
472 assert(Kind == k_ShiftExtend && "Invalid access!");
473 return ShiftExtend.HasExplicitAmount;
474 }
475
476 bool isImm() const override { return Kind == k_Immediate; }
477 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000478
479 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
480
481 template <int Bits, int Scale> bool isSImmScaled() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000482 if (!isImm())
483 return false;
484 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
485 if (!MCE)
486 return false;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000487
488 int64_t Shift = Bits - 1;
489 int64_t MinVal = (int64_t(1) << Shift) * -Scale;
490 int64_t MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
491
Tim Northover3b0846e2014-05-24 12:50:23 +0000492 int64_t Val = MCE->getValue();
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000493 return Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0;
Tim Northover3b0846e2014-05-24 12:50:23 +0000494 }
495
Sander de Smalen245e0e62018-01-22 10:46:00 +0000496 bool isSVEPattern() const {
497 if (!isImm())
498 return false;
499 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
500 if (!MCE)
501 return false;
502 int64_t Val = MCE->getValue();
503 return Val >= 0 && Val < 32;
504 }
505
Tim Northover3b0846e2014-05-24 12:50:23 +0000506 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
507 AArch64MCExpr::VariantKind ELFRefKind;
508 MCSymbolRefExpr::VariantKind DarwinRefKind;
509 int64_t Addend;
510 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
511 Addend)) {
512 // If we don't understand the expression, assume the best and
513 // let the fixup and relocation code deal with it.
514 return true;
515 }
516
517 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
518 ELFRefKind == AArch64MCExpr::VK_LO12 ||
519 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
520 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
521 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
522 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
523 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
524 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000525 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
526 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
527 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000528 // Note that we don't range-check the addend. It's adjusted modulo page
529 // size when converted, so there is no "out of range" condition when using
530 // @pageoff.
531 return Addend >= 0 && (Addend % Scale) == 0;
532 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
533 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
534 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
535 return Addend == 0;
536 }
537
538 return false;
539 }
540
541 template <int Scale> bool isUImm12Offset() const {
542 if (!isImm())
543 return false;
544
545 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
546 if (!MCE)
547 return isSymbolicUImm12Offset(getImm(), Scale);
548
549 int64_t Val = MCE->getValue();
550 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
551 }
552
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000553 template <int N, int M>
554 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000555 if (!isImm())
556 return false;
557 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
558 if (!MCE)
559 return false;
560 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000561 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000562 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000563
Sander de Smalena1c259c2018-01-29 13:05:38 +0000564 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
565 // a logical immediate can always be represented when inverted.
566 template <typename T>
567 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000568 if (!isImm())
569 return false;
570 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
571 if (!MCE)
572 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000573
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000574 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000575 int64_t SVal = typename std::make_signed<T>::type(Val);
576 int64_t UVal = typename std::make_unsigned<T>::type(Val);
577 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000578 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000579
Sander de Smalena1c259c2018-01-29 13:05:38 +0000580 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000581 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000582
Tim Northover3b0846e2014-05-24 12:50:23 +0000583 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000584
Tim Northover3b0846e2014-05-24 12:50:23 +0000585 bool isAddSubImm() const {
586 if (!isShiftedImm() && !isImm())
587 return false;
588
589 const MCExpr *Expr;
590
591 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
592 if (isShiftedImm()) {
593 unsigned Shift = ShiftedImm.ShiftAmount;
594 Expr = ShiftedImm.Val;
595 if (Shift != 0 && Shift != 12)
596 return false;
597 } else {
598 Expr = getImm();
599 }
600
601 AArch64MCExpr::VariantKind ELFRefKind;
602 MCSymbolRefExpr::VariantKind DarwinRefKind;
603 int64_t Addend;
604 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
605 DarwinRefKind, Addend)) {
606 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
607 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
608 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
609 || ELFRefKind == AArch64MCExpr::VK_LO12
610 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
611 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
612 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
613 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
614 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
615 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000616 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
617 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
618 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000619 }
620
Diana Picusc93518d2016-10-11 09:17:47 +0000621 // If it's a constant, it should be a real immediate in range:
622 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
623 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
624
625 // If it's an expression, we hope for the best and let the fixup/relocation
626 // code deal with it.
627 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000628 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000629
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000630 bool isAddSubImmNeg() const {
631 if (!isShiftedImm() && !isImm())
632 return false;
633
634 const MCExpr *Expr;
635
636 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
637 if (isShiftedImm()) {
638 unsigned Shift = ShiftedImm.ShiftAmount;
639 Expr = ShiftedImm.Val;
640 if (Shift != 0 && Shift != 12)
641 return false;
642 } else
643 Expr = getImm();
644
645 // Otherwise it should be a real negative immediate in range:
646 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
647 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
648 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000649
Tim Northover3b0846e2014-05-24 12:50:23 +0000650 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000651
Tim Northover3b0846e2014-05-24 12:50:23 +0000652 bool isSIMDImmType10() const {
653 if (!isImm())
654 return false;
655 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
656 if (!MCE)
657 return false;
658 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
659 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000660
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000661 template<int N>
662 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000663 if (!isImm())
664 return false;
665 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
666 if (!MCE)
667 return true;
668 int64_t Val = MCE->getValue();
669 if (Val & 0x3)
670 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000671 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
672 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000673 }
674
675 bool
676 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
677 if (!isImm())
678 return false;
679
680 AArch64MCExpr::VariantKind ELFRefKind;
681 MCSymbolRefExpr::VariantKind DarwinRefKind;
682 int64_t Addend;
683 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
684 DarwinRefKind, Addend)) {
685 return false;
686 }
687 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
688 return false;
689
690 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
691 if (ELFRefKind == AllowedModifiers[i])
692 return Addend == 0;
693 }
694
695 return false;
696 }
697
698 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000699 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000700 }
701
702 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000703 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
704 AArch64MCExpr::VK_TPREL_G2,
705 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000706 }
707
708 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000709 return isMovWSymbol({
710 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000711 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
712 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000713 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000714 }
715
716 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000717 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
718 AArch64MCExpr::VK_TPREL_G0,
719 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000720 }
721
722 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000723 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000724 }
725
726 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000727 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000728 }
729
730 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000731 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
732 AArch64MCExpr::VK_TPREL_G1_NC,
733 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000734 }
735
736 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000737 return isMovWSymbol(
738 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
739 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000740 }
741
742 template<int RegWidth, int Shift>
743 bool isMOVZMovAlias() const {
744 if (!isImm()) return false;
745
746 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
747 if (!CE) return false;
748 uint64_t Value = CE->getValue();
749
Tim Northoverdaa1c012016-06-16 01:42:25 +0000750 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000751 }
752
753 template<int RegWidth, int Shift>
754 bool isMOVNMovAlias() const {
755 if (!isImm()) return false;
756
757 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
758 if (!CE) return false;
759 uint64_t Value = CE->getValue();
760
Tim Northoverdaa1c012016-06-16 01:42:25 +0000761 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000762 }
763
764 bool isFPImm() const { return Kind == k_FPImm; }
765 bool isBarrier() const { return Kind == k_Barrier; }
766 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000767
Tim Northover3b0846e2014-05-24 12:50:23 +0000768 bool isMRSSystemRegister() const {
769 if (!isSysReg()) return false;
770
Tim Northover7cd58932015-01-22 17:23:04 +0000771 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000772 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000773
Tim Northover3b0846e2014-05-24 12:50:23 +0000774 bool isMSRSystemRegister() const {
775 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000776 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000777 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000778
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000779 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000780 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000781 return (SysReg.PStateField == AArch64PState::PAN ||
782 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000783 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000784
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000785 bool isSystemPStateFieldWithImm0_15() const {
786 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000787 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000788 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000789
Florian Hahnc4422242017-11-07 13:07:50 +0000790 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000791 return Kind == k_Register;
792 }
793
794 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000795 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
796 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000797
Florian Hahnc4422242017-11-07 13:07:50 +0000798 bool isNeonVectorReg() const {
799 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
800 }
801
802 bool isNeonVectorRegLo() const {
803 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000804 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
805 Reg.RegNum);
806 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000807
Sander de Smalencd6be962017-12-20 11:02:42 +0000808 template <unsigned Class> bool isSVEVectorReg() const {
809 RegKind RK;
810 switch (Class) {
811 case AArch64::ZPRRegClassID:
812 RK = RegKind::SVEDataVector;
813 break;
814 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000815 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000816 RK = RegKind::SVEPredicateVector;
817 break;
818 default:
819 llvm_unreachable("Unsupport register class");
820 }
821
822 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000823 AArch64MCRegisterClasses[Class].contains(getReg());
824 }
825
Sander de Smalencd6be962017-12-20 11:02:42 +0000826 template <int ElementWidth, unsigned Class>
827 bool isSVEVectorRegOfWidth() const {
828 return isSVEVectorReg<Class>() &&
Sander de Smalen73937b72018-04-11 07:36:10 +0000829 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth);
Florian Hahn91f11e52017-11-07 16:45:48 +0000830 }
831
Tim Northover3b0846e2014-05-24 12:50:23 +0000832 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000833 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000834 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
835 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000836
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000837 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000838 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000839 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
840 Reg.RegNum);
841 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000842
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000843 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000844 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000845 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
846 Reg.RegNum);
847 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000848
849 bool isGPR64sp0() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000850 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000851 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
852 }
853
Sam Parker5f934642017-08-31 09:27:04 +0000854 template<int64_t Angle, int64_t Remainder>
855 bool isComplexRotation() const {
856 if (!isImm()) return false;
857
858 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
859 if (!CE) return false;
860 uint64_t Value = CE->getValue();
861
862 return (Value % Angle == Remainder && Value <= 270);
863 }
864
Tim Northover3b0846e2014-05-24 12:50:23 +0000865 /// Is this a vector list with the type implicit (presumably attached to the
866 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +0000867 template <RegKind VectorKind, unsigned NumRegs>
868 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000869 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +0000870 VectorList.NumElements == 0 &&
871 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000872 }
873
Sander de Smalen650234b2018-04-12 11:40:52 +0000874 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
875 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +0000876 bool isTypedVectorList() const {
877 if (Kind != k_VectorList)
878 return false;
879 if (VectorList.Count != NumRegs)
880 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +0000881 if (VectorList.RegisterKind != VectorKind)
882 return false;
883 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +0000884 return false;
885 return VectorList.NumElements == NumElements;
886 }
887
888 bool isVectorIndex1() const {
889 return Kind == k_VectorIndex && VectorIndex.Val == 1;
890 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000891
Tim Northover3b0846e2014-05-24 12:50:23 +0000892 bool isVectorIndexB() const {
893 return Kind == k_VectorIndex && VectorIndex.Val < 16;
894 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000895
Tim Northover3b0846e2014-05-24 12:50:23 +0000896 bool isVectorIndexH() const {
897 return Kind == k_VectorIndex && VectorIndex.Val < 8;
898 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000899
Tim Northover3b0846e2014-05-24 12:50:23 +0000900 bool isVectorIndexS() const {
901 return Kind == k_VectorIndex && VectorIndex.Val < 4;
902 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000903
Tim Northover3b0846e2014-05-24 12:50:23 +0000904 bool isVectorIndexD() const {
905 return Kind == k_VectorIndex && VectorIndex.Val < 2;
906 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000907
Tim Northover3b0846e2014-05-24 12:50:23 +0000908 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000909
Tim Northover3b0846e2014-05-24 12:50:23 +0000910 bool isTokenEqual(StringRef Str) const {
911 return Kind == k_Token && getToken() == Str;
912 }
913 bool isSysCR() const { return Kind == k_SysCR; }
914 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000915 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000916 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
917 bool isShifter() const {
918 if (!isShiftExtend())
919 return false;
920
921 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
922 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
923 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
924 ST == AArch64_AM::MSL);
925 }
926 bool isExtend() const {
927 if (!isShiftExtend())
928 return false;
929
930 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
931 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
932 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
933 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
934 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
935 ET == AArch64_AM::LSL) &&
936 getShiftExtendAmount() <= 4;
937 }
938
939 bool isExtend64() const {
940 if (!isExtend())
941 return false;
942 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
943 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
944 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
945 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000946
Tim Northover3b0846e2014-05-24 12:50:23 +0000947 bool isExtendLSL64() const {
948 if (!isExtend())
949 return false;
950 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
951 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
952 ET == AArch64_AM::LSL) &&
953 getShiftExtendAmount() <= 4;
954 }
955
956 template<int Width> bool isMemXExtend() const {
957 if (!isExtend())
958 return false;
959 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
960 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
961 (getShiftExtendAmount() == Log2_32(Width / 8) ||
962 getShiftExtendAmount() == 0);
963 }
964
965 template<int Width> bool isMemWExtend() const {
966 if (!isExtend())
967 return false;
968 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
969 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
970 (getShiftExtendAmount() == Log2_32(Width / 8) ||
971 getShiftExtendAmount() == 0);
972 }
973
974 template <unsigned width>
975 bool isArithmeticShifter() const {
976 if (!isShifter())
977 return false;
978
979 // An arithmetic shifter is LSL, LSR, or ASR.
980 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
981 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
982 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
983 }
984
985 template <unsigned width>
986 bool isLogicalShifter() const {
987 if (!isShifter())
988 return false;
989
990 // A logical shifter is LSL, LSR, ASR or ROR.
991 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
992 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
993 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
994 getShiftExtendAmount() < width;
995 }
996
997 bool isMovImm32Shifter() const {
998 if (!isShifter())
999 return false;
1000
1001 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1002 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1003 if (ST != AArch64_AM::LSL)
1004 return false;
1005 uint64_t Val = getShiftExtendAmount();
1006 return (Val == 0 || Val == 16);
1007 }
1008
1009 bool isMovImm64Shifter() const {
1010 if (!isShifter())
1011 return false;
1012
1013 // A MOVi shifter is LSL of 0 or 16.
1014 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1015 if (ST != AArch64_AM::LSL)
1016 return false;
1017 uint64_t Val = getShiftExtendAmount();
1018 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1019 }
1020
1021 bool isLogicalVecShifter() const {
1022 if (!isShifter())
1023 return false;
1024
1025 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1026 unsigned Shift = getShiftExtendAmount();
1027 return getShiftExtendType() == AArch64_AM::LSL &&
1028 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1029 }
1030
1031 bool isLogicalVecHalfWordShifter() const {
1032 if (!isLogicalVecShifter())
1033 return false;
1034
1035 // A logical vector shifter is a left shift by 0 or 8.
1036 unsigned Shift = getShiftExtendAmount();
1037 return getShiftExtendType() == AArch64_AM::LSL &&
1038 (Shift == 0 || Shift == 8);
1039 }
1040
1041 bool isMoveVecShifter() const {
1042 if (!isShiftExtend())
1043 return false;
1044
1045 // A logical vector shifter is a left shift by 8 or 16.
1046 unsigned Shift = getShiftExtendAmount();
1047 return getShiftExtendType() == AArch64_AM::MSL &&
1048 (Shift == 8 || Shift == 16);
1049 }
1050
1051 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1052 // to LDUR/STUR when the offset is not legal for the former but is for
1053 // the latter. As such, in addition to checking for being a legal unscaled
1054 // address, also check that it is not a legal scaled address. This avoids
1055 // ambiguity in the matcher.
1056 template<int Width>
1057 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001058 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001059 }
1060
1061 bool isAdrpLabel() const {
1062 // Validation was handled during parsing, so we just sanity check that
1063 // something didn't go haywire.
1064 if (!isImm())
1065 return false;
1066
1067 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1068 int64_t Val = CE->getValue();
1069 int64_t Min = - (4096 * (1LL << (21 - 1)));
1070 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1071 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1072 }
1073
1074 return true;
1075 }
1076
1077 bool isAdrLabel() const {
1078 // Validation was handled during parsing, so we just sanity check that
1079 // something didn't go haywire.
1080 if (!isImm())
1081 return false;
1082
1083 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1084 int64_t Val = CE->getValue();
1085 int64_t Min = - (1LL << (21 - 1));
1086 int64_t Max = ((1LL << (21 - 1)) - 1);
1087 return Val >= Min && Val <= Max;
1088 }
1089
1090 return true;
1091 }
1092
1093 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1094 // Add as immediates when possible. Null MCExpr = 0.
1095 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001096 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001097 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001098 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001099 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001100 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001101 }
1102
1103 void addRegOperands(MCInst &Inst, unsigned N) const {
1104 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001105 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001106 }
1107
1108 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1109 assert(N == 1 && "Invalid number of operands!");
1110 assert(
1111 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1112
1113 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1114 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1115 RI->getEncodingValue(getReg()));
1116
Jim Grosbache9119e42015-05-13 18:37:00 +00001117 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001118 }
1119
1120 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1121 assert(N == 1 && "Invalid number of operands!");
1122 assert(
1123 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001124 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001125 }
1126
1127 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1128 assert(N == 1 && "Invalid number of operands!");
1129 assert(
1130 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001131 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001132 }
1133
1134 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1135 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001136 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001137 }
1138
Sander de Smalen525e3222018-04-12 13:19:32 +00001139 enum VecListIndexType {
1140 VecListIdx_DReg = 0,
1141 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001142 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001143 };
1144
1145 template <VecListIndexType RegTy, unsigned NumRegs>
1146 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001147 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001148 static const unsigned FirstRegs[][5] = {
1149 /* DReg */ { AArch64::Q0,
1150 AArch64::D0, AArch64::D0_D1,
1151 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1152 /* QReg */ { AArch64::Q0,
1153 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001154 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1155 /* ZReg */ { AArch64::Z0,
1156 AArch64::Z0 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001157 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001158
Sander de Smalenea626e32018-04-13 09:11:53 +00001159 assert((RegTy != VecListIdx_ZReg || NumRegs <= 1) &&
1160 " NumRegs must be 0 or 1 for ZRegs");
1161
Sander de Smalen525e3222018-04-12 13:19:32 +00001162 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1163 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1164 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001165 }
1166
1167 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1168 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001169 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001170 }
1171
1172 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1173 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001174 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001175 }
1176
1177 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1178 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001179 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001180 }
1181
1182 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1183 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001184 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001185 }
1186
1187 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1188 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001189 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001190 }
1191
1192 void addImmOperands(MCInst &Inst, unsigned N) const {
1193 assert(N == 1 && "Invalid number of operands!");
1194 // If this is a pageoff symrefexpr with an addend, adjust the addend
1195 // to be only the page-offset portion. Otherwise, just add the expr
1196 // as-is.
1197 addExpr(Inst, getImm());
1198 }
1199
1200 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1201 assert(N == 2 && "Invalid number of operands!");
1202 if (isShiftedImm()) {
1203 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001204 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001205 } else {
1206 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001207 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001208 }
1209 }
1210
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001211 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1212 assert(N == 2 && "Invalid number of operands!");
1213
1214 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1215 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1216 int64_t Val = -CE->getValue();
1217 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1218
1219 Inst.addOperand(MCOperand::createImm(Val));
1220 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1221 }
1222
Tim Northover3b0846e2014-05-24 12:50:23 +00001223 void addCondCodeOperands(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(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001226 }
1227
1228 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1229 assert(N == 1 && "Invalid number of operands!");
1230 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1231 if (!MCE)
1232 addExpr(Inst, getImm());
1233 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001234 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001235 }
1236
1237 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1238 addImmOperands(Inst, N);
1239 }
1240
1241 template<int Scale>
1242 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1243 assert(N == 1 && "Invalid number of operands!");
1244 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1245
1246 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001247 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001248 return;
1249 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001250 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001251 }
1252
1253 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1254 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001255 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001256 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001257 }
1258
Sam Parker6d42de72017-08-11 13:14:00 +00001259 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1260 assert(N == 1 && "Invalid number of operands!");
1261 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1262 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1263 }
1264
Tim Northover3b0846e2014-05-24 12:50:23 +00001265 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1266 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001267 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001268 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001269 }
1270
1271 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1272 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001273 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001274 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001275 }
1276
1277 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1278 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001279 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001280 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001281 }
1282
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001283 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1284 assert(N == 1 && "Invalid number of operands!");
1285 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1286 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1287 }
1288
Tim Northover3b0846e2014-05-24 12:50:23 +00001289 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1290 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001291 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001292 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001293 }
1294
1295 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1296 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001297 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001298 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001299 }
1300
1301 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1302 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001303 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001304 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001305 }
1306
1307 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1308 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001309 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001310 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001311 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001312 }
1313
1314 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1315 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001316 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001317 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001318 }
1319
1320 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1321 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001322 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001323 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001324 }
1325
1326 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1327 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001328 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001329 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001330 }
1331
1332 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1333 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001334 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001335 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001336 }
1337
1338 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1339 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001340 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001341 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001342 }
1343
1344 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1345 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001346 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001347 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001348 }
1349
1350 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1351 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001352 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001353 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001354 }
1355
1356 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1357 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001358 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001359 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001360 }
1361
1362 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1363 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001364 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001365 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001366 }
1367
1368 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1369 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001370 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001371 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001372 }
1373
Sander de Smalena1c259c2018-01-29 13:05:38 +00001374 template <typename T>
1375 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001376 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001377 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001378 typename std::make_unsigned<T>::type Val = MCE->getValue();
1379 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001380 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001381 }
1382
Sander de Smalena1c259c2018-01-29 13:05:38 +00001383 template <typename T>
1384 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001385 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001386 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001387 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1388 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001389 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001390 }
1391
Tim Northover3b0846e2014-05-24 12:50:23 +00001392 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1393 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001394 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001395 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001396 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001397 }
1398
1399 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1400 // Branch operands don't encode the low bits, so shift them off
1401 // here. If it's a label, however, just put it on directly as there's
1402 // not enough information now to do anything.
1403 assert(N == 1 && "Invalid number of operands!");
1404 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1405 if (!MCE) {
1406 addExpr(Inst, getImm());
1407 return;
1408 }
1409 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001410 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001411 }
1412
1413 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1414 // Branch operands don't encode the low bits, so shift them off
1415 // here. If it's a label, however, just put it on directly as there's
1416 // not enough information now to do anything.
1417 assert(N == 1 && "Invalid number of operands!");
1418 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1419 if (!MCE) {
1420 addExpr(Inst, getImm());
1421 return;
1422 }
1423 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001424 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001425 }
1426
1427 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1428 // Branch operands don't encode the low bits, so shift them off
1429 // here. If it's a label, however, just put it on directly as there's
1430 // not enough information now to do anything.
1431 assert(N == 1 && "Invalid number of operands!");
1432 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1433 if (!MCE) {
1434 addExpr(Inst, getImm());
1435 return;
1436 }
1437 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001438 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001439 }
1440
1441 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1442 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001443 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001444 }
1445
1446 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1447 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001448 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001449 }
1450
1451 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1452 assert(N == 1 && "Invalid number of operands!");
1453
Jim Grosbache9119e42015-05-13 18:37:00 +00001454 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001455 }
1456
1457 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1458 assert(N == 1 && "Invalid number of operands!");
1459
Jim Grosbache9119e42015-05-13 18:37:00 +00001460 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001461 }
1462
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001463 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1464 assert(N == 1 && "Invalid number of operands!");
1465
1466 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1467 }
1468
1469 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001470 assert(N == 1 && "Invalid number of operands!");
1471
Jim Grosbache9119e42015-05-13 18:37:00 +00001472 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001473 }
1474
1475 void addSysCROperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001477 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001478 }
1479
1480 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1481 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001482 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001483 }
1484
Oliver Stannarda34e4702015-12-01 10:48:51 +00001485 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1486 assert(N == 1 && "Invalid number of operands!");
1487 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1488 }
1489
Tim Northover3b0846e2014-05-24 12:50:23 +00001490 void addShifterOperands(MCInst &Inst, unsigned N) const {
1491 assert(N == 1 && "Invalid number of operands!");
1492 unsigned Imm =
1493 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001494 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001495 }
1496
1497 void addExtendOperands(MCInst &Inst, unsigned N) const {
1498 assert(N == 1 && "Invalid number of operands!");
1499 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1500 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1501 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001502 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001503 }
1504
1505 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1506 assert(N == 1 && "Invalid number of operands!");
1507 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1508 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1509 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001510 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001511 }
1512
1513 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1514 assert(N == 2 && "Invalid number of operands!");
1515 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1516 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001517 Inst.addOperand(MCOperand::createImm(IsSigned));
1518 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001519 }
1520
1521 // For 8-bit load/store instructions with a register offset, both the
1522 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1523 // they're disambiguated by whether the shift was explicit or implicit rather
1524 // than its size.
1525 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1526 assert(N == 2 && "Invalid number of operands!");
1527 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1528 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001529 Inst.addOperand(MCOperand::createImm(IsSigned));
1530 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001531 }
1532
1533 template<int Shift>
1534 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1535 assert(N == 1 && "Invalid number of operands!");
1536
1537 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1538 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001539 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001540 }
1541
1542 template<int Shift>
1543 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1544 assert(N == 1 && "Invalid number of operands!");
1545
1546 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1547 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001548 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001549 }
1550
Sam Parker5f934642017-08-31 09:27:04 +00001551 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1552 assert(N == 1 && "Invalid number of operands!");
1553 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1554 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1555 }
1556
1557 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1558 assert(N == 1 && "Invalid number of operands!");
1559 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1560 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1561 }
1562
Tim Northover3b0846e2014-05-24 12:50:23 +00001563 void print(raw_ostream &OS) const override;
1564
David Blaikie960ea3f2014-06-08 16:18:35 +00001565 static std::unique_ptr<AArch64Operand>
1566 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1567 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001568 Op->Tok.Data = Str.data();
1569 Op->Tok.Length = Str.size();
1570 Op->Tok.IsSuffix = IsSuffix;
1571 Op->StartLoc = S;
1572 Op->EndLoc = S;
1573 return Op;
1574 }
1575
David Blaikie960ea3f2014-06-08 16:18:35 +00001576 static std::unique_ptr<AArch64Operand>
Florian Hahnc4422242017-11-07 13:07:50 +00001577 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001578 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001579 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001580 Op->Reg.Kind = Kind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001581 Op->StartLoc = S;
1582 Op->EndLoc = E;
1583 return Op;
1584 }
1585
David Blaikie960ea3f2014-06-08 16:18:35 +00001586 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001587 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1588 SMLoc S, SMLoc E, MCContext &Ctx) {
1589 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1590 Kind == RegKind::SVEPredicateVector) &&
1591 "Invalid vector kind");
Florian Hahn91f11e52017-11-07 16:45:48 +00001592 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1593 Op->Reg.RegNum = RegNum;
1594 Op->Reg.ElementWidth = ElementWidth;
1595 Op->Reg.Kind = Kind;
1596 Op->StartLoc = S;
1597 Op->EndLoc = E;
1598 return Op;
1599 }
1600
1601 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001602 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001603 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1604 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001605 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001606 Op->VectorList.RegNum = RegNum;
1607 Op->VectorList.Count = Count;
1608 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001609 Op->VectorList.ElementWidth = ElementWidth;
1610 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001611 Op->StartLoc = S;
1612 Op->EndLoc = E;
1613 return Op;
1614 }
1615
David Blaikie960ea3f2014-06-08 16:18:35 +00001616 static std::unique_ptr<AArch64Operand>
1617 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1618 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001619 Op->VectorIndex.Val = Idx;
1620 Op->StartLoc = S;
1621 Op->EndLoc = E;
1622 return Op;
1623 }
1624
David Blaikie960ea3f2014-06-08 16:18:35 +00001625 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1626 SMLoc E, MCContext &Ctx) {
1627 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001628 Op->Imm.Val = Val;
1629 Op->StartLoc = S;
1630 Op->EndLoc = E;
1631 return Op;
1632 }
1633
David Blaikie960ea3f2014-06-08 16:18:35 +00001634 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1635 unsigned ShiftAmount,
1636 SMLoc S, SMLoc E,
1637 MCContext &Ctx) {
1638 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001639 Op->ShiftedImm .Val = Val;
1640 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1641 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>
1647 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1648 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001649 Op->CondCode.Code = Code;
1650 Op->StartLoc = S;
1651 Op->EndLoc = E;
1652 return Op;
1653 }
1654
David Blaikie960ea3f2014-06-08 16:18:35 +00001655 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1656 MCContext &Ctx) {
1657 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001658 Op->FPImm.Val = Val;
1659 Op->StartLoc = S;
1660 Op->EndLoc = S;
1661 return Op;
1662 }
1663
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001664 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1665 StringRef Str,
1666 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001667 MCContext &Ctx) {
1668 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001669 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001670 Op->Barrier.Data = Str.data();
1671 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001672 Op->StartLoc = S;
1673 Op->EndLoc = S;
1674 return Op;
1675 }
1676
Tim Northover7cd58932015-01-22 17:23:04 +00001677 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1678 uint32_t MRSReg,
1679 uint32_t MSRReg,
1680 uint32_t PStateField,
1681 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001682 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001683 Op->SysReg.Data = Str.data();
1684 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001685 Op->SysReg.MRSReg = MRSReg;
1686 Op->SysReg.MSRReg = MSRReg;
1687 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001688 Op->StartLoc = S;
1689 Op->EndLoc = S;
1690 return Op;
1691 }
1692
David Blaikie960ea3f2014-06-08 16:18:35 +00001693 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1694 SMLoc E, MCContext &Ctx) {
1695 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001696 Op->SysCRImm.Val = Val;
1697 Op->StartLoc = S;
1698 Op->EndLoc = E;
1699 return Op;
1700 }
1701
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001702 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1703 StringRef Str,
1704 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001705 MCContext &Ctx) {
1706 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001707 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001708 Op->Barrier.Data = Str.data();
1709 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001710 Op->StartLoc = S;
1711 Op->EndLoc = S;
1712 return Op;
1713 }
1714
Oliver Stannarda34e4702015-12-01 10:48:51 +00001715 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1716 StringRef Str,
1717 SMLoc S,
1718 MCContext &Ctx) {
1719 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1720 Op->PSBHint.Val = Val;
1721 Op->PSBHint.Data = Str.data();
1722 Op->PSBHint.Length = Str.size();
1723 Op->StartLoc = S;
1724 Op->EndLoc = S;
1725 return Op;
1726 }
1727
David Blaikie960ea3f2014-06-08 16:18:35 +00001728 static std::unique_ptr<AArch64Operand>
1729 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1730 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1731 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001732 Op->ShiftExtend.Type = ShOp;
1733 Op->ShiftExtend.Amount = Val;
1734 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1735 Op->StartLoc = S;
1736 Op->EndLoc = E;
1737 return Op;
1738 }
1739};
1740
1741} // end anonymous namespace.
1742
1743void AArch64Operand::print(raw_ostream &OS) const {
1744 switch (Kind) {
1745 case k_FPImm:
1746 OS << "<fpimm " << getFPImm() << "("
1747 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1748 break;
1749 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001750 StringRef Name = getBarrierName();
1751 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001752 OS << "<barrier " << Name << ">";
1753 else
1754 OS << "<barrier invalid #" << getBarrier() << ">";
1755 break;
1756 }
1757 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001758 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001759 break;
1760 case k_ShiftedImm: {
1761 unsigned Shift = getShiftedImmShift();
1762 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001763 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001764 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1765 break;
1766 }
1767 case k_CondCode:
1768 OS << "<condcode " << getCondCode() << ">";
1769 break;
1770 case k_Register:
1771 OS << "<register " << getReg() << ">";
1772 break;
1773 case k_VectorList: {
1774 OS << "<vectorlist ";
1775 unsigned Reg = getVectorListStart();
1776 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1777 OS << Reg + i << " ";
1778 OS << ">";
1779 break;
1780 }
1781 case k_VectorIndex:
1782 OS << "<vectorindex " << getVectorIndex() << ">";
1783 break;
1784 case k_SysReg:
1785 OS << "<sysreg: " << getSysReg() << '>';
1786 break;
1787 case k_Token:
1788 OS << "'" << getToken() << "'";
1789 break;
1790 case k_SysCR:
1791 OS << "c" << getSysCR();
1792 break;
1793 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001794 StringRef Name = getPrefetchName();
1795 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001796 OS << "<prfop " << Name << ">";
1797 else
1798 OS << "<prfop invalid #" << getPrefetch() << ">";
1799 break;
1800 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001801 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001802 OS << getPSBHintName();
1803 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001804 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001805 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1806 << getShiftExtendAmount();
1807 if (!hasShiftExtendAmount())
1808 OS << "<imp>";
1809 OS << '>';
1810 break;
1811 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001812}
1813
1814/// @name Auto-generated Match Functions
1815/// {
1816
1817static unsigned MatchRegisterName(StringRef Name);
1818
1819/// }
1820
Florian Hahnc4422242017-11-07 13:07:50 +00001821static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001822 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001823 .Case("v0", AArch64::Q0)
1824 .Case("v1", AArch64::Q1)
1825 .Case("v2", AArch64::Q2)
1826 .Case("v3", AArch64::Q3)
1827 .Case("v4", AArch64::Q4)
1828 .Case("v5", AArch64::Q5)
1829 .Case("v6", AArch64::Q6)
1830 .Case("v7", AArch64::Q7)
1831 .Case("v8", AArch64::Q8)
1832 .Case("v9", AArch64::Q9)
1833 .Case("v10", AArch64::Q10)
1834 .Case("v11", AArch64::Q11)
1835 .Case("v12", AArch64::Q12)
1836 .Case("v13", AArch64::Q13)
1837 .Case("v14", AArch64::Q14)
1838 .Case("v15", AArch64::Q15)
1839 .Case("v16", AArch64::Q16)
1840 .Case("v17", AArch64::Q17)
1841 .Case("v18", AArch64::Q18)
1842 .Case("v19", AArch64::Q19)
1843 .Case("v20", AArch64::Q20)
1844 .Case("v21", AArch64::Q21)
1845 .Case("v22", AArch64::Q22)
1846 .Case("v23", AArch64::Q23)
1847 .Case("v24", AArch64::Q24)
1848 .Case("v25", AArch64::Q25)
1849 .Case("v26", AArch64::Q26)
1850 .Case("v27", AArch64::Q27)
1851 .Case("v28", AArch64::Q28)
1852 .Case("v29", AArch64::Q29)
1853 .Case("v30", AArch64::Q30)
1854 .Case("v31", AArch64::Q31)
1855 .Default(0);
1856}
1857
Sander de Smalen73937b72018-04-11 07:36:10 +00001858/// Returns an optional pair of (#elements, element-width) if Suffix
1859/// is a valid vector kind. Where the number of elements in a vector
1860/// or the vector width is implicit or explicitly unknown (but still a
1861/// valid suffix kind), 0 is used.
1862static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1863 RegKind VectorKind) {
1864 std::pair<int, int> Res = {-1, -1};
1865
1866 switch (VectorKind) {
1867 case RegKind::NeonVector:
1868 Res =
1869 StringSwitch<std::pair<int, int>>(Suffix.lower())
1870 .Case("", {0, 0})
1871 .Case(".1d", {1, 64})
1872 .Case(".1q", {1, 128})
1873 // '.2h' needed for fp16 scalar pairwise reductions
1874 .Case(".2h", {2, 16})
1875 .Case(".2s", {2, 32})
1876 .Case(".2d", {2, 64})
1877 // '.4b' is another special case for the ARMv8.2a dot product
1878 // operand
1879 .Case(".4b", {4, 8})
1880 .Case(".4h", {4, 16})
1881 .Case(".4s", {4, 32})
1882 .Case(".8b", {8, 8})
1883 .Case(".8h", {8, 16})
1884 .Case(".16b", {16, 8})
1885 // Accept the width neutral ones, too, for verbose syntax. If those
1886 // aren't used in the right places, the token operand won't match so
1887 // all will work out.
1888 .Case(".b", {0, 8})
1889 .Case(".h", {0, 16})
1890 .Case(".s", {0, 32})
1891 .Case(".d", {0, 64})
1892 .Default({-1, -1});
1893 break;
1894 case RegKind::SVEPredicateVector:
1895 case RegKind::SVEDataVector:
1896 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1897 .Case("", {0, 0})
1898 .Case(".b", {0, 8})
1899 .Case(".h", {0, 16})
1900 .Case(".s", {0, 32})
1901 .Case(".d", {0, 64})
1902 .Case(".q", {0, 128})
1903 .Default({-1, -1});
1904 break;
1905 default:
1906 llvm_unreachable("Unsupported RegKind");
1907 }
1908
1909 if (Res == std::make_pair(-1, -1))
1910 return Optional<std::pair<int, int>>();
1911
1912 return Optional<std::pair<int, int>>(Res);
1913}
1914
1915static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1916 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001917}
1918
Florian Hahn91f11e52017-11-07 16:45:48 +00001919static unsigned matchSVEDataVectorRegName(StringRef Name) {
1920 return StringSwitch<unsigned>(Name.lower())
1921 .Case("z0", AArch64::Z0)
1922 .Case("z1", AArch64::Z1)
1923 .Case("z2", AArch64::Z2)
1924 .Case("z3", AArch64::Z3)
1925 .Case("z4", AArch64::Z4)
1926 .Case("z5", AArch64::Z5)
1927 .Case("z6", AArch64::Z6)
1928 .Case("z7", AArch64::Z7)
1929 .Case("z8", AArch64::Z8)
1930 .Case("z9", AArch64::Z9)
1931 .Case("z10", AArch64::Z10)
1932 .Case("z11", AArch64::Z11)
1933 .Case("z12", AArch64::Z12)
1934 .Case("z13", AArch64::Z13)
1935 .Case("z14", AArch64::Z14)
1936 .Case("z15", AArch64::Z15)
1937 .Case("z16", AArch64::Z16)
1938 .Case("z17", AArch64::Z17)
1939 .Case("z18", AArch64::Z18)
1940 .Case("z19", AArch64::Z19)
1941 .Case("z20", AArch64::Z20)
1942 .Case("z21", AArch64::Z21)
1943 .Case("z22", AArch64::Z22)
1944 .Case("z23", AArch64::Z23)
1945 .Case("z24", AArch64::Z24)
1946 .Case("z25", AArch64::Z25)
1947 .Case("z26", AArch64::Z26)
1948 .Case("z27", AArch64::Z27)
1949 .Case("z28", AArch64::Z28)
1950 .Case("z29", AArch64::Z29)
1951 .Case("z30", AArch64::Z30)
1952 .Case("z31", AArch64::Z31)
1953 .Default(0);
1954}
1955
Sander de Smalencd6be962017-12-20 11:02:42 +00001956static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1957 return StringSwitch<unsigned>(Name.lower())
1958 .Case("p0", AArch64::P0)
1959 .Case("p1", AArch64::P1)
1960 .Case("p2", AArch64::P2)
1961 .Case("p3", AArch64::P3)
1962 .Case("p4", AArch64::P4)
1963 .Case("p5", AArch64::P5)
1964 .Case("p6", AArch64::P6)
1965 .Case("p7", AArch64::P7)
1966 .Case("p8", AArch64::P8)
1967 .Case("p9", AArch64::P9)
1968 .Case("p10", AArch64::P10)
1969 .Case("p11", AArch64::P11)
1970 .Case("p12", AArch64::P12)
1971 .Case("p13", AArch64::P13)
1972 .Case("p14", AArch64::P14)
1973 .Case("p15", AArch64::P15)
1974 .Default(0);
1975}
1976
Tim Northover3b0846e2014-05-24 12:50:23 +00001977bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1978 SMLoc &EndLoc) {
1979 StartLoc = getLoc();
1980 RegNo = tryParseRegister();
1981 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1982 return (RegNo == (unsigned)-1);
1983}
1984
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001985// Matches a register name or register alias previously defined by '.req'
1986unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001987 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001988 unsigned RegNum = 0;
1989 if ((RegNum = matchSVEDataVectorRegName(Name)))
1990 return Kind == RegKind::SVEDataVector ? RegNum : 0;
1991
Sander de Smalencd6be962017-12-20 11:02:42 +00001992 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
1993 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
1994
Sander de Smalenc067c302017-12-20 09:45:45 +00001995 if ((RegNum = MatchNeonVectorRegName(Name)))
1996 return Kind == RegKind::NeonVector ? RegNum : 0;
1997
1998 // The parsed register must be of RegKind Scalar
1999 if ((RegNum = MatchRegisterName(Name)))
2000 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002001
Florian Hahnc4422242017-11-07 13:07:50 +00002002 if (!RegNum) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002003 // Check for aliases registered via .req. Canonicalize to lower case.
2004 // That's more consistent since register names are case insensitive, and
2005 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2006 auto Entry = RegisterReqs.find(Name.lower());
2007 if (Entry == RegisterReqs.end())
2008 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002009
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002010 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002011 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002012 RegNum = Entry->getValue().second;
2013 }
2014 return RegNum;
2015}
2016
Tim Northover3b0846e2014-05-24 12:50:23 +00002017/// tryParseRegister - Try to parse a register name. The token must be an
2018/// Identifier when called, and if it is a register name the token is eaten and
2019/// the register is added to the operand list.
2020int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002021 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002022 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002023 if (Tok.isNot(AsmToken::Identifier))
2024 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00002025
2026 std::string lowerCase = Tok.getString().lower();
Florian Hahnc4422242017-11-07 13:07:50 +00002027 unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
Sander de Smalenc067c302017-12-20 09:45:45 +00002028
Tim Northover3b0846e2014-05-24 12:50:23 +00002029 // Also handle a few aliases of registers.
2030 if (RegNum == 0)
2031 RegNum = StringSwitch<unsigned>(lowerCase)
2032 .Case("fp", AArch64::FP)
2033 .Case("lr", AArch64::LR)
2034 .Case("x31", AArch64::XZR)
2035 .Case("w31", AArch64::WZR)
2036 .Default(0);
2037
2038 if (RegNum == 0)
2039 return -1;
2040
2041 Parser.Lex(); // Eat identifier token.
2042 return RegNum;
2043}
2044
Tim Northover3b0846e2014-05-24 12:50:23 +00002045/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002046OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002047AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002048 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002049 SMLoc S = getLoc();
2050
2051 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2052 Error(S, "Expected cN operand where 0 <= N <= 15");
2053 return MatchOperand_ParseFail;
2054 }
2055
2056 StringRef Tok = Parser.getTok().getIdentifier();
2057 if (Tok[0] != 'c' && Tok[0] != 'C') {
2058 Error(S, "Expected cN operand where 0 <= N <= 15");
2059 return MatchOperand_ParseFail;
2060 }
2061
2062 uint32_t CRNum;
2063 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2064 if (BadNum || CRNum > 15) {
2065 Error(S, "Expected cN operand where 0 <= N <= 15");
2066 return MatchOperand_ParseFail;
2067 }
2068
2069 Parser.Lex(); // Eat identifier token.
2070 Operands.push_back(
2071 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2072 return MatchOperand_Success;
2073}
2074
2075/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002076OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002077AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002078 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002079 SMLoc S = getLoc();
2080 const AsmToken &Tok = Parser.getTok();
2081 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002082 // Eat optional hash.
2083 if (parseOptionalToken(AsmToken::Hash) ||
2084 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002085 const MCExpr *ImmVal;
2086 if (getParser().parseExpression(ImmVal))
2087 return MatchOperand_ParseFail;
2088
2089 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2090 if (!MCE) {
2091 TokError("immediate value expected for prefetch operand");
2092 return MatchOperand_ParseFail;
2093 }
2094 unsigned prfop = MCE->getValue();
2095 if (prfop > 31) {
2096 TokError("prefetch operand out of range, [0,31] expected");
2097 return MatchOperand_ParseFail;
2098 }
2099
Tim Northovere6ae6762016-07-05 21:23:04 +00002100 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2101 Operands.push_back(AArch64Operand::CreatePrefetch(
2102 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002103 return MatchOperand_Success;
2104 }
2105
2106 if (Tok.isNot(AsmToken::Identifier)) {
2107 TokError("pre-fetch hint expected");
2108 return MatchOperand_ParseFail;
2109 }
2110
Tim Northovere6ae6762016-07-05 21:23:04 +00002111 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2112 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002113 TokError("pre-fetch hint expected");
2114 return MatchOperand_ParseFail;
2115 }
2116
2117 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002118 Operands.push_back(AArch64Operand::CreatePrefetch(
2119 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002120 return MatchOperand_Success;
2121}
2122
Oliver Stannarda34e4702015-12-01 10:48:51 +00002123/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002124OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002125AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2126 MCAsmParser &Parser = getParser();
2127 SMLoc S = getLoc();
2128 const AsmToken &Tok = Parser.getTok();
2129 if (Tok.isNot(AsmToken::Identifier)) {
2130 TokError("invalid operand for instruction");
2131 return MatchOperand_ParseFail;
2132 }
2133
Tim Northovere6ae6762016-07-05 21:23:04 +00002134 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2135 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002136 TokError("invalid operand for instruction");
2137 return MatchOperand_ParseFail;
2138 }
2139
2140 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002141 Operands.push_back(AArch64Operand::CreatePSBHint(
2142 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002143 return MatchOperand_Success;
2144}
2145
Tim Northover3b0846e2014-05-24 12:50:23 +00002146/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2147/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002148OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002149AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002150 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002151 SMLoc S = getLoc();
2152 const MCExpr *Expr;
2153
2154 if (Parser.getTok().is(AsmToken::Hash)) {
2155 Parser.Lex(); // Eat hash token.
2156 }
2157
2158 if (parseSymbolicImmVal(Expr))
2159 return MatchOperand_ParseFail;
2160
2161 AArch64MCExpr::VariantKind ELFRefKind;
2162 MCSymbolRefExpr::VariantKind DarwinRefKind;
2163 int64_t Addend;
2164 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2165 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2166 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2167 // No modifier was specified at all; this is the syntax for an ELF basic
2168 // ADRP relocation (unfortunately).
2169 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002170 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002171 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2172 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2173 Addend != 0) {
2174 Error(S, "gotpage label reference not allowed an addend");
2175 return MatchOperand_ParseFail;
2176 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2177 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2178 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2179 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2180 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2181 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2182 // The operand must be an @page or @gotpage qualified symbolref.
2183 Error(S, "page or gotpage label reference expected");
2184 return MatchOperand_ParseFail;
2185 }
2186 }
2187
2188 // We have either a label reference possibly with addend or an immediate. The
2189 // addend is a raw value here. The linker will adjust it to only reference the
2190 // page.
2191 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2192 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2193
2194 return MatchOperand_Success;
2195}
2196
2197/// tryParseAdrLabel - Parse and validate a source label for the ADR
2198/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002199OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002200AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2201 SMLoc S = getLoc();
2202 const MCExpr *Expr;
2203
Nirav Davee833c6c2016-11-08 18:31:04 +00002204 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002205 if (getParser().parseExpression(Expr))
2206 return MatchOperand_ParseFail;
2207
2208 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2209 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2210
2211 return MatchOperand_Success;
2212}
2213
2214/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002215OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002216AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002217 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002218 SMLoc S = getLoc();
2219
Nirav Davee833c6c2016-11-08 18:31:04 +00002220 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002221
2222 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002223 bool isNegative = parseOptionalToken(AsmToken::Minus);
2224
Tim Northover3b0846e2014-05-24 12:50:23 +00002225 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002226 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002227 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002228 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002229 Val = Tok.getIntVal();
2230 if (Val > 255 || Val < 0) {
2231 TokError("encoded floating point value out of range");
2232 return MatchOperand_ParseFail;
2233 }
2234 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002235 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002236 if (isNegative)
2237 RealVal.changeSign();
2238
Tim Northover3b0846e2014-05-24 12:50:23 +00002239 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002240 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002241
John Brawn5ca5daa2017-04-20 10:13:54 +00002242 // Check for out of range values. As an exception we let Zero through,
2243 // but as tokens instead of an FPImm so that it can be matched by the
2244 // appropriate alias if one exists.
2245 if (RealVal.isPosZero()) {
2246 Parser.Lex(); // Eat the token.
2247 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2248 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2249 return MatchOperand_Success;
2250 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002251 TokError("expected compatible register or floating-point constant");
2252 return MatchOperand_ParseFail;
2253 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002254 }
2255 Parser.Lex(); // Eat the token.
2256 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2257 return MatchOperand_Success;
2258 }
2259
2260 if (!Hash)
2261 return MatchOperand_NoMatch;
2262
2263 TokError("invalid floating point immediate");
2264 return MatchOperand_ParseFail;
2265}
2266
2267/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002268OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002269AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002270 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002271 SMLoc S = getLoc();
2272
2273 if (Parser.getTok().is(AsmToken::Hash))
2274 Parser.Lex(); // Eat '#'
2275 else if (Parser.getTok().isNot(AsmToken::Integer))
2276 // Operand should start from # or should be integer, emit error otherwise.
2277 return MatchOperand_NoMatch;
2278
2279 const MCExpr *Imm;
2280 if (parseSymbolicImmVal(Imm))
2281 return MatchOperand_ParseFail;
2282 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2283 uint64_t ShiftAmount = 0;
2284 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2285 if (MCE) {
2286 int64_t Val = MCE->getValue();
2287 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002288 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002289 ShiftAmount = 12;
2290 }
2291 }
2292 SMLoc E = Parser.getTok().getLoc();
2293 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2294 getContext()));
2295 return MatchOperand_Success;
2296 }
2297
2298 // Eat ','
2299 Parser.Lex();
2300
2301 // The optional operand must be "lsl #N" where N is non-negative.
2302 if (!Parser.getTok().is(AsmToken::Identifier) ||
2303 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2304 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2305 return MatchOperand_ParseFail;
2306 }
2307
2308 // Eat 'lsl'
2309 Parser.Lex();
2310
Nirav Davee833c6c2016-11-08 18:31:04 +00002311 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002312
2313 if (Parser.getTok().isNot(AsmToken::Integer)) {
2314 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2315 return MatchOperand_ParseFail;
2316 }
2317
2318 int64_t ShiftAmount = Parser.getTok().getIntVal();
2319
2320 if (ShiftAmount < 0) {
2321 Error(Parser.getTok().getLoc(), "positive shift amount required");
2322 return MatchOperand_ParseFail;
2323 }
2324 Parser.Lex(); // Eat the number
2325
2326 SMLoc E = Parser.getTok().getLoc();
2327 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2328 S, E, getContext()));
2329 return MatchOperand_Success;
2330}
2331
2332/// parseCondCodeString - Parse a Condition Code string.
2333AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2334 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2335 .Case("eq", AArch64CC::EQ)
2336 .Case("ne", AArch64CC::NE)
2337 .Case("cs", AArch64CC::HS)
2338 .Case("hs", AArch64CC::HS)
2339 .Case("cc", AArch64CC::LO)
2340 .Case("lo", AArch64CC::LO)
2341 .Case("mi", AArch64CC::MI)
2342 .Case("pl", AArch64CC::PL)
2343 .Case("vs", AArch64CC::VS)
2344 .Case("vc", AArch64CC::VC)
2345 .Case("hi", AArch64CC::HI)
2346 .Case("ls", AArch64CC::LS)
2347 .Case("ge", AArch64CC::GE)
2348 .Case("lt", AArch64CC::LT)
2349 .Case("gt", AArch64CC::GT)
2350 .Case("le", AArch64CC::LE)
2351 .Case("al", AArch64CC::AL)
2352 .Case("nv", AArch64CC::NV)
2353 .Default(AArch64CC::Invalid);
2354 return CC;
2355}
2356
2357/// parseCondCode - Parse a Condition Code operand.
2358bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2359 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002360 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002361 SMLoc S = getLoc();
2362 const AsmToken &Tok = Parser.getTok();
2363 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2364
2365 StringRef Cond = Tok.getString();
2366 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2367 if (CC == AArch64CC::Invalid)
2368 return TokError("invalid condition code");
2369 Parser.Lex(); // Eat identifier token.
2370
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002371 if (invertCondCode) {
2372 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2373 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002374 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002375 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002376
2377 Operands.push_back(
2378 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2379 return false;
2380}
2381
2382/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2383/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002384OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002385AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002386 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002387 const AsmToken &Tok = Parser.getTok();
2388 std::string LowerID = Tok.getString().lower();
2389 AArch64_AM::ShiftExtendType ShOp =
2390 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2391 .Case("lsl", AArch64_AM::LSL)
2392 .Case("lsr", AArch64_AM::LSR)
2393 .Case("asr", AArch64_AM::ASR)
2394 .Case("ror", AArch64_AM::ROR)
2395 .Case("msl", AArch64_AM::MSL)
2396 .Case("uxtb", AArch64_AM::UXTB)
2397 .Case("uxth", AArch64_AM::UXTH)
2398 .Case("uxtw", AArch64_AM::UXTW)
2399 .Case("uxtx", AArch64_AM::UXTX)
2400 .Case("sxtb", AArch64_AM::SXTB)
2401 .Case("sxth", AArch64_AM::SXTH)
2402 .Case("sxtw", AArch64_AM::SXTW)
2403 .Case("sxtx", AArch64_AM::SXTX)
2404 .Default(AArch64_AM::InvalidShiftExtend);
2405
2406 if (ShOp == AArch64_AM::InvalidShiftExtend)
2407 return MatchOperand_NoMatch;
2408
2409 SMLoc S = Tok.getLoc();
2410 Parser.Lex();
2411
Nirav Davee833c6c2016-11-08 18:31:04 +00002412 bool Hash = parseOptionalToken(AsmToken::Hash);
2413
Tim Northover3b0846e2014-05-24 12:50:23 +00002414 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2415 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2416 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2417 ShOp == AArch64_AM::MSL) {
2418 // We expect a number here.
2419 TokError("expected #imm after shift specifier");
2420 return MatchOperand_ParseFail;
2421 }
2422
Chad Rosier2ff37b82016-12-27 16:58:09 +00002423 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002424 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2425 Operands.push_back(
2426 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2427 return MatchOperand_Success;
2428 }
2429
Chad Rosier2ff37b82016-12-27 16:58:09 +00002430 // Make sure we do actually have a number, identifier or a parenthesized
2431 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002432 SMLoc E = Parser.getTok().getLoc();
2433 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002434 !Parser.getTok().is(AsmToken::LParen) &&
2435 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002436 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002437 return MatchOperand_ParseFail;
2438 }
2439
2440 const MCExpr *ImmVal;
2441 if (getParser().parseExpression(ImmVal))
2442 return MatchOperand_ParseFail;
2443
2444 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2445 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002446 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002447 return MatchOperand_ParseFail;
2448 }
2449
Jim Grosbach57fd2622014-09-23 22:16:02 +00002450 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002451 Operands.push_back(AArch64Operand::CreateShiftExtend(
2452 ShOp, MCE->getValue(), true, S, E, getContext()));
2453 return MatchOperand_Success;
2454}
2455
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002456static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2457 if (FBS[AArch64::HasV8_1aOps])
2458 Str += "ARMv8.1a";
2459 else if (FBS[AArch64::HasV8_2aOps])
2460 Str += "ARMv8.2a";
2461 else
2462 Str += "(unknown)";
2463}
2464
2465void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2466 SMLoc S) {
2467 const uint16_t Op2 = Encoding & 7;
2468 const uint16_t Cm = (Encoding & 0x78) >> 3;
2469 const uint16_t Cn = (Encoding & 0x780) >> 7;
2470 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2471
2472 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2473
2474 Operands.push_back(
2475 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2476 Operands.push_back(
2477 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2478 Operands.push_back(
2479 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2480 Expr = MCConstantExpr::create(Op2, getContext());
2481 Operands.push_back(
2482 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2483}
2484
Tim Northover3b0846e2014-05-24 12:50:23 +00002485/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2486/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2487bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2488 OperandVector &Operands) {
2489 if (Name.find('.') != StringRef::npos)
2490 return TokError("invalid operand");
2491
2492 Mnemonic = Name;
2493 Operands.push_back(
2494 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2495
Rafael Espindola961d4692014-11-11 05:18:41 +00002496 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002497 const AsmToken &Tok = Parser.getTok();
2498 StringRef Op = Tok.getString();
2499 SMLoc S = Tok.getLoc();
2500
Tim Northover3b0846e2014-05-24 12:50:23 +00002501 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002502 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2503 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002504 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002505 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2506 std::string Str("IC " + std::string(IC->Name) + " requires ");
2507 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2508 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002509 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002510 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002511 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002512 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2513 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002514 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002515 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2516 std::string Str("DC " + std::string(DC->Name) + " requires ");
2517 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2518 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002519 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002520 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002521 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002522 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2523 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002524 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002525 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2526 std::string Str("AT " + std::string(AT->Name) + " requires ");
2527 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2528 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002529 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002530 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002531 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002532 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2533 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002534 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002535 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2536 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2537 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2538 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002539 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002540 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002541 }
2542
Tim Northover3b0846e2014-05-24 12:50:23 +00002543 Parser.Lex(); // Eat operand.
2544
2545 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2546 bool HasRegister = false;
2547
2548 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002549 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002550 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2551 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002552 HasRegister = true;
2553 }
2554
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002555 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002556 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002557 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002558 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002559
Nirav Davee833c6c2016-11-08 18:31:04 +00002560 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2561 return true;
2562
Tim Northover3b0846e2014-05-24 12:50:23 +00002563 return false;
2564}
2565
Alex Bradbury58eba092016-11-01 16:32:05 +00002566OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002567AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002568 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002569 const AsmToken &Tok = Parser.getTok();
2570
2571 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002572 if (parseOptionalToken(AsmToken::Hash) ||
2573 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002574 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002575 const MCExpr *ImmVal;
2576 SMLoc ExprLoc = getLoc();
2577 if (getParser().parseExpression(ImmVal))
2578 return MatchOperand_ParseFail;
2579 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2580 if (!MCE) {
2581 Error(ExprLoc, "immediate value expected for barrier operand");
2582 return MatchOperand_ParseFail;
2583 }
2584 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2585 Error(ExprLoc, "barrier operand out of range");
2586 return MatchOperand_ParseFail;
2587 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002588 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2589 Operands.push_back(AArch64Operand::CreateBarrier(
2590 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002591 return MatchOperand_Success;
2592 }
2593
2594 if (Tok.isNot(AsmToken::Identifier)) {
2595 TokError("invalid operand for instruction");
2596 return MatchOperand_ParseFail;
2597 }
2598
Tim Northover3b0846e2014-05-24 12:50:23 +00002599 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002600 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2601 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002602 TokError("'sy' or #imm operand expected");
2603 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002604 } else if (!DB) {
2605 TokError("invalid barrier option name");
2606 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002607 }
2608
Tim Northovere6ae6762016-07-05 21:23:04 +00002609 Operands.push_back(AArch64Operand::CreateBarrier(
2610 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002611 Parser.Lex(); // Consume the option
2612
2613 return MatchOperand_Success;
2614}
2615
Alex Bradbury58eba092016-11-01 16:32:05 +00002616OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002617AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002618 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002619 const AsmToken &Tok = Parser.getTok();
2620
2621 if (Tok.isNot(AsmToken::Identifier))
2622 return MatchOperand_NoMatch;
2623
Tim Northovere6ae6762016-07-05 21:23:04 +00002624 int MRSReg, MSRReg;
2625 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2626 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2627 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2628 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2629 } else
2630 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002631
Tim Northovere6ae6762016-07-05 21:23:04 +00002632 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2633 unsigned PStateImm = -1;
2634 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2635 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002636
Tim Northovere6ae6762016-07-05 21:23:04 +00002637 Operands.push_back(
2638 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2639 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002640 Parser.Lex(); // Eat identifier
2641
2642 return MatchOperand_Success;
2643}
2644
Florian Hahnc4422242017-11-07 13:07:50 +00002645/// tryParseNeonVectorRegister - Parse a vector register operand.
2646bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002647 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002648 if (Parser.getTok().isNot(AsmToken::Identifier))
2649 return true;
2650
2651 SMLoc S = getLoc();
2652 // Check for a vector register specifier first.
2653 StringRef Kind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002654 int Reg = -1;
2655 OperandMatchResultTy Res =
2656 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2657 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002658 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002659
2660 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2661 if (!KindRes)
2662 return true;
2663
2664 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002665 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002666 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2667 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002668
Tim Northover3b0846e2014-05-24 12:50:23 +00002669 // If there was an explicit qualifier, that goes on as a literal text
2670 // operand.
2671 if (!Kind.empty())
2672 Operands.push_back(
2673 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2674
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002675 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2676}
2677
2678OperandMatchResultTy
2679AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002680 SMLoc SIdx = getLoc();
2681 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002682 const MCExpr *ImmVal;
2683 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002684 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002685 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2686 if (!MCE) {
2687 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002688 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002689 }
2690
2691 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002692
Nirav Davee833c6c2016-11-08 18:31:04 +00002693 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002694 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002695
2696 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2697 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002698 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002699 }
2700
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002701 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002702}
2703
Sander de Smalen73937b72018-04-11 07:36:10 +00002704// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002705// optional kind specifier. If it is a register specifier, eat the token
2706// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002707OperandMatchResultTy
Sander de Smalen73937b72018-04-11 07:36:10 +00002708AArch64AsmParser::tryParseVectorRegister(int &Reg, StringRef &Kind,
2709 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002710 MCAsmParser &Parser = getParser();
2711 const AsmToken &Tok = Parser.getTok();
2712
Florian Hahn91f11e52017-11-07 16:45:48 +00002713 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002714 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002715
2716 StringRef Name = Tok.getString();
2717 // If there is a kind specifier, it's separated from the register name by
2718 // a '.'.
2719 size_t Start = 0, Next = Name.find('.');
2720 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002721 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002722
2723 if (RegNum) {
2724 if (Next != StringRef::npos) {
2725 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002726 if (!isValidVectorKind(Kind, MatchKind)) {
2727 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002728 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002729 }
2730 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002731 Parser.Lex(); // Eat the register token.
2732
2733 Reg = RegNum;
2734 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002735 }
2736
Sander de Smalen8e607342017-11-15 15:44:43 +00002737 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002738}
2739
Sander de Smalencd6be962017-12-20 11:02:42 +00002740/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2741OperandMatchResultTy
2742AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2743 // Check for a SVE predicate register specifier first.
2744 const SMLoc S = getLoc();
2745 StringRef Kind;
2746 int RegNum = -1;
Sander de Smalen73937b72018-04-11 07:36:10 +00002747 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002748 if (Res != MatchOperand_Success)
2749 return Res;
2750
Sander de Smalen73937b72018-04-11 07:36:10 +00002751 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2752 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002753 return MatchOperand_NoMatch;
2754
Sander de Smalen73937b72018-04-11 07:36:10 +00002755 unsigned ElementWidth = KindRes->second;
2756 Operands.push_back(AArch64Operand::CreateVectorReg(
2757 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2758 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002759
Sander de Smalen7868e742018-01-09 11:17:06 +00002760 // Not all predicates are followed by a '/m' or '/z'.
2761 MCAsmParser &Parser = getParser();
2762 if (Parser.getTok().isNot(AsmToken::Slash))
2763 return MatchOperand_Success;
2764
2765 // But when they do they shouldn't have an element type suffix.
2766 if (!Kind.empty()) {
2767 Error(S, "not expecting size suffix");
2768 return MatchOperand_ParseFail;
2769 }
2770
2771 // Add a literal slash as operand
2772 Operands.push_back(
2773 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2774
2775 Parser.Lex(); // Eat the slash.
2776
2777 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002778 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002779 if (Pred != "z" && Pred != "m") {
2780 Error(getLoc(), "expecting 'm' or 'z' predication");
2781 return MatchOperand_ParseFail;
2782 }
2783
2784 // Add zero/merge token.
2785 const char *ZM = Pred == "z" ? "z" : "m";
2786 Operands.push_back(
2787 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2788
2789 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002790 return MatchOperand_Success;
2791}
2792
Tim Northover3b0846e2014-05-24 12:50:23 +00002793/// parseRegister - Parse a non-vector register operand.
2794bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2795 SMLoc S = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00002796 // Try for a vector (neon) register.
2797 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002798 return false;
2799
2800 // Try for a scalar register.
2801 int64_t Reg = tryParseRegister();
2802 if (Reg == -1)
2803 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002804 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2805 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002806
Tim Northover3b0846e2014-05-24 12:50:23 +00002807 return false;
2808}
2809
2810bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002811 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002812 bool HasELFModifier = false;
2813 AArch64MCExpr::VariantKind RefKind;
2814
Nirav Davee833c6c2016-11-08 18:31:04 +00002815 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002816 HasELFModifier = true;
2817
Nirav Davee833c6c2016-11-08 18:31:04 +00002818 if (Parser.getTok().isNot(AsmToken::Identifier))
2819 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002820
2821 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2822 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2823 .Case("lo12", AArch64MCExpr::VK_LO12)
2824 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2825 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2826 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2827 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2828 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2829 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2830 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2831 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2832 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2833 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2834 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2835 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2836 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2837 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2838 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2839 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2840 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2841 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2842 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2843 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2844 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2845 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2846 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2847 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2848 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2849 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2850 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2851 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2852 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2853 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2854 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2855 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2856 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2857 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002858 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2859 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002860 .Default(AArch64MCExpr::VK_INVALID);
2861
Nirav Davee833c6c2016-11-08 18:31:04 +00002862 if (RefKind == AArch64MCExpr::VK_INVALID)
2863 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002864
2865 Parser.Lex(); // Eat identifier
2866
Nirav Davee833c6c2016-11-08 18:31:04 +00002867 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002868 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002869 }
2870
2871 if (getParser().parseExpression(ImmVal))
2872 return true;
2873
2874 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002875 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002876
2877 return false;
2878}
2879
Sander de Smalen650234b2018-04-12 11:40:52 +00002880template <RegKind VectorKind>
2881OperandMatchResultTy
2882AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
2883 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002884 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00002885 if (!Parser.getTok().is(AsmToken::LCurly))
2886 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002887
2888 // Wrapper around parse function
Sander de Smalen650234b2018-04-12 11:40:52 +00002889 auto ParseVector = [this, &Parser](int &Reg, StringRef &Kind, SMLoc Loc,
2890 bool NoMatchIsError) {
2891 auto RegTok = Parser.getTok();
2892 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
2893 if (ParseRes == MatchOperand_Success) {
Sander de Smalen73937b72018-04-11 07:36:10 +00002894 if (parseVectorKind(Kind, RegKind::NeonVector))
Sander de Smalen650234b2018-04-12 11:40:52 +00002895 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002896 llvm_unreachable("Expected a valid vector kind");
2897 }
2898
Sander de Smalen650234b2018-04-12 11:40:52 +00002899 if (RegTok.isNot(AsmToken::Identifier) ||
2900 ParseRes == MatchOperand_ParseFail ||
2901 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
2902 Error(Loc, "vector register expected");
2903 return MatchOperand_ParseFail;
2904 }
2905
2906 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002907 };
2908
Tim Northover3b0846e2014-05-24 12:50:23 +00002909 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00002910 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00002911 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00002912
Tim Northover3b0846e2014-05-24 12:50:23 +00002913 StringRef Kind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002914 int FirstReg = -1;
Sander de Smalen650234b2018-04-12 11:40:52 +00002915 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
2916
2917 // Put back the original left bracket if there was no match, so that
2918 // different types of list-operands can be matched (e.g. SVE, Neon).
2919 if (ParseRes == MatchOperand_NoMatch)
2920 Parser.getLexer().UnLex(LCurly);
2921
2922 if (ParseRes != MatchOperand_Success)
2923 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002924
Tim Northover3b0846e2014-05-24 12:50:23 +00002925 int64_t PrevReg = FirstReg;
2926 unsigned Count = 1;
2927
Nirav Davee833c6c2016-11-08 18:31:04 +00002928 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002929 SMLoc Loc = getLoc();
2930 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002931
2932 int Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002933 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2934 if (ParseRes != MatchOperand_Success)
2935 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002936
Tim Northover3b0846e2014-05-24 12:50:23 +00002937 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002938 if (Kind != NextKind) {
2939 Error(Loc, "mismatched register size suffix");
2940 return MatchOperand_ParseFail;
2941 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002942
2943 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2944
2945 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002946 Error(Loc, "invalid number of vectors");
2947 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002948 }
2949
2950 Count += Space;
2951 }
2952 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002953 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002954 SMLoc Loc = getLoc();
2955 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002956 int Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002957 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2958 if (ParseRes != MatchOperand_Success)
2959 return ParseRes;
2960
Tim Northover3b0846e2014-05-24 12:50:23 +00002961 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002962 if (Kind != NextKind) {
2963 Error(Loc, "mismatched register size suffix");
2964 return MatchOperand_ParseFail;
2965 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002966
2967 // Registers must be incremental (with wraparound at 31)
2968 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00002969 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
2970 Error(Loc, "registers must be sequential");
2971 return MatchOperand_ParseFail;
2972 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002973
2974 PrevReg = Reg;
2975 ++Count;
2976 }
2977 }
2978
Nirav Davee833c6c2016-11-08 18:31:04 +00002979 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00002980 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002981
Sander de Smalen650234b2018-04-12 11:40:52 +00002982 if (Count > 4) {
2983 Error(S, "invalid number of vectors");
2984 return MatchOperand_ParseFail;
2985 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002986
2987 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00002988 unsigned ElementWidth = 0;
2989 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002990 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00002991 std::tie(NumElements, ElementWidth) = *VK;
2992 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002993
2994 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00002995 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
2996 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002997
Sander de Smalen650234b2018-04-12 11:40:52 +00002998 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002999}
3000
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003001/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3002bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003003 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3004 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003005 return true;
3006
3007 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3008}
3009
Alex Bradbury58eba092016-11-01 16:32:05 +00003010OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003011AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003012 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003013 const AsmToken &Tok = Parser.getTok();
3014 if (!Tok.is(AsmToken::Identifier))
3015 return MatchOperand_NoMatch;
3016
Florian Hahnc4422242017-11-07 13:07:50 +00003017 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00003018
3019 MCContext &Ctx = getContext();
3020 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
3021 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
3022 return MatchOperand_NoMatch;
3023
3024 SMLoc S = getLoc();
3025 Parser.Lex(); // Eat register
3026
Nirav Davee833c6c2016-11-08 18:31:04 +00003027 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003028 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003029 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003030 return MatchOperand_Success;
3031 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003032
Nirav Davee833c6c2016-11-08 18:31:04 +00003033 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003034
3035 if (Parser.getTok().isNot(AsmToken::Integer)) {
3036 Error(getLoc(), "index must be absent or #0");
3037 return MatchOperand_ParseFail;
3038 }
3039
3040 const MCExpr *ImmVal;
3041 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3042 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3043 Error(getLoc(), "index must be absent or #0");
3044 return MatchOperand_ParseFail;
3045 }
3046
3047 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003048 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003049 return MatchOperand_Success;
3050}
3051
3052/// parseOperand - Parse a arm instruction operand. For now this parses the
3053/// operand regardless of the mnemonic.
3054bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3055 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003056 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003057
3058 OperandMatchResultTy ResTy =
3059 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3060
Tim Northover3b0846e2014-05-24 12:50:23 +00003061 // Check if the current operand has a custom associated parser, if so, try to
3062 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003063 if (ResTy == MatchOperand_Success)
3064 return false;
3065 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3066 // there was a match, but an error occurred, in which case, just return that
3067 // the operand parsing failed.
3068 if (ResTy == MatchOperand_ParseFail)
3069 return true;
3070
3071 // Nothing custom, so do general case parsing.
3072 SMLoc S, E;
3073 switch (getLexer().getKind()) {
3074 default: {
3075 SMLoc S = getLoc();
3076 const MCExpr *Expr;
3077 if (parseSymbolicImmVal(Expr))
3078 return Error(S, "invalid operand");
3079
3080 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3081 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3082 return false;
3083 }
3084 case AsmToken::LBrac: {
3085 SMLoc Loc = Parser.getTok().getLoc();
3086 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3087 getContext()));
3088 Parser.Lex(); // Eat '['
3089
3090 // There's no comma after a '[', so we can parse the next operand
3091 // immediately.
3092 return parseOperand(Operands, false, false);
3093 }
3094 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003095 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003096 case AsmToken::Identifier: {
3097 // If we're expecting a Condition Code operand, then just parse that.
3098 if (isCondCode)
3099 return parseCondCode(Operands, invertCondCode);
3100
3101 // If it's a register name, parse it.
3102 if (!parseRegister(Operands))
3103 return false;
3104
3105 // This could be an optional "shift" or "extend" operand.
3106 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3107 // We can only continue if no tokens were eaten.
3108 if (GotShift != MatchOperand_NoMatch)
3109 return GotShift;
3110
3111 // This was not a register so parse other operands that start with an
3112 // identifier (like labels) as expressions and create them as immediates.
3113 const MCExpr *IdVal;
3114 S = getLoc();
3115 if (getParser().parseExpression(IdVal))
3116 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003117 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3118 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3119 return false;
3120 }
3121 case AsmToken::Integer:
3122 case AsmToken::Real:
3123 case AsmToken::Hash: {
3124 // #42 -> immediate.
3125 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003126
3127 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003128
3129 // Parse a negative sign
3130 bool isNegative = false;
3131 if (Parser.getTok().is(AsmToken::Minus)) {
3132 isNegative = true;
3133 // We need to consume this token only when we have a Real, otherwise
3134 // we let parseSymbolicImmVal take care of it
3135 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3136 Parser.Lex();
3137 }
3138
3139 // The only Real that should come through here is a literal #0.0 for
3140 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3141 // so convert the value.
3142 const AsmToken &Tok = Parser.getTok();
3143 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003144 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003145 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3146 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3147 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3148 Mnemonic != "fcmlt")
3149 return TokError("unexpected floating point literal");
3150 else if (IntVal != 0 || isNegative)
3151 return TokError("expected floating-point constant #0.0");
3152 Parser.Lex(); // Eat the token.
3153
3154 Operands.push_back(
3155 AArch64Operand::CreateToken("#0", false, S, getContext()));
3156 Operands.push_back(
3157 AArch64Operand::CreateToken(".0", false, S, getContext()));
3158 return false;
3159 }
3160
3161 const MCExpr *ImmVal;
3162 if (parseSymbolicImmVal(ImmVal))
3163 return true;
3164
3165 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3166 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3167 return false;
3168 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003169 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003170 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003171 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003172 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003173 Parser.Lex(); // Eat '='
3174 const MCExpr *SubExprVal;
3175 if (getParser().parseExpression(SubExprVal))
3176 return true;
3177
David Peixottoae5ba762014-07-18 16:05:14 +00003178 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003179 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003180 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003181
3182 bool IsXReg =
3183 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3184 Operands[1]->getReg());
3185
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003186 MCContext& Ctx = getContext();
3187 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3188 // 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 +00003189 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003190 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3191 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3192 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3193 ShiftAmt += 16;
3194 Imm >>= 16;
3195 }
3196 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3197 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3198 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003199 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003200 if (ShiftAmt)
3201 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3202 ShiftAmt, true, S, E, Ctx));
3203 return false;
3204 }
David Peixottoae5ba762014-07-18 16:05:14 +00003205 APInt Simm = APInt(64, Imm << ShiftAmt);
3206 // check if the immediate is an unsigned or signed 32-bit int for W regs
3207 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3208 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003209 }
3210 // 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 +00003211 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003212 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003213 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3214 return false;
3215 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003216 }
3217}
3218
3219/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3220/// operands.
3221bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3222 StringRef Name, SMLoc NameLoc,
3223 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003224 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003225 Name = StringSwitch<StringRef>(Name.lower())
3226 .Case("beq", "b.eq")
3227 .Case("bne", "b.ne")
3228 .Case("bhs", "b.hs")
3229 .Case("bcs", "b.cs")
3230 .Case("blo", "b.lo")
3231 .Case("bcc", "b.cc")
3232 .Case("bmi", "b.mi")
3233 .Case("bpl", "b.pl")
3234 .Case("bvs", "b.vs")
3235 .Case("bvc", "b.vc")
3236 .Case("bhi", "b.hi")
3237 .Case("bls", "b.ls")
3238 .Case("bge", "b.ge")
3239 .Case("blt", "b.lt")
3240 .Case("bgt", "b.gt")
3241 .Case("ble", "b.le")
3242 .Case("bal", "b.al")
3243 .Case("bnv", "b.nv")
3244 .Default(Name);
3245
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003246 // First check for the AArch64-specific .req directive.
3247 if (Parser.getTok().is(AsmToken::Identifier) &&
3248 Parser.getTok().getIdentifier() == ".req") {
3249 parseDirectiveReq(Name, NameLoc);
3250 // We always return 'error' for this, as we're done with this
3251 // statement and don't need to match the 'instruction."
3252 return true;
3253 }
3254
Tim Northover3b0846e2014-05-24 12:50:23 +00003255 // Create the leading tokens for the mnemonic, split by '.' characters.
3256 size_t Start = 0, Next = Name.find('.');
3257 StringRef Head = Name.slice(Start, Next);
3258
3259 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003260 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3261 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003262
3263 Operands.push_back(
3264 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3265 Mnemonic = Head;
3266
3267 // Handle condition codes for a branch mnemonic
3268 if (Head == "b" && Next != StringRef::npos) {
3269 Start = Next;
3270 Next = Name.find('.', Start + 1);
3271 Head = Name.slice(Start + 1, Next);
3272
3273 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3274 (Head.data() - Name.data()));
3275 AArch64CC::CondCode CC = parseCondCodeString(Head);
3276 if (CC == AArch64CC::Invalid)
3277 return Error(SuffixLoc, "invalid condition code");
3278 Operands.push_back(
3279 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3280 Operands.push_back(
3281 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3282 }
3283
3284 // Add the remaining tokens in the mnemonic.
3285 while (Next != StringRef::npos) {
3286 Start = Next;
3287 Next = Name.find('.', Start + 1);
3288 Head = Name.slice(Start, Next);
3289 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3290 (Head.data() - Name.data()) + 1);
3291 Operands.push_back(
3292 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3293 }
3294
3295 // Conditional compare instructions have a Condition Code operand, which needs
3296 // to be parsed and an immediate operand created.
3297 bool condCodeFourthOperand =
3298 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3299 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3300 Head == "csinc" || Head == "csinv" || Head == "csneg");
3301
3302 // These instructions are aliases to some of the conditional select
3303 // instructions. However, the condition code is inverted in the aliased
3304 // instruction.
3305 //
3306 // FIXME: Is this the correct way to handle these? Or should the parser
3307 // generate the aliased instructions directly?
3308 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3309 bool condCodeThirdOperand =
3310 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3311
3312 // Read the remaining operands.
3313 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3314 // Read the first operand.
3315 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003316 return true;
3317 }
3318
3319 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003320 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003321 // Parse and remember the operand.
3322 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3323 (N == 3 && condCodeThirdOperand) ||
3324 (N == 2 && condCodeSecondOperand),
3325 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003326 return true;
3327 }
3328
3329 // After successfully parsing some operands there are two special cases to
3330 // consider (i.e. notional operands not separated by commas). Both are due
3331 // to memory specifiers:
3332 // + An RBrac will end an address for load/store/prefetch
3333 // + An '!' will indicate a pre-indexed operation.
3334 //
3335 // It's someone else's responsibility to make sure these tokens are sane
3336 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003337
Nirav Davee833c6c2016-11-08 18:31:04 +00003338 SMLoc RLoc = Parser.getTok().getLoc();
3339 if (parseOptionalToken(AsmToken::RBrac))
3340 Operands.push_back(
3341 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3342 SMLoc ELoc = Parser.getTok().getLoc();
3343 if (parseOptionalToken(AsmToken::Exclaim))
3344 Operands.push_back(
3345 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003346
3347 ++N;
3348 }
3349 }
3350
Nirav Davee833c6c2016-11-08 18:31:04 +00003351 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3352 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003353
Tim Northover3b0846e2014-05-24 12:50:23 +00003354 return false;
3355}
3356
3357// FIXME: This entire function is a giant hack to provide us with decent
3358// operand range validation/diagnostics until TableGen/MC can be extended
3359// to support autogeneration of this kind of validation.
3360bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3361 SmallVectorImpl<SMLoc> &Loc) {
3362 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3363 // Check for indexed addressing modes w/ the base register being the
3364 // same as a destination/source register or pair load where
3365 // the Rt == Rt2. All of those are undefined behaviour.
3366 switch (Inst.getOpcode()) {
3367 case AArch64::LDPSWpre:
3368 case AArch64::LDPWpost:
3369 case AArch64::LDPWpre:
3370 case AArch64::LDPXpost:
3371 case AArch64::LDPXpre: {
3372 unsigned Rt = Inst.getOperand(1).getReg();
3373 unsigned Rt2 = Inst.getOperand(2).getReg();
3374 unsigned Rn = Inst.getOperand(3).getReg();
3375 if (RI->isSubRegisterEq(Rn, Rt))
3376 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3377 "is also a destination");
3378 if (RI->isSubRegisterEq(Rn, Rt2))
3379 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3380 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003381 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003382 }
3383 case AArch64::LDPDi:
3384 case AArch64::LDPQi:
3385 case AArch64::LDPSi:
3386 case AArch64::LDPSWi:
3387 case AArch64::LDPWi:
3388 case AArch64::LDPXi: {
3389 unsigned Rt = Inst.getOperand(0).getReg();
3390 unsigned Rt2 = Inst.getOperand(1).getReg();
3391 if (Rt == Rt2)
3392 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3393 break;
3394 }
3395 case AArch64::LDPDpost:
3396 case AArch64::LDPDpre:
3397 case AArch64::LDPQpost:
3398 case AArch64::LDPQpre:
3399 case AArch64::LDPSpost:
3400 case AArch64::LDPSpre:
3401 case AArch64::LDPSWpost: {
3402 unsigned Rt = Inst.getOperand(1).getReg();
3403 unsigned Rt2 = Inst.getOperand(2).getReg();
3404 if (Rt == Rt2)
3405 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3406 break;
3407 }
3408 case AArch64::STPDpost:
3409 case AArch64::STPDpre:
3410 case AArch64::STPQpost:
3411 case AArch64::STPQpre:
3412 case AArch64::STPSpost:
3413 case AArch64::STPSpre:
3414 case AArch64::STPWpost:
3415 case AArch64::STPWpre:
3416 case AArch64::STPXpost:
3417 case AArch64::STPXpre: {
3418 unsigned Rt = Inst.getOperand(1).getReg();
3419 unsigned Rt2 = Inst.getOperand(2).getReg();
3420 unsigned Rn = Inst.getOperand(3).getReg();
3421 if (RI->isSubRegisterEq(Rn, Rt))
3422 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3423 "is also a source");
3424 if (RI->isSubRegisterEq(Rn, Rt2))
3425 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3426 "is also a source");
3427 break;
3428 }
3429 case AArch64::LDRBBpre:
3430 case AArch64::LDRBpre:
3431 case AArch64::LDRHHpre:
3432 case AArch64::LDRHpre:
3433 case AArch64::LDRSBWpre:
3434 case AArch64::LDRSBXpre:
3435 case AArch64::LDRSHWpre:
3436 case AArch64::LDRSHXpre:
3437 case AArch64::LDRSWpre:
3438 case AArch64::LDRWpre:
3439 case AArch64::LDRXpre:
3440 case AArch64::LDRBBpost:
3441 case AArch64::LDRBpost:
3442 case AArch64::LDRHHpost:
3443 case AArch64::LDRHpost:
3444 case AArch64::LDRSBWpost:
3445 case AArch64::LDRSBXpost:
3446 case AArch64::LDRSHWpost:
3447 case AArch64::LDRSHXpost:
3448 case AArch64::LDRSWpost:
3449 case AArch64::LDRWpost:
3450 case AArch64::LDRXpost: {
3451 unsigned Rt = Inst.getOperand(1).getReg();
3452 unsigned Rn = Inst.getOperand(2).getReg();
3453 if (RI->isSubRegisterEq(Rn, Rt))
3454 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3455 "is also a source");
3456 break;
3457 }
3458 case AArch64::STRBBpost:
3459 case AArch64::STRBpost:
3460 case AArch64::STRHHpost:
3461 case AArch64::STRHpost:
3462 case AArch64::STRWpost:
3463 case AArch64::STRXpost:
3464 case AArch64::STRBBpre:
3465 case AArch64::STRBpre:
3466 case AArch64::STRHHpre:
3467 case AArch64::STRHpre:
3468 case AArch64::STRWpre:
3469 case AArch64::STRXpre: {
3470 unsigned Rt = Inst.getOperand(1).getReg();
3471 unsigned Rn = Inst.getOperand(2).getReg();
3472 if (RI->isSubRegisterEq(Rn, Rt))
3473 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3474 "is also a source");
3475 break;
3476 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003477 case AArch64::STXRB:
3478 case AArch64::STXRH:
3479 case AArch64::STXRW:
3480 case AArch64::STXRX:
3481 case AArch64::STLXRB:
3482 case AArch64::STLXRH:
3483 case AArch64::STLXRW:
3484 case AArch64::STLXRX: {
3485 unsigned Rs = Inst.getOperand(0).getReg();
3486 unsigned Rt = Inst.getOperand(1).getReg();
3487 unsigned Rn = Inst.getOperand(2).getReg();
3488 if (RI->isSubRegisterEq(Rt, Rs) ||
3489 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3490 return Error(Loc[0],
3491 "unpredictable STXR instruction, status is also a source");
3492 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003493 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003494 case AArch64::STXPW:
3495 case AArch64::STXPX:
3496 case AArch64::STLXPW:
3497 case AArch64::STLXPX: {
3498 unsigned Rs = Inst.getOperand(0).getReg();
3499 unsigned Rt1 = Inst.getOperand(1).getReg();
3500 unsigned Rt2 = Inst.getOperand(2).getReg();
3501 unsigned Rn = Inst.getOperand(3).getReg();
3502 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3503 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3504 return Error(Loc[0],
3505 "unpredictable STXP instruction, status is also a source");
3506 break;
3507 }
3508 }
3509
Tim Northover3b0846e2014-05-24 12:50:23 +00003510
3511 // Now check immediate ranges. Separate from the above as there is overlap
3512 // in the instructions being checked and this keeps the nested conditionals
3513 // to a minimum.
3514 switch (Inst.getOpcode()) {
3515 case AArch64::ADDSWri:
3516 case AArch64::ADDSXri:
3517 case AArch64::ADDWri:
3518 case AArch64::ADDXri:
3519 case AArch64::SUBSWri:
3520 case AArch64::SUBSXri:
3521 case AArch64::SUBWri:
3522 case AArch64::SUBXri: {
3523 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3524 // some slight duplication here.
3525 if (Inst.getOperand(2).isExpr()) {
3526 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3527 AArch64MCExpr::VariantKind ELFRefKind;
3528 MCSymbolRefExpr::VariantKind DarwinRefKind;
3529 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003530 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3531
3532 // Only allow these with ADDXri.
3533 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3534 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3535 Inst.getOpcode() == AArch64::ADDXri)
3536 return false;
3537
3538 // Only allow these with ADDXri/ADDWri
3539 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3540 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3541 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3542 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3543 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3544 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3545 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003546 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3547 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3548 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003549 (Inst.getOpcode() == AArch64::ADDXri ||
3550 Inst.getOpcode() == AArch64::ADDWri))
3551 return false;
3552
3553 // Don't allow symbol refs in the immediate field otherwise
3554 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3555 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3556 // 'cmp w0, 'borked')
3557 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003558 }
Diana Picusc93518d2016-10-11 09:17:47 +00003559 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003560 }
3561 return false;
3562 }
3563 default:
3564 return false;
3565 }
3566}
3567
Craig Topper05515562017-10-26 06:46:41 +00003568static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3569 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003570
3571bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3572 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003573 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003574 case Match_InvalidTiedOperand:
3575 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003576 case Match_MissingFeature:
3577 return Error(Loc,
3578 "instruction requires a CPU feature not currently enabled");
3579 case Match_InvalidOperand:
3580 return Error(Loc, "invalid operand for instruction");
3581 case Match_InvalidSuffix:
3582 return Error(Loc, "invalid type suffix for instruction");
3583 case Match_InvalidCondCode:
3584 return Error(Loc, "expected AArch64 condition code");
3585 case Match_AddSubRegExtendSmall:
3586 return Error(Loc,
3587 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3588 case Match_AddSubRegExtendLarge:
3589 return Error(Loc,
3590 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3591 case Match_AddSubSecondSource:
3592 return Error(Loc,
3593 "expected compatible register, symbol or integer in range [0, 4095]");
3594 case Match_LogicalSecondSource:
3595 return Error(Loc, "expected compatible register or logical immediate");
3596 case Match_InvalidMovImm32Shift:
3597 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3598 case Match_InvalidMovImm64Shift:
3599 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3600 case Match_AddSubRegShift32:
3601 return Error(Loc,
3602 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3603 case Match_AddSubRegShift64:
3604 return Error(Loc,
3605 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3606 case Match_InvalidFPImm:
3607 return Error(Loc,
3608 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003609 case Match_InvalidMemoryIndexedSImm6:
3610 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003611 case Match_InvalidMemoryIndexedSImm5:
3612 return Error(Loc, "index must be an integer in range [-16, 15].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003613 case Match_InvalidMemoryIndexedSImm9:
3614 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003615 case Match_InvalidMemoryIndexedSImm10:
3616 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003617 case Match_InvalidMemoryIndexed4SImm7:
3618 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3619 case Match_InvalidMemoryIndexed8SImm7:
3620 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3621 case Match_InvalidMemoryIndexed16SImm7:
3622 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3623 case Match_InvalidMemoryWExtend8:
3624 return Error(Loc,
3625 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3626 case Match_InvalidMemoryWExtend16:
3627 return Error(Loc,
3628 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3629 case Match_InvalidMemoryWExtend32:
3630 return Error(Loc,
3631 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3632 case Match_InvalidMemoryWExtend64:
3633 return Error(Loc,
3634 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3635 case Match_InvalidMemoryWExtend128:
3636 return Error(Loc,
3637 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3638 case Match_InvalidMemoryXExtend8:
3639 return Error(Loc,
3640 "expected 'lsl' or 'sxtx' with optional shift of #0");
3641 case Match_InvalidMemoryXExtend16:
3642 return Error(Loc,
3643 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3644 case Match_InvalidMemoryXExtend32:
3645 return Error(Loc,
3646 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3647 case Match_InvalidMemoryXExtend64:
3648 return Error(Loc,
3649 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3650 case Match_InvalidMemoryXExtend128:
3651 return Error(Loc,
3652 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3653 case Match_InvalidMemoryIndexed1:
3654 return Error(Loc, "index must be an integer in range [0, 4095].");
3655 case Match_InvalidMemoryIndexed2:
3656 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3657 case Match_InvalidMemoryIndexed4:
3658 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3659 case Match_InvalidMemoryIndexed8:
3660 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3661 case Match_InvalidMemoryIndexed16:
3662 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003663 case Match_InvalidImm0_1:
3664 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003665 case Match_InvalidImm0_7:
3666 return Error(Loc, "immediate must be an integer in range [0, 7].");
3667 case Match_InvalidImm0_15:
3668 return Error(Loc, "immediate must be an integer in range [0, 15].");
3669 case Match_InvalidImm0_31:
3670 return Error(Loc, "immediate must be an integer in range [0, 31].");
3671 case Match_InvalidImm0_63:
3672 return Error(Loc, "immediate must be an integer in range [0, 63].");
3673 case Match_InvalidImm0_127:
3674 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003675 case Match_InvalidImm0_255:
3676 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003677 case Match_InvalidImm0_65535:
3678 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3679 case Match_InvalidImm1_8:
3680 return Error(Loc, "immediate must be an integer in range [1, 8].");
3681 case Match_InvalidImm1_16:
3682 return Error(Loc, "immediate must be an integer in range [1, 16].");
3683 case Match_InvalidImm1_32:
3684 return Error(Loc, "immediate must be an integer in range [1, 32].");
3685 case Match_InvalidImm1_64:
3686 return Error(Loc, "immediate must be an integer in range [1, 64].");
3687 case Match_InvalidIndex1:
3688 return Error(Loc, "expected lane specifier '[1]'");
3689 case Match_InvalidIndexB:
3690 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3691 case Match_InvalidIndexH:
3692 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3693 case Match_InvalidIndexS:
3694 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3695 case Match_InvalidIndexD:
3696 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3697 case Match_InvalidLabel:
3698 return Error(Loc, "expected label or encodable integer pc offset");
3699 case Match_MRS:
3700 return Error(Loc, "expected readable system register");
3701 case Match_MSR:
3702 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003703 case Match_InvalidComplexRotationEven:
3704 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3705 case Match_InvalidComplexRotationOdd:
3706 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003707 case Match_MnemonicFail: {
3708 std::string Suggestion = AArch64MnemonicSpellCheck(
3709 ((AArch64Operand &)*Operands[0]).getToken(),
3710 ComputeAvailableFeatures(STI->getFeatureBits()));
3711 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3712 }
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003713 case Match_InvalidSVEPattern:
3714 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003715 case Match_InvalidSVEPredicateAnyReg:
3716 case Match_InvalidSVEPredicateBReg:
3717 case Match_InvalidSVEPredicateHReg:
3718 case Match_InvalidSVEPredicateSReg:
3719 case Match_InvalidSVEPredicateDReg:
3720 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003721 case Match_InvalidSVEPredicate3bAnyReg:
3722 case Match_InvalidSVEPredicate3bBReg:
3723 case Match_InvalidSVEPredicate3bHReg:
3724 case Match_InvalidSVEPredicate3bSReg:
3725 case Match_InvalidSVEPredicate3bDReg:
3726 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003727 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003728 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003729 }
3730}
3731
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003732static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003733
3734bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3735 OperandVector &Operands,
3736 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003737 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003738 bool MatchingInlineAsm) {
3739 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003740 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3741 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003742
David Blaikie960ea3f2014-06-08 16:18:35 +00003743 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003744 unsigned NumOperands = Operands.size();
3745
3746 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003747 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3748 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003749 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003750 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003751 if (Op3CE) {
3752 uint64_t Op3Val = Op3CE->getValue();
3753 uint64_t NewOp3Val = 0;
3754 uint64_t NewOp4Val = 0;
3755 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003756 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003757 NewOp3Val = (32 - Op3Val) & 0x1f;
3758 NewOp4Val = 31 - Op3Val;
3759 } else {
3760 NewOp3Val = (64 - Op3Val) & 0x3f;
3761 NewOp4Val = 63 - Op3Val;
3762 }
3763
Jim Grosbach13760bd2015-05-30 01:25:56 +00003764 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3765 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003766
3767 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003768 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003769 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003770 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3771 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3772 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003773 }
3774 }
Tim Northover03b99f62015-04-30 18:28:58 +00003775 } else if (NumOperands == 4 && Tok == "bfc") {
3776 // FIXME: Horrible hack to handle BFC->BFM alias.
3777 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3778 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3779 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3780
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003781 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003782 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3783 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3784
3785 if (LSBCE && WidthCE) {
3786 uint64_t LSB = LSBCE->getValue();
3787 uint64_t Width = WidthCE->getValue();
3788
3789 uint64_t RegWidth = 0;
3790 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3791 Op1.getReg()))
3792 RegWidth = 64;
3793 else
3794 RegWidth = 32;
3795
3796 if (LSB >= RegWidth)
3797 return Error(LSBOp.getStartLoc(),
3798 "expected integer in range [0, 31]");
3799 if (Width < 1 || Width > RegWidth)
3800 return Error(WidthOp.getStartLoc(),
3801 "expected integer in range [1, 32]");
3802
3803 uint64_t ImmR = 0;
3804 if (RegWidth == 32)
3805 ImmR = (32 - LSB) & 0x1f;
3806 else
3807 ImmR = (64 - LSB) & 0x3f;
3808
3809 uint64_t ImmS = Width - 1;
3810
3811 if (ImmR != 0 && ImmS >= ImmR)
3812 return Error(WidthOp.getStartLoc(),
3813 "requested insert overflows register");
3814
Jim Grosbach13760bd2015-05-30 01:25:56 +00003815 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3816 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003817 Operands[0] = AArch64Operand::CreateToken(
3818 "bfm", false, Op.getStartLoc(), getContext());
3819 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003820 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3821 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003822 Operands[3] = AArch64Operand::CreateImm(
3823 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3824 Operands.emplace_back(
3825 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3826 WidthOp.getEndLoc(), getContext()));
3827 }
3828 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003829 } else if (NumOperands == 5) {
3830 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3831 // UBFIZ -> UBFM aliases.
3832 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003833 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3834 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3835 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003836
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003837 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003838 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3839 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003840
3841 if (Op3CE && Op4CE) {
3842 uint64_t Op3Val = Op3CE->getValue();
3843 uint64_t Op4Val = Op4CE->getValue();
3844
3845 uint64_t RegWidth = 0;
3846 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003847 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003848 RegWidth = 64;
3849 else
3850 RegWidth = 32;
3851
3852 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003853 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003854 "expected integer in range [0, 31]");
3855 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003856 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003857 "expected integer in range [1, 32]");
3858
3859 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003860 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003861 NewOp3Val = (32 - Op3Val) & 0x1f;
3862 else
3863 NewOp3Val = (64 - Op3Val) & 0x3f;
3864
3865 uint64_t NewOp4Val = Op4Val - 1;
3866
3867 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003868 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003869 "requested insert overflows register");
3870
3871 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003872 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003873 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003874 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003875 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003876 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003877 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003878 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003879 if (Tok == "bfi")
3880 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003881 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003882 else if (Tok == "sbfiz")
3883 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003884 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003885 else if (Tok == "ubfiz")
3886 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003887 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003888 else
3889 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003890 }
3891 }
3892
3893 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3894 // UBFX -> UBFM aliases.
3895 } else if (NumOperands == 5 &&
3896 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003897 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3898 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3899 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003900
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003901 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003902 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3903 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003904
3905 if (Op3CE && Op4CE) {
3906 uint64_t Op3Val = Op3CE->getValue();
3907 uint64_t Op4Val = Op4CE->getValue();
3908
3909 uint64_t RegWidth = 0;
3910 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003911 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003912 RegWidth = 64;
3913 else
3914 RegWidth = 32;
3915
3916 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003917 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003918 "expected integer in range [0, 31]");
3919 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003920 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003921 "expected integer in range [1, 32]");
3922
3923 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3924
3925 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003926 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003927 "requested extract overflows register");
3928
3929 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003930 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003931 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003932 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003933 if (Tok == "bfxil")
3934 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003935 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003936 else if (Tok == "sbfx")
3937 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003938 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003939 else if (Tok == "ubfx")
3940 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003941 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003942 else
3943 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003944 }
3945 }
3946 }
3947 }
Tim Northover9097a072017-12-18 10:36:00 +00003948
3949 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
3950 // instruction for FP registers correctly in some rare circumstances. Convert
3951 // it to a safe instruction and warn (because silently changing someone's
3952 // assembly is rude).
3953 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
3954 NumOperands == 4 && Tok == "movi") {
3955 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3956 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3957 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3958 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
3959 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
3960 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
3961 if (Suffix.lower() == ".2d" &&
3962 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
3963 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
3964 " correctly on this CPU, converting to equivalent movi.16b");
3965 // Switch the suffix to .16b.
3966 unsigned Idx = Op1.isToken() ? 1 : 2;
3967 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
3968 getContext());
3969 }
3970 }
3971 }
3972
Tim Northover3b0846e2014-05-24 12:50:23 +00003973 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3974 // InstAlias can't quite handle this since the reg classes aren't
3975 // subclasses.
3976 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3977 // The source register can be Wn here, but the matcher expects a
3978 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003979 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003980 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003981 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003982 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3983 Op.getStartLoc(), Op.getEndLoc(),
3984 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003985 }
3986 }
3987 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3988 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003989 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003990 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003991 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003992 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003993 // The source register can be Wn here, but the matcher expects a
3994 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003995 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003996 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003997 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003998 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3999 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004000 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004001 }
4002 }
4003 }
4004 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4005 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004006 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004007 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004008 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004009 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004010 // The source register can be Wn here, but the matcher expects a
4011 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004012 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004013 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004014 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004015 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4016 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004017 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004018 }
4019 }
4020 }
4021
Tim Northover3b0846e2014-05-24 12:50:23 +00004022 MCInst Inst;
4023 // First try to match against the secondary set of tables containing the
4024 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4025 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004026 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004027
4028 // If that fails, try against the alternate table containing long-form NEON:
4029 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004030 if (MatchResult != Match_Success) {
4031 // But first, save the short-form match result: we can use it in case the
4032 // long-form match also fails.
4033 auto ShortFormNEONErrorInfo = ErrorInfo;
4034 auto ShortFormNEONMatchResult = MatchResult;
4035
Tim Northover3b0846e2014-05-24 12:50:23 +00004036 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004037 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004038
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004039 // Now, both matches failed, and the long-form match failed on the mnemonic
4040 // suffix token operand. The short-form match failure is probably more
4041 // relevant: use it instead.
4042 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004043 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004044 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4045 MatchResult = ShortFormNEONMatchResult;
4046 ErrorInfo = ShortFormNEONErrorInfo;
4047 }
4048 }
4049
Tim Northover3b0846e2014-05-24 12:50:23 +00004050 switch (MatchResult) {
4051 case Match_Success: {
4052 // Perform range checking and other semantic validations
4053 SmallVector<SMLoc, 8> OperandLocs;
4054 NumOperands = Operands.size();
4055 for (unsigned i = 1; i < NumOperands; ++i)
4056 OperandLocs.push_back(Operands[i]->getStartLoc());
4057 if (validateInstruction(Inst, OperandLocs))
4058 return true;
4059
4060 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004061 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004062 return false;
4063 }
4064 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004065 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004066 // Special case the error message for the very common case where only
4067 // a single subtarget feature is missing (neon, e.g.).
4068 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004069 uint64_t Mask = 1;
4070 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4071 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004072 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004073 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004074 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004075 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004076 }
4077 return Error(IDLoc, Msg);
4078 }
4079 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004080 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004081 case Match_InvalidOperand: {
4082 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004083
Tim Northover26bb14e2014-08-18 11:49:42 +00004084 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004085 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004086 return Error(IDLoc, "too few operands for instruction",
4087 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004088
David Blaikie960ea3f2014-06-08 16:18:35 +00004089 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004090 if (ErrorLoc == SMLoc())
4091 ErrorLoc = IDLoc;
4092 }
4093 // If the match failed on a suffix token operand, tweak the diagnostic
4094 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004095 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4096 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004097 MatchResult = Match_InvalidSuffix;
4098
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004099 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004100 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004101 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004102 case Match_InvalidMemoryIndexed1:
4103 case Match_InvalidMemoryIndexed2:
4104 case Match_InvalidMemoryIndexed4:
4105 case Match_InvalidMemoryIndexed8:
4106 case Match_InvalidMemoryIndexed16:
4107 case Match_InvalidCondCode:
4108 case Match_AddSubRegExtendSmall:
4109 case Match_AddSubRegExtendLarge:
4110 case Match_AddSubSecondSource:
4111 case Match_LogicalSecondSource:
4112 case Match_AddSubRegShift32:
4113 case Match_AddSubRegShift64:
4114 case Match_InvalidMovImm32Shift:
4115 case Match_InvalidMovImm64Shift:
4116 case Match_InvalidFPImm:
4117 case Match_InvalidMemoryWExtend8:
4118 case Match_InvalidMemoryWExtend16:
4119 case Match_InvalidMemoryWExtend32:
4120 case Match_InvalidMemoryWExtend64:
4121 case Match_InvalidMemoryWExtend128:
4122 case Match_InvalidMemoryXExtend8:
4123 case Match_InvalidMemoryXExtend16:
4124 case Match_InvalidMemoryXExtend32:
4125 case Match_InvalidMemoryXExtend64:
4126 case Match_InvalidMemoryXExtend128:
Sander de Smalen909cf952018-01-19 15:22:00 +00004127 case Match_InvalidMemoryIndexedSImm6:
Tim Northover3b0846e2014-05-24 12:50:23 +00004128 case Match_InvalidMemoryIndexed4SImm7:
4129 case Match_InvalidMemoryIndexed8SImm7:
4130 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen30fda452018-04-10 07:01:53 +00004131 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004132 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004133 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004134 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004135 case Match_InvalidImm0_7:
4136 case Match_InvalidImm0_15:
4137 case Match_InvalidImm0_31:
4138 case Match_InvalidImm0_63:
4139 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004140 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004141 case Match_InvalidImm0_65535:
4142 case Match_InvalidImm1_8:
4143 case Match_InvalidImm1_16:
4144 case Match_InvalidImm1_32:
4145 case Match_InvalidImm1_64:
4146 case Match_InvalidIndex1:
4147 case Match_InvalidIndexB:
4148 case Match_InvalidIndexH:
4149 case Match_InvalidIndexS:
4150 case Match_InvalidIndexD:
4151 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004152 case Match_InvalidComplexRotationEven:
4153 case Match_InvalidComplexRotationOdd:
Sander de Smalencd6be962017-12-20 11:02:42 +00004154 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004155 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004156 case Match_InvalidSVEPredicateBReg:
4157 case Match_InvalidSVEPredicateHReg:
4158 case Match_InvalidSVEPredicateSReg:
4159 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004160 case Match_InvalidSVEPredicate3bAnyReg:
4161 case Match_InvalidSVEPredicate3bBReg:
4162 case Match_InvalidSVEPredicate3bHReg:
4163 case Match_InvalidSVEPredicate3bSReg:
4164 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004165 case Match_MSR:
4166 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004167 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004168 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004169 // Any time we get here, there's nothing fancy to do. Just get the
4170 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004171 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004172 if (ErrorLoc == SMLoc())
4173 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004174 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004175 }
4176 }
4177
4178 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004179}
4180
4181/// ParseDirective parses the arm specific directives
4182bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004183 const MCObjectFileInfo::Environment Format =
4184 getContext().getObjectFileInfo()->getObjectFileType();
4185 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4186 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004187
Tim Northover3b0846e2014-05-24 12:50:23 +00004188 StringRef IDVal = DirectiveID.getIdentifier();
4189 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004190 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004191 parseDirectiveArch(Loc);
4192 else if (IDVal == ".cpu")
4193 parseDirectiveCPU(Loc);
4194 else if (IDVal == ".hword")
4195 parseDirectiveWord(2, Loc);
4196 else if (IDVal == ".word")
4197 parseDirectiveWord(4, Loc);
4198 else if (IDVal == ".xword")
4199 parseDirectiveWord(8, Loc);
4200 else if (IDVal == ".tlsdesccall")
4201 parseDirectiveTLSDescCall(Loc);
4202 else if (IDVal == ".ltorg" || IDVal == ".pool")
4203 parseDirectiveLtorg(Loc);
4204 else if (IDVal == ".unreq")
4205 parseDirectiveUnreq(Loc);
4206 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004207 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004208 parseDirectiveInst(Loc);
4209 else
4210 return true;
4211 } else if (IDVal == MCLOHDirectiveName())
4212 parseDirectiveLOH(IDVal, Loc);
4213 else
4214 return true;
4215 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004216}
4217
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004218static const struct {
4219 const char *Name;
4220 const FeatureBitset Features;
4221} ExtensionMap[] = {
4222 { "crc", {AArch64::FeatureCRC} },
4223 { "crypto", {AArch64::FeatureCrypto} },
4224 { "fp", {AArch64::FeatureFPARMv8} },
4225 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004226 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004227 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004228
4229 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004230 { "pan", {} },
4231 { "lor", {} },
4232 { "rdma", {} },
4233 { "profile", {} },
4234};
4235
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004236/// parseDirectiveArch
4237/// ::= .arch token
4238bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4239 SMLoc ArchLoc = getLoc();
4240
4241 StringRef Arch, ExtensionString;
4242 std::tie(Arch, ExtensionString) =
4243 getParser().parseStringToEndOfStatement().trim().split('+');
4244
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004245 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4246 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004247 return Error(ArchLoc, "unknown arch name");
4248
4249 if (parseToken(AsmToken::EndOfStatement))
4250 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004251
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004252 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004253 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004254 AArch64::getArchFeatures(ID, AArch64Features);
4255 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4256 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004257
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004258 MCSubtargetInfo &STI = copySTI();
4259 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4260 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4261
4262 SmallVector<StringRef, 4> RequestedExtensions;
4263 if (!ExtensionString.empty())
4264 ExtensionString.split(RequestedExtensions, '+');
4265
4266 FeatureBitset Features = STI.getFeatureBits();
4267 for (auto Name : RequestedExtensions) {
4268 bool EnableFeature = true;
4269
4270 if (Name.startswith_lower("no")) {
4271 EnableFeature = false;
4272 Name = Name.substr(2);
4273 }
4274
4275 for (const auto &Extension : ExtensionMap) {
4276 if (Extension.Name != Name)
4277 continue;
4278
4279 if (Extension.Features.none())
4280 report_fatal_error("unsupported architectural extension: " + Name);
4281
4282 FeatureBitset ToggleFeatures = EnableFeature
4283 ? (~Features & Extension.Features)
4284 : ( Features & Extension.Features);
4285 uint64_t Features =
4286 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4287 setAvailableFeatures(Features);
4288 break;
4289 }
4290 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004291 return false;
4292}
4293
Tim Northover8b96c7e2017-05-15 19:42:15 +00004294static SMLoc incrementLoc(SMLoc L, int Offset) {
4295 return SMLoc::getFromPointer(L.getPointer() + Offset);
4296}
4297
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004298/// parseDirectiveCPU
4299/// ::= .cpu id
4300bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004301 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004302
4303 StringRef CPU, ExtensionString;
4304 std::tie(CPU, ExtensionString) =
4305 getParser().parseStringToEndOfStatement().trim().split('+');
4306
Nirav Davee833c6c2016-11-08 18:31:04 +00004307 if (parseToken(AsmToken::EndOfStatement))
4308 return true;
4309
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004310 SmallVector<StringRef, 4> RequestedExtensions;
4311 if (!ExtensionString.empty())
4312 ExtensionString.split(RequestedExtensions, '+');
4313
4314 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4315 // once that is tablegen'ed
4316 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004317 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004318 return false;
4319 }
4320
4321 MCSubtargetInfo &STI = copySTI();
4322 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004323 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004324
4325 FeatureBitset Features = STI.getFeatureBits();
4326 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004327 // Advance source location past '+'.
4328 CurLoc = incrementLoc(CurLoc, 1);
4329
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004330 bool EnableFeature = true;
4331
4332 if (Name.startswith_lower("no")) {
4333 EnableFeature = false;
4334 Name = Name.substr(2);
4335 }
4336
Tim Northover8b96c7e2017-05-15 19:42:15 +00004337 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004338 for (const auto &Extension : ExtensionMap) {
4339 if (Extension.Name != Name)
4340 continue;
4341
4342 if (Extension.Features.none())
4343 report_fatal_error("unsupported architectural extension: " + Name);
4344
4345 FeatureBitset ToggleFeatures = EnableFeature
4346 ? (~Features & Extension.Features)
4347 : ( Features & Extension.Features);
4348 uint64_t Features =
4349 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4350 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004351 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004352
4353 break;
4354 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004355
4356 if (!FoundExtension)
4357 Error(CurLoc, "unsupported architectural extension");
4358
4359 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004360 }
4361 return false;
4362}
4363
Tim Northover3b0846e2014-05-24 12:50:23 +00004364/// parseDirectiveWord
4365/// ::= .word [ expression (, expression)* ]
4366bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004367 auto parseOp = [&]() -> bool {
4368 const MCExpr *Value;
4369 if (getParser().parseExpression(Value))
4370 return true;
4371 getParser().getStreamer().EmitValue(Value, Size, L);
4372 return false;
4373 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004374
Nirav Davee833c6c2016-11-08 18:31:04 +00004375 if (parseMany(parseOp))
4376 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004377 return false;
4378}
4379
Chad Rosierdcd2a302014-10-22 20:35:57 +00004380/// parseDirectiveInst
4381/// ::= .inst opcode [, ...]
4382bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004383 if (getLexer().is(AsmToken::EndOfStatement))
4384 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004385
Nirav Davee833c6c2016-11-08 18:31:04 +00004386 auto parseOp = [&]() -> bool {
4387 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004388 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004389 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4390 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004391 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004392 if (check(!Value, L, "expected constant expression"))
4393 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004394 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004395 return false;
4396 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004397
Nirav Davee833c6c2016-11-08 18:31:04 +00004398 if (parseMany(parseOp))
4399 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004400 return false;
4401}
4402
Tim Northover3b0846e2014-05-24 12:50:23 +00004403// parseDirectiveTLSDescCall:
4404// ::= .tlsdesccall symbol
4405bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4406 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004407 if (check(getParser().parseIdentifier(Name), L,
4408 "expected symbol after directive") ||
4409 parseToken(AsmToken::EndOfStatement))
4410 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004411
Jim Grosbach6f482002015-05-18 18:43:14 +00004412 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004413 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4414 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004415
4416 MCInst Inst;
4417 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004418 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004419
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004420 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004421 return false;
4422}
4423
4424/// ::= .loh <lohName | lohId> label1, ..., labelN
4425/// The number of arguments depends on the loh identifier.
4426bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004427 MCLOHType Kind;
4428 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4429 if (getParser().getTok().isNot(AsmToken::Integer))
4430 return TokError("expected an identifier or a number in directive");
4431 // We successfully get a numeric value for the identifier.
4432 // Check if it is valid.
4433 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004434 if (Id <= -1U && !isValidMCLOHType(Id))
4435 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004436 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004437 } else {
4438 StringRef Name = getTok().getIdentifier();
4439 // We successfully parse an identifier.
4440 // Check if it is a recognized one.
4441 int Id = MCLOHNameToId(Name);
4442
4443 if (Id == -1)
4444 return TokError("invalid identifier in directive");
4445 Kind = (MCLOHType)Id;
4446 }
4447 // Consume the identifier.
4448 Lex();
4449 // Get the number of arguments of this LOH.
4450 int NbArgs = MCLOHIdToNbArgs(Kind);
4451
4452 assert(NbArgs != -1 && "Invalid number of arguments");
4453
4454 SmallVector<MCSymbol *, 3> Args;
4455 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4456 StringRef Name;
4457 if (getParser().parseIdentifier(Name))
4458 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004459 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004460
4461 if (Idx + 1 == NbArgs)
4462 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004463 if (parseToken(AsmToken::Comma,
4464 "unexpected token in '" + Twine(IDVal) + "' directive"))
4465 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004466 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004467 if (parseToken(AsmToken::EndOfStatement,
4468 "unexpected token in '" + Twine(IDVal) + "' directive"))
4469 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004470
4471 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4472 return false;
4473}
4474
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004475/// parseDirectiveLtorg
4476/// ::= .ltorg | .pool
4477bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004478 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4479 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004480 getTargetStreamer().emitCurrentConstantPool();
4481 return false;
4482}
4483
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004484/// parseDirectiveReq
4485/// ::= name .req registername
4486bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004487 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004488 Parser.Lex(); // Eat the '.req' token.
4489 SMLoc SRegLoc = getLoc();
Sander de Smalen8e607342017-11-15 15:44:43 +00004490 int RegNum = tryParseRegister();
Florian Hahnc4422242017-11-07 13:07:50 +00004491 RegKind RegisterKind = RegKind::Scalar;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004492
Sander de Smalen8e607342017-11-15 15:44:43 +00004493 if (RegNum == -1) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004494 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004495 RegisterKind = RegKind::NeonVector;
Sander de Smalen73937b72018-04-11 07:36:10 +00004496 OperandMatchResultTy Res =
4497 tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
4498
4499 if (Res == MatchOperand_ParseFail)
4500 return true;
4501
4502 if (Res == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004503 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004504 }
4505
Sander de Smalen8e607342017-11-15 15:44:43 +00004506 if (RegNum == -1) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004507 StringRef Kind;
4508 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen8e607342017-11-15 15:44:43 +00004509 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004510 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004511
4512 if (Res == MatchOperand_ParseFail)
4513 return true;
4514
4515 if (Res == MatchOperand_Success && !Kind.empty())
4516 return Error(SRegLoc,
4517 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004518 }
4519
Sander de Smalencd6be962017-12-20 11:02:42 +00004520 if (RegNum == -1) {
4521 StringRef Kind;
4522 RegisterKind = RegKind::SVEPredicateVector;
4523 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004524 tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004525
4526 if (Res == MatchOperand_ParseFail)
4527 return true;
4528
4529 if (Res == MatchOperand_Success && !Kind.empty())
4530 return Error(SRegLoc,
4531 "sve predicate register without type specifier expected");
4532 }
4533
Sander de Smalen8e607342017-11-15 15:44:43 +00004534 if (RegNum == -1)
Nirav Dave2364748a2016-09-16 18:30:20 +00004535 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004536
4537 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004538 if (parseToken(AsmToken::EndOfStatement,
4539 "unexpected input in .req directive"))
4540 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004541
Sander de Smalen8e607342017-11-15 15:44:43 +00004542 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004543 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004544 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4545
Nirav Dave2364748a2016-09-16 18:30:20 +00004546 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004547}
4548
4549/// parseDirectiveUneq
4550/// ::= .unreq registername
4551bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004552 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004553 if (getTok().isNot(AsmToken::Identifier))
4554 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004555 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4556 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004557 if (parseToken(AsmToken::EndOfStatement))
4558 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004559 return false;
4560}
4561
Tim Northover3b0846e2014-05-24 12:50:23 +00004562bool
4563AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4564 AArch64MCExpr::VariantKind &ELFRefKind,
4565 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4566 int64_t &Addend) {
4567 ELFRefKind = AArch64MCExpr::VK_INVALID;
4568 DarwinRefKind = MCSymbolRefExpr::VK_None;
4569 Addend = 0;
4570
4571 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4572 ELFRefKind = AE->getKind();
4573 Expr = AE->getSubExpr();
4574 }
4575
4576 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4577 if (SE) {
4578 // It's a simple symbol reference with no addend.
4579 DarwinRefKind = SE->getKind();
4580 return true;
4581 }
4582
4583 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4584 if (!BE)
4585 return false;
4586
4587 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4588 if (!SE)
4589 return false;
4590 DarwinRefKind = SE->getKind();
4591
4592 if (BE->getOpcode() != MCBinaryExpr::Add &&
4593 BE->getOpcode() != MCBinaryExpr::Sub)
4594 return false;
4595
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004596 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004597 // on here than we can deal with.
4598 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4599 if (!AddendExpr)
4600 return false;
4601
4602 Addend = AddendExpr->getValue();
4603 if (BE->getOpcode() == MCBinaryExpr::Sub)
4604 Addend = -Addend;
4605
4606 // It's some symbol reference + a constant addend, but really
4607 // shouldn't use both Darwin and ELF syntax.
4608 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4609 DarwinRefKind == MCSymbolRefExpr::VK_None;
4610}
4611
4612/// Force static initialization.
4613extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004614 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4615 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4616 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004617}
4618
4619#define GET_REGISTER_MATCHER
4620#define GET_SUBTARGET_FEATURE_NAME
4621#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004622#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004623#include "AArch64GenAsmMatcher.inc"
4624
4625// Define this matcher function after the auto-generated include so we
4626// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004627unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004628 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004629 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004630 // If the kind is a token for a literal immediate, check if our asm
4631 // operand matches. This is for InstAliases which have a fixed-value
4632 // immediate in the syntax.
4633 int64_t ExpectedVal;
4634 switch (Kind) {
4635 default:
4636 return Match_InvalidOperand;
4637 case MCK__35_0:
4638 ExpectedVal = 0;
4639 break;
4640 case MCK__35_1:
4641 ExpectedVal = 1;
4642 break;
4643 case MCK__35_12:
4644 ExpectedVal = 12;
4645 break;
4646 case MCK__35_16:
4647 ExpectedVal = 16;
4648 break;
4649 case MCK__35_2:
4650 ExpectedVal = 2;
4651 break;
4652 case MCK__35_24:
4653 ExpectedVal = 24;
4654 break;
4655 case MCK__35_3:
4656 ExpectedVal = 3;
4657 break;
4658 case MCK__35_32:
4659 ExpectedVal = 32;
4660 break;
4661 case MCK__35_4:
4662 ExpectedVal = 4;
4663 break;
4664 case MCK__35_48:
4665 ExpectedVal = 48;
4666 break;
4667 case MCK__35_6:
4668 ExpectedVal = 6;
4669 break;
4670 case MCK__35_64:
4671 ExpectedVal = 64;
4672 break;
4673 case MCK__35_8:
4674 ExpectedVal = 8;
4675 break;
4676 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004677 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004678 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004679 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004680 if (!CE)
4681 return Match_InvalidOperand;
4682 if (CE->getValue() == ExpectedVal)
4683 return Match_Success;
4684 return Match_InvalidOperand;
4685}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004686
Alex Bradbury58eba092016-11-01 16:32:05 +00004687OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004688AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4689
4690 SMLoc S = getLoc();
4691
4692 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4693 Error(S, "expected register");
4694 return MatchOperand_ParseFail;
4695 }
4696
4697 int FirstReg = tryParseRegister();
4698 if (FirstReg == -1) {
4699 return MatchOperand_ParseFail;
4700 }
4701 const MCRegisterClass &WRegClass =
4702 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4703 const MCRegisterClass &XRegClass =
4704 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4705
4706 bool isXReg = XRegClass.contains(FirstReg),
4707 isWReg = WRegClass.contains(FirstReg);
4708 if (!isXReg && !isWReg) {
4709 Error(S, "expected first even register of a "
4710 "consecutive same-size even/odd register pair");
4711 return MatchOperand_ParseFail;
4712 }
4713
4714 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4715 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4716
4717 if (FirstEncoding & 0x1) {
4718 Error(S, "expected first even register of a "
4719 "consecutive same-size even/odd register pair");
4720 return MatchOperand_ParseFail;
4721 }
4722
4723 SMLoc M = getLoc();
4724 if (getParser().getTok().isNot(AsmToken::Comma)) {
4725 Error(M, "expected comma");
4726 return MatchOperand_ParseFail;
4727 }
4728 // Eat the comma
4729 getParser().Lex();
4730
4731 SMLoc E = getLoc();
4732 int SecondReg = tryParseRegister();
4733 if (SecondReg ==-1) {
4734 return MatchOperand_ParseFail;
4735 }
4736
Eugene Zelenko049b0172017-01-06 00:30:53 +00004737 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004738 (isXReg && !XRegClass.contains(SecondReg)) ||
4739 (isWReg && !WRegClass.contains(SecondReg))) {
4740 Error(E,"expected second odd register of a "
4741 "consecutive same-size even/odd register pair");
4742 return MatchOperand_ParseFail;
4743 }
Joel Jones504bf332016-10-24 13:37:13 +00004744
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004745 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004746 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004747 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4748 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4749 } else {
4750 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4751 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4752 }
4753
Florian Hahnc4422242017-11-07 13:07:50 +00004754 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4755 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004756
4757 return MatchOperand_Success;
4758}
Florian Hahn91f11e52017-11-07 16:45:48 +00004759
4760template <bool ParseSuffix>
4761OperandMatchResultTy
4762AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004763 const SMLoc S = getLoc();
4764 // Check for a SVE vector register specifier first.
Sander de Smalen8e607342017-11-15 15:44:43 +00004765 int RegNum = -1;
Florian Hahn91f11e52017-11-07 16:45:48 +00004766 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004767
Sander de Smalen8e607342017-11-15 15:44:43 +00004768 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004769 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004770
4771 if (Res != MatchOperand_Success)
4772 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004773
4774 if (ParseSuffix && Kind.empty())
4775 return MatchOperand_NoMatch;
4776
Sander de Smalen73937b72018-04-11 07:36:10 +00004777 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
4778 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00004779 return MatchOperand_NoMatch;
4780
Sander de Smalen73937b72018-04-11 07:36:10 +00004781 unsigned ElementWidth = KindRes->second;
4782 Operands.push_back(AArch64Operand::CreateVectorReg(
4783 RegNum, RegKind::SVEDataVector, ElementWidth, S, S,
4784 getContext()));
Florian Hahn91f11e52017-11-07 16:45:48 +00004785
4786 return MatchOperand_Success;
4787}
Sander de Smalen245e0e62018-01-22 10:46:00 +00004788
4789OperandMatchResultTy
4790AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
4791 MCAsmParser &Parser = getParser();
4792
4793 SMLoc SS = getLoc();
4794 const AsmToken &TokE = Parser.getTok();
4795 bool IsHash = TokE.is(AsmToken::Hash);
4796
4797 if (!IsHash && TokE.isNot(AsmToken::Identifier))
4798 return MatchOperand_NoMatch;
4799
4800 int64_t Pattern;
4801 if (IsHash) {
4802 Parser.Lex(); // Eat hash
4803
4804 // Parse the immediate operand.
4805 const MCExpr *ImmVal;
4806 SS = getLoc();
4807 if (Parser.parseExpression(ImmVal))
4808 return MatchOperand_ParseFail;
4809
4810 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4811 if (!MCE)
4812 return MatchOperand_ParseFail;
4813
4814 Pattern = MCE->getValue();
4815 } else {
4816 // Parse the pattern
4817 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
4818 if (!Pat)
4819 return MatchOperand_NoMatch;
4820
4821 Parser.Lex();
4822 Pattern = Pat->Encoding;
4823 assert(Pattern >= 0 && Pattern < 32);
4824 }
4825
4826 Operands.push_back(
4827 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
4828 SS, getLoc(), getContext()));
4829
4830 return MatchOperand_Success;
4831}