blob: ee49f411a49d8dedd3f8740d4e1b94f1127b6d1d [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);
91 bool parseVectorList(OperandVector &Operands);
92 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);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000138 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Florian Hahn91f11e52017-11-07 16:45:48 +0000139 template <bool ParseSuffix>
140 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000141 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000142 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000143
144public:
145 enum AArch64MatchResultTy {
146 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
147#define GET_OPERAND_DIAGNOSTIC_TYPES
148#include "AArch64GenAsmMatcher.inc"
149 };
Joel Jones504bf332016-10-24 13:37:13 +0000150 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000151
Akira Hatanakab11ef082015-11-14 06:35:56 +0000152 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000153 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000154 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000155 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000156 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000157 MCStreamer &S = getParser().getStreamer();
158 if (S.getTargetStreamer() == nullptr)
159 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000160
161 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000162 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000163 }
164
165 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
166 SMLoc NameLoc, OperandVector &Operands) override;
167 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
168 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000169 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000170 unsigned Kind) override;
171
172 static bool classifySymbolRef(const MCExpr *Expr,
173 AArch64MCExpr::VariantKind &ELFRefKind,
174 MCSymbolRefExpr::VariantKind &DarwinRefKind,
175 int64_t &Addend);
176};
Tim Northover3b0846e2014-05-24 12:50:23 +0000177
178/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
179/// instruction.
180class AArch64Operand : public MCParsedAsmOperand {
181private:
182 enum KindTy {
183 k_Immediate,
184 k_ShiftedImm,
185 k_CondCode,
186 k_Register,
187 k_VectorList,
188 k_VectorIndex,
189 k_Token,
190 k_SysReg,
191 k_SysCR,
192 k_Prefetch,
193 k_ShiftExtend,
194 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000195 k_Barrier,
196 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000197 } Kind;
198
199 SMLoc StartLoc, EndLoc;
200
201 struct TokOp {
202 const char *Data;
203 unsigned Length;
204 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
205 };
206
207 struct RegOp {
208 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000209 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000210
211 int ElementWidth;
Tim Northover3b0846e2014-05-24 12:50:23 +0000212 };
213
214 struct VectorListOp {
215 unsigned RegNum;
216 unsigned Count;
217 unsigned NumElements;
218 unsigned ElementKind;
219 };
220
221 struct VectorIndexOp {
222 unsigned Val;
223 };
224
225 struct ImmOp {
226 const MCExpr *Val;
227 };
228
229 struct ShiftedImmOp {
230 const MCExpr *Val;
231 unsigned ShiftAmount;
232 };
233
234 struct CondCodeOp {
235 AArch64CC::CondCode Code;
236 };
237
238 struct FPImmOp {
239 unsigned Val; // Encoded 8-bit representation.
240 };
241
242 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000243 const char *Data;
244 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000245 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000246 };
247
248 struct SysRegOp {
249 const char *Data;
250 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000251 uint32_t MRSReg;
252 uint32_t MSRReg;
253 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000254 };
255
256 struct SysCRImmOp {
257 unsigned Val;
258 };
259
260 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000261 const char *Data;
262 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000263 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000264 };
265
Oliver Stannarda34e4702015-12-01 10:48:51 +0000266 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000267 const char *Data;
268 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000269 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000270 };
271
Tim Northover3b0846e2014-05-24 12:50:23 +0000272 struct ShiftExtendOp {
273 AArch64_AM::ShiftExtendType Type;
274 unsigned Amount;
275 bool HasExplicitAmount;
276 };
277
278 struct ExtendOp {
279 unsigned Val;
280 };
281
282 union {
283 struct TokOp Tok;
284 struct RegOp Reg;
285 struct VectorListOp VectorList;
286 struct VectorIndexOp VectorIndex;
287 struct ImmOp Imm;
288 struct ShiftedImmOp ShiftedImm;
289 struct CondCodeOp CondCode;
290 struct FPImmOp FPImm;
291 struct BarrierOp Barrier;
292 struct SysRegOp SysReg;
293 struct SysCRImmOp SysCRImm;
294 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000295 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000296 struct ShiftExtendOp ShiftExtend;
297 };
298
299 // Keep the MCContext around as the MCExprs may need manipulated during
300 // the add<>Operands() calls.
301 MCContext &Ctx;
302
David Blaikie960ea3f2014-06-08 16:18:35 +0000303public:
David Blaikie9f380a32015-03-16 18:06:57 +0000304 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000305
Tim Northover3b0846e2014-05-24 12:50:23 +0000306 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
307 Kind = o.Kind;
308 StartLoc = o.StartLoc;
309 EndLoc = o.EndLoc;
310 switch (Kind) {
311 case k_Token:
312 Tok = o.Tok;
313 break;
314 case k_Immediate:
315 Imm = o.Imm;
316 break;
317 case k_ShiftedImm:
318 ShiftedImm = o.ShiftedImm;
319 break;
320 case k_CondCode:
321 CondCode = o.CondCode;
322 break;
323 case k_FPImm:
324 FPImm = o.FPImm;
325 break;
326 case k_Barrier:
327 Barrier = o.Barrier;
328 break;
329 case k_Register:
330 Reg = o.Reg;
331 break;
332 case k_VectorList:
333 VectorList = o.VectorList;
334 break;
335 case k_VectorIndex:
336 VectorIndex = o.VectorIndex;
337 break;
338 case k_SysReg:
339 SysReg = o.SysReg;
340 break;
341 case k_SysCR:
342 SysCRImm = o.SysCRImm;
343 break;
344 case k_Prefetch:
345 Prefetch = o.Prefetch;
346 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000347 case k_PSBHint:
348 PSBHint = o.PSBHint;
349 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000350 case k_ShiftExtend:
351 ShiftExtend = o.ShiftExtend;
352 break;
353 }
354 }
355
356 /// getStartLoc - Get the location of the first token of this operand.
357 SMLoc getStartLoc() const override { return StartLoc; }
358 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000359 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000360
361 StringRef getToken() const {
362 assert(Kind == k_Token && "Invalid access!");
363 return StringRef(Tok.Data, Tok.Length);
364 }
365
366 bool isTokenSuffix() const {
367 assert(Kind == k_Token && "Invalid access!");
368 return Tok.IsSuffix;
369 }
370
371 const MCExpr *getImm() const {
372 assert(Kind == k_Immediate && "Invalid access!");
373 return Imm.Val;
374 }
375
376 const MCExpr *getShiftedImmVal() const {
377 assert(Kind == k_ShiftedImm && "Invalid access!");
378 return ShiftedImm.Val;
379 }
380
381 unsigned getShiftedImmShift() const {
382 assert(Kind == k_ShiftedImm && "Invalid access!");
383 return ShiftedImm.ShiftAmount;
384 }
385
386 AArch64CC::CondCode getCondCode() const {
387 assert(Kind == k_CondCode && "Invalid access!");
388 return CondCode.Code;
389 }
390
391 unsigned getFPImm() const {
392 assert(Kind == k_FPImm && "Invalid access!");
393 return FPImm.Val;
394 }
395
396 unsigned getBarrier() const {
397 assert(Kind == k_Barrier && "Invalid access!");
398 return Barrier.Val;
399 }
400
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000401 StringRef getBarrierName() const {
402 assert(Kind == k_Barrier && "Invalid access!");
403 return StringRef(Barrier.Data, Barrier.Length);
404 }
405
Tim Northover3b0846e2014-05-24 12:50:23 +0000406 unsigned getReg() const override {
407 assert(Kind == k_Register && "Invalid access!");
408 return Reg.RegNum;
409 }
410
411 unsigned getVectorListStart() const {
412 assert(Kind == k_VectorList && "Invalid access!");
413 return VectorList.RegNum;
414 }
415
416 unsigned getVectorListCount() const {
417 assert(Kind == k_VectorList && "Invalid access!");
418 return VectorList.Count;
419 }
420
421 unsigned getVectorIndex() const {
422 assert(Kind == k_VectorIndex && "Invalid access!");
423 return VectorIndex.Val;
424 }
425
426 StringRef getSysReg() const {
427 assert(Kind == k_SysReg && "Invalid access!");
428 return StringRef(SysReg.Data, SysReg.Length);
429 }
430
Tim Northover3b0846e2014-05-24 12:50:23 +0000431 unsigned getSysCR() const {
432 assert(Kind == k_SysCR && "Invalid access!");
433 return SysCRImm.Val;
434 }
435
436 unsigned getPrefetch() const {
437 assert(Kind == k_Prefetch && "Invalid access!");
438 return Prefetch.Val;
439 }
440
Oliver Stannarda34e4702015-12-01 10:48:51 +0000441 unsigned getPSBHint() const {
442 assert(Kind == k_PSBHint && "Invalid access!");
443 return PSBHint.Val;
444 }
445
446 StringRef getPSBHintName() const {
447 assert(Kind == k_PSBHint && "Invalid access!");
448 return StringRef(PSBHint.Data, PSBHint.Length);
449 }
450
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000451 StringRef getPrefetchName() const {
452 assert(Kind == k_Prefetch && "Invalid access!");
453 return StringRef(Prefetch.Data, Prefetch.Length);
454 }
455
Tim Northover3b0846e2014-05-24 12:50:23 +0000456 AArch64_AM::ShiftExtendType getShiftExtendType() const {
457 assert(Kind == k_ShiftExtend && "Invalid access!");
458 return ShiftExtend.Type;
459 }
460
461 unsigned getShiftExtendAmount() const {
462 assert(Kind == k_ShiftExtend && "Invalid access!");
463 return ShiftExtend.Amount;
464 }
465
466 bool hasShiftExtendAmount() const {
467 assert(Kind == k_ShiftExtend && "Invalid access!");
468 return ShiftExtend.HasExplicitAmount;
469 }
470
471 bool isImm() const override { return Kind == k_Immediate; }
472 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000473
474 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
475
476 template <int Bits, int Scale> bool isSImmScaled() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000477 if (!isImm())
478 return false;
479 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
480 if (!MCE)
481 return false;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000482
483 int64_t Shift = Bits - 1;
484 int64_t MinVal = (int64_t(1) << Shift) * -Scale;
485 int64_t MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
486
Tim Northover3b0846e2014-05-24 12:50:23 +0000487 int64_t Val = MCE->getValue();
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000488 return Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0;
Tim Northover3b0846e2014-05-24 12:50:23 +0000489 }
490
Sander de Smalen245e0e62018-01-22 10:46:00 +0000491 bool isSVEPattern() const {
492 if (!isImm())
493 return false;
494 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
495 if (!MCE)
496 return false;
497 int64_t Val = MCE->getValue();
498 return Val >= 0 && Val < 32;
499 }
500
Tim Northover3b0846e2014-05-24 12:50:23 +0000501 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
502 AArch64MCExpr::VariantKind ELFRefKind;
503 MCSymbolRefExpr::VariantKind DarwinRefKind;
504 int64_t Addend;
505 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
506 Addend)) {
507 // If we don't understand the expression, assume the best and
508 // let the fixup and relocation code deal with it.
509 return true;
510 }
511
512 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
513 ELFRefKind == AArch64MCExpr::VK_LO12 ||
514 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
515 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
516 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
517 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
518 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
519 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000520 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
521 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
522 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000523 // Note that we don't range-check the addend. It's adjusted modulo page
524 // size when converted, so there is no "out of range" condition when using
525 // @pageoff.
526 return Addend >= 0 && (Addend % Scale) == 0;
527 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
528 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
529 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
530 return Addend == 0;
531 }
532
533 return false;
534 }
535
536 template <int Scale> bool isUImm12Offset() const {
537 if (!isImm())
538 return false;
539
540 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
541 if (!MCE)
542 return isSymbolicUImm12Offset(getImm(), Scale);
543
544 int64_t Val = MCE->getValue();
545 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
546 }
547
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000548 template <int N, int M>
549 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000550 if (!isImm())
551 return false;
552 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
553 if (!MCE)
554 return false;
555 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000556 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000557 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000558
Sander de Smalena1c259c2018-01-29 13:05:38 +0000559 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
560 // a logical immediate can always be represented when inverted.
561 template <typename T>
562 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000563 if (!isImm())
564 return false;
565 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
566 if (!MCE)
567 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000568
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000569 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000570 int64_t SVal = typename std::make_signed<T>::type(Val);
571 int64_t UVal = typename std::make_unsigned<T>::type(Val);
572 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000573 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000574
Sander de Smalena1c259c2018-01-29 13:05:38 +0000575 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000576 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000577
Tim Northover3b0846e2014-05-24 12:50:23 +0000578 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000579
Tim Northover3b0846e2014-05-24 12:50:23 +0000580 bool isAddSubImm() const {
581 if (!isShiftedImm() && !isImm())
582 return false;
583
584 const MCExpr *Expr;
585
586 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
587 if (isShiftedImm()) {
588 unsigned Shift = ShiftedImm.ShiftAmount;
589 Expr = ShiftedImm.Val;
590 if (Shift != 0 && Shift != 12)
591 return false;
592 } else {
593 Expr = getImm();
594 }
595
596 AArch64MCExpr::VariantKind ELFRefKind;
597 MCSymbolRefExpr::VariantKind DarwinRefKind;
598 int64_t Addend;
599 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
600 DarwinRefKind, Addend)) {
601 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
602 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
603 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
604 || ELFRefKind == AArch64MCExpr::VK_LO12
605 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
606 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
607 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
608 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
609 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
610 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000611 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
612 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
613 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000614 }
615
Diana Picusc93518d2016-10-11 09:17:47 +0000616 // If it's a constant, it should be a real immediate in range:
617 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
618 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
619
620 // If it's an expression, we hope for the best and let the fixup/relocation
621 // code deal with it.
622 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000623 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000624
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000625 bool isAddSubImmNeg() const {
626 if (!isShiftedImm() && !isImm())
627 return false;
628
629 const MCExpr *Expr;
630
631 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
632 if (isShiftedImm()) {
633 unsigned Shift = ShiftedImm.ShiftAmount;
634 Expr = ShiftedImm.Val;
635 if (Shift != 0 && Shift != 12)
636 return false;
637 } else
638 Expr = getImm();
639
640 // Otherwise it should be a real negative immediate in range:
641 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
642 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
643 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000644
Tim Northover3b0846e2014-05-24 12:50:23 +0000645 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000646
Tim Northover3b0846e2014-05-24 12:50:23 +0000647 bool isSIMDImmType10() const {
648 if (!isImm())
649 return false;
650 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
651 if (!MCE)
652 return false;
653 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
654 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000655
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000656 template<int N>
657 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000658 if (!isImm())
659 return false;
660 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
661 if (!MCE)
662 return true;
663 int64_t Val = MCE->getValue();
664 if (Val & 0x3)
665 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000666 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
667 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000668 }
669
670 bool
671 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
672 if (!isImm())
673 return false;
674
675 AArch64MCExpr::VariantKind ELFRefKind;
676 MCSymbolRefExpr::VariantKind DarwinRefKind;
677 int64_t Addend;
678 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
679 DarwinRefKind, Addend)) {
680 return false;
681 }
682 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
683 return false;
684
685 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
686 if (ELFRefKind == AllowedModifiers[i])
687 return Addend == 0;
688 }
689
690 return false;
691 }
692
693 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000694 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000695 }
696
697 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000698 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
699 AArch64MCExpr::VK_TPREL_G2,
700 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000701 }
702
703 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000704 return isMovWSymbol({
705 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000706 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
707 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000708 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000709 }
710
711 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000712 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
713 AArch64MCExpr::VK_TPREL_G0,
714 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000715 }
716
717 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000718 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000719 }
720
721 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000722 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000723 }
724
725 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000726 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
727 AArch64MCExpr::VK_TPREL_G1_NC,
728 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000729 }
730
731 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000732 return isMovWSymbol(
733 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
734 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000735 }
736
737 template<int RegWidth, int Shift>
738 bool isMOVZMovAlias() const {
739 if (!isImm()) return false;
740
741 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
742 if (!CE) return false;
743 uint64_t Value = CE->getValue();
744
Tim Northoverdaa1c012016-06-16 01:42:25 +0000745 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000746 }
747
748 template<int RegWidth, int Shift>
749 bool isMOVNMovAlias() const {
750 if (!isImm()) return false;
751
752 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
753 if (!CE) return false;
754 uint64_t Value = CE->getValue();
755
Tim Northoverdaa1c012016-06-16 01:42:25 +0000756 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000757 }
758
759 bool isFPImm() const { return Kind == k_FPImm; }
760 bool isBarrier() const { return Kind == k_Barrier; }
761 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000762
Tim Northover3b0846e2014-05-24 12:50:23 +0000763 bool isMRSSystemRegister() const {
764 if (!isSysReg()) return false;
765
Tim Northover7cd58932015-01-22 17:23:04 +0000766 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000767 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000768
Tim Northover3b0846e2014-05-24 12:50:23 +0000769 bool isMSRSystemRegister() const {
770 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000771 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000772 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000773
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000774 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000775 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000776 return (SysReg.PStateField == AArch64PState::PAN ||
777 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000778 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000779
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000780 bool isSystemPStateFieldWithImm0_15() const {
781 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000782 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000783 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000784
Florian Hahnc4422242017-11-07 13:07:50 +0000785 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000786 return Kind == k_Register;
787 }
788
789 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000790 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
791 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000792
Florian Hahnc4422242017-11-07 13:07:50 +0000793 bool isNeonVectorReg() const {
794 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
795 }
796
797 bool isNeonVectorRegLo() const {
798 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000799 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
800 Reg.RegNum);
801 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000802
Sander de Smalencd6be962017-12-20 11:02:42 +0000803 template <unsigned Class> bool isSVEVectorReg() const {
804 RegKind RK;
805 switch (Class) {
806 case AArch64::ZPRRegClassID:
807 RK = RegKind::SVEDataVector;
808 break;
809 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000810 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000811 RK = RegKind::SVEPredicateVector;
812 break;
813 default:
814 llvm_unreachable("Unsupport register class");
815 }
816
817 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000818 AArch64MCRegisterClasses[Class].contains(getReg());
819 }
820
Sander de Smalencd6be962017-12-20 11:02:42 +0000821 template <int ElementWidth, unsigned Class>
822 bool isSVEVectorRegOfWidth() const {
823 return isSVEVectorReg<Class>() &&
Sander de Smalen73937b72018-04-11 07:36:10 +0000824 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth);
Florian Hahn91f11e52017-11-07 16:45:48 +0000825 }
826
Tim Northover3b0846e2014-05-24 12:50:23 +0000827 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000828 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000829 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
830 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000831
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000832 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000833 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000834 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
835 Reg.RegNum);
836 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000837
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000838 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000839 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000840 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
841 Reg.RegNum);
842 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000843
844 bool isGPR64sp0() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000845 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000846 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
847 }
848
Sam Parker5f934642017-08-31 09:27:04 +0000849 template<int64_t Angle, int64_t Remainder>
850 bool isComplexRotation() const {
851 if (!isImm()) return false;
852
853 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
854 if (!CE) return false;
855 uint64_t Value = CE->getValue();
856
857 return (Value % Angle == Remainder && Value <= 270);
858 }
859
Tim Northover3b0846e2014-05-24 12:50:23 +0000860 /// Is this a vector list with the type implicit (presumably attached to the
861 /// instruction itself)?
862 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
863 return Kind == k_VectorList && VectorList.Count == NumRegs &&
864 !VectorList.ElementKind;
865 }
866
867 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
868 bool isTypedVectorList() const {
869 if (Kind != k_VectorList)
870 return false;
871 if (VectorList.Count != NumRegs)
872 return false;
873 if (VectorList.ElementKind != ElementKind)
874 return false;
875 return VectorList.NumElements == NumElements;
876 }
877
878 bool isVectorIndex1() const {
879 return Kind == k_VectorIndex && VectorIndex.Val == 1;
880 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000881
Tim Northover3b0846e2014-05-24 12:50:23 +0000882 bool isVectorIndexB() const {
883 return Kind == k_VectorIndex && VectorIndex.Val < 16;
884 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000885
Tim Northover3b0846e2014-05-24 12:50:23 +0000886 bool isVectorIndexH() const {
887 return Kind == k_VectorIndex && VectorIndex.Val < 8;
888 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000889
Tim Northover3b0846e2014-05-24 12:50:23 +0000890 bool isVectorIndexS() const {
891 return Kind == k_VectorIndex && VectorIndex.Val < 4;
892 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000893
Tim Northover3b0846e2014-05-24 12:50:23 +0000894 bool isVectorIndexD() const {
895 return Kind == k_VectorIndex && VectorIndex.Val < 2;
896 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000897
Tim Northover3b0846e2014-05-24 12:50:23 +0000898 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000899
Tim Northover3b0846e2014-05-24 12:50:23 +0000900 bool isTokenEqual(StringRef Str) const {
901 return Kind == k_Token && getToken() == Str;
902 }
903 bool isSysCR() const { return Kind == k_SysCR; }
904 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000905 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000906 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
907 bool isShifter() const {
908 if (!isShiftExtend())
909 return false;
910
911 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
912 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
913 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
914 ST == AArch64_AM::MSL);
915 }
916 bool isExtend() const {
917 if (!isShiftExtend())
918 return false;
919
920 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
921 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
922 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
923 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
924 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
925 ET == AArch64_AM::LSL) &&
926 getShiftExtendAmount() <= 4;
927 }
928
929 bool isExtend64() const {
930 if (!isExtend())
931 return false;
932 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
933 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
934 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
935 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000936
Tim Northover3b0846e2014-05-24 12:50:23 +0000937 bool isExtendLSL64() const {
938 if (!isExtend())
939 return false;
940 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
941 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
942 ET == AArch64_AM::LSL) &&
943 getShiftExtendAmount() <= 4;
944 }
945
946 template<int Width> bool isMemXExtend() const {
947 if (!isExtend())
948 return false;
949 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
950 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
951 (getShiftExtendAmount() == Log2_32(Width / 8) ||
952 getShiftExtendAmount() == 0);
953 }
954
955 template<int Width> bool isMemWExtend() const {
956 if (!isExtend())
957 return false;
958 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
959 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
960 (getShiftExtendAmount() == Log2_32(Width / 8) ||
961 getShiftExtendAmount() == 0);
962 }
963
964 template <unsigned width>
965 bool isArithmeticShifter() const {
966 if (!isShifter())
967 return false;
968
969 // An arithmetic shifter is LSL, LSR, or ASR.
970 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
971 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
972 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
973 }
974
975 template <unsigned width>
976 bool isLogicalShifter() const {
977 if (!isShifter())
978 return false;
979
980 // A logical shifter is LSL, LSR, ASR or ROR.
981 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
982 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
983 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
984 getShiftExtendAmount() < width;
985 }
986
987 bool isMovImm32Shifter() const {
988 if (!isShifter())
989 return false;
990
991 // A MOVi shifter is LSL of 0, 16, 32, or 48.
992 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
993 if (ST != AArch64_AM::LSL)
994 return false;
995 uint64_t Val = getShiftExtendAmount();
996 return (Val == 0 || Val == 16);
997 }
998
999 bool isMovImm64Shifter() const {
1000 if (!isShifter())
1001 return false;
1002
1003 // A MOVi shifter is LSL of 0 or 16.
1004 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1005 if (ST != AArch64_AM::LSL)
1006 return false;
1007 uint64_t Val = getShiftExtendAmount();
1008 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1009 }
1010
1011 bool isLogicalVecShifter() const {
1012 if (!isShifter())
1013 return false;
1014
1015 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1016 unsigned Shift = getShiftExtendAmount();
1017 return getShiftExtendType() == AArch64_AM::LSL &&
1018 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1019 }
1020
1021 bool isLogicalVecHalfWordShifter() const {
1022 if (!isLogicalVecShifter())
1023 return false;
1024
1025 // A logical vector shifter is a left shift by 0 or 8.
1026 unsigned Shift = getShiftExtendAmount();
1027 return getShiftExtendType() == AArch64_AM::LSL &&
1028 (Shift == 0 || Shift == 8);
1029 }
1030
1031 bool isMoveVecShifter() const {
1032 if (!isShiftExtend())
1033 return false;
1034
1035 // A logical vector shifter is a left shift by 8 or 16.
1036 unsigned Shift = getShiftExtendAmount();
1037 return getShiftExtendType() == AArch64_AM::MSL &&
1038 (Shift == 8 || Shift == 16);
1039 }
1040
1041 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1042 // to LDUR/STUR when the offset is not legal for the former but is for
1043 // the latter. As such, in addition to checking for being a legal unscaled
1044 // address, also check that it is not a legal scaled address. This avoids
1045 // ambiguity in the matcher.
1046 template<int Width>
1047 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001048 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001049 }
1050
1051 bool isAdrpLabel() const {
1052 // Validation was handled during parsing, so we just sanity check that
1053 // something didn't go haywire.
1054 if (!isImm())
1055 return false;
1056
1057 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1058 int64_t Val = CE->getValue();
1059 int64_t Min = - (4096 * (1LL << (21 - 1)));
1060 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1061 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1062 }
1063
1064 return true;
1065 }
1066
1067 bool isAdrLabel() const {
1068 // Validation was handled during parsing, so we just sanity check that
1069 // something didn't go haywire.
1070 if (!isImm())
1071 return false;
1072
1073 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1074 int64_t Val = CE->getValue();
1075 int64_t Min = - (1LL << (21 - 1));
1076 int64_t Max = ((1LL << (21 - 1)) - 1);
1077 return Val >= Min && Val <= Max;
1078 }
1079
1080 return true;
1081 }
1082
1083 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1084 // Add as immediates when possible. Null MCExpr = 0.
1085 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001086 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001087 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001088 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001089 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001090 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001091 }
1092
1093 void addRegOperands(MCInst &Inst, unsigned N) const {
1094 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001095 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001096 }
1097
1098 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1099 assert(N == 1 && "Invalid number of operands!");
1100 assert(
1101 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1102
1103 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1104 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1105 RI->getEncodingValue(getReg()));
1106
Jim Grosbache9119e42015-05-13 18:37:00 +00001107 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001108 }
1109
1110 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1111 assert(N == 1 && "Invalid number of operands!");
1112 assert(
1113 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001114 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001115 }
1116
1117 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1118 assert(N == 1 && "Invalid number of operands!");
1119 assert(
1120 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001121 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001122 }
1123
1124 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1125 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001126 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001127 }
1128
1129 template <unsigned NumRegs>
1130 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1131 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001132 static const unsigned FirstRegs[] = { AArch64::D0,
1133 AArch64::D0_D1,
1134 AArch64::D0_D1_D2,
1135 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001136 unsigned FirstReg = FirstRegs[NumRegs - 1];
1137
1138 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001139 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001140 }
1141
1142 template <unsigned NumRegs>
1143 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1144 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001145 static const unsigned FirstRegs[] = { AArch64::Q0,
1146 AArch64::Q0_Q1,
1147 AArch64::Q0_Q1_Q2,
1148 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001149 unsigned FirstReg = FirstRegs[NumRegs - 1];
1150
1151 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001152 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001153 }
1154
1155 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1156 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001157 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001158 }
1159
1160 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1161 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001162 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001163 }
1164
1165 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1166 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001167 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001168 }
1169
1170 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1171 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001172 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001173 }
1174
1175 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1176 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001177 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001178 }
1179
1180 void addImmOperands(MCInst &Inst, unsigned N) const {
1181 assert(N == 1 && "Invalid number of operands!");
1182 // If this is a pageoff symrefexpr with an addend, adjust the addend
1183 // to be only the page-offset portion. Otherwise, just add the expr
1184 // as-is.
1185 addExpr(Inst, getImm());
1186 }
1187
1188 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1189 assert(N == 2 && "Invalid number of operands!");
1190 if (isShiftedImm()) {
1191 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001192 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001193 } else {
1194 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001195 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001196 }
1197 }
1198
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001199 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1200 assert(N == 2 && "Invalid number of operands!");
1201
1202 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1203 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1204 int64_t Val = -CE->getValue();
1205 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1206
1207 Inst.addOperand(MCOperand::createImm(Val));
1208 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1209 }
1210
Tim Northover3b0846e2014-05-24 12:50:23 +00001211 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1212 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001213 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001214 }
1215
1216 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1217 assert(N == 1 && "Invalid number of operands!");
1218 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1219 if (!MCE)
1220 addExpr(Inst, getImm());
1221 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001222 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001223 }
1224
1225 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1226 addImmOperands(Inst, N);
1227 }
1228
1229 template<int Scale>
1230 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1231 assert(N == 1 && "Invalid number of operands!");
1232 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1233
1234 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001235 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001236 return;
1237 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001238 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001239 }
1240
1241 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1242 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001243 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001244 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001245 }
1246
Sam Parker6d42de72017-08-11 13:14:00 +00001247 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1248 assert(N == 1 && "Invalid number of operands!");
1249 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1250 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1251 }
1252
Tim Northover3b0846e2014-05-24 12:50:23 +00001253 void addSImm7s4Operands(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() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001257 }
1258
1259 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1260 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001261 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001262 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001263 }
1264
1265 void addSImm7s16Operands(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() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001269 }
1270
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001271 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1272 assert(N == 1 && "Invalid number of operands!");
1273 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1274 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1275 }
1276
Tim Northover3b0846e2014-05-24 12:50:23 +00001277 void addImm0_7Operands(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()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001281 }
1282
1283 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1284 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001285 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001286 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001287 }
1288
1289 void addImm0_15Operands(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_16Operands(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());
Tim Northover3b0846e2014-05-24 12:50:23 +00001298 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001299 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001300 }
1301
1302 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1303 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001304 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001305 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001306 }
1307
1308 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1309 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001310 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
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 addImm1_32Operands(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 addImm0_63Operands(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_63Operands(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 addImm1_64Operands(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 addImm0_127Operands(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 addImm0_255Operands(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_65535Operands(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 addImm32_63Operands(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
Sander de Smalena1c259c2018-01-29 13:05:38 +00001362 template <typename T>
1363 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001364 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001365 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001366 typename std::make_unsigned<T>::type Val = MCE->getValue();
1367 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001368 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001369 }
1370
Sander de Smalena1c259c2018-01-29 13:05:38 +00001371 template <typename T>
1372 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001373 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001374 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001375 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1376 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001377 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001378 }
1379
Tim Northover3b0846e2014-05-24 12:50:23 +00001380 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1381 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001382 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001383 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001384 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001385 }
1386
1387 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1388 // Branch operands don't encode the low bits, so shift them off
1389 // here. If it's a label, however, just put it on directly as there's
1390 // not enough information now to do anything.
1391 assert(N == 1 && "Invalid number of operands!");
1392 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1393 if (!MCE) {
1394 addExpr(Inst, getImm());
1395 return;
1396 }
1397 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001398 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001399 }
1400
1401 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1402 // Branch operands don't encode the low bits, so shift them off
1403 // here. If it's a label, however, just put it on directly as there's
1404 // not enough information now to do anything.
1405 assert(N == 1 && "Invalid number of operands!");
1406 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1407 if (!MCE) {
1408 addExpr(Inst, getImm());
1409 return;
1410 }
1411 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001412 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001413 }
1414
1415 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1416 // Branch operands don't encode the low bits, so shift them off
1417 // here. If it's a label, however, just put it on directly as there's
1418 // not enough information now to do anything.
1419 assert(N == 1 && "Invalid number of operands!");
1420 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1421 if (!MCE) {
1422 addExpr(Inst, getImm());
1423 return;
1424 }
1425 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001426 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001427 }
1428
1429 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1430 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001431 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001432 }
1433
1434 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1435 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001436 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001437 }
1438
1439 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1440 assert(N == 1 && "Invalid number of operands!");
1441
Jim Grosbache9119e42015-05-13 18:37:00 +00001442 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001443 }
1444
1445 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1446 assert(N == 1 && "Invalid number of operands!");
1447
Jim Grosbache9119e42015-05-13 18:37:00 +00001448 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001449 }
1450
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001451 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1452 assert(N == 1 && "Invalid number of operands!");
1453
1454 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1455 }
1456
1457 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001458 assert(N == 1 && "Invalid number of operands!");
1459
Jim Grosbache9119e42015-05-13 18:37:00 +00001460 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001461 }
1462
1463 void addSysCROperands(MCInst &Inst, unsigned N) const {
1464 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001465 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001466 }
1467
1468 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1469 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001470 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001471 }
1472
Oliver Stannarda34e4702015-12-01 10:48:51 +00001473 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1474 assert(N == 1 && "Invalid number of operands!");
1475 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1476 }
1477
Tim Northover3b0846e2014-05-24 12:50:23 +00001478 void addShifterOperands(MCInst &Inst, unsigned N) const {
1479 assert(N == 1 && "Invalid number of operands!");
1480 unsigned Imm =
1481 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001482 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001483 }
1484
1485 void addExtendOperands(MCInst &Inst, unsigned N) const {
1486 assert(N == 1 && "Invalid number of operands!");
1487 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1488 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1489 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001490 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001491 }
1492
1493 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1494 assert(N == 1 && "Invalid number of operands!");
1495 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1496 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1497 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001498 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001499 }
1500
1501 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1502 assert(N == 2 && "Invalid number of operands!");
1503 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1504 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001505 Inst.addOperand(MCOperand::createImm(IsSigned));
1506 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001507 }
1508
1509 // For 8-bit load/store instructions with a register offset, both the
1510 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1511 // they're disambiguated by whether the shift was explicit or implicit rather
1512 // than its size.
1513 void addMemExtend8Operands(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(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001519 }
1520
1521 template<int Shift>
1522 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1523 assert(N == 1 && "Invalid number of operands!");
1524
1525 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1526 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001527 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001528 }
1529
1530 template<int Shift>
1531 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1532 assert(N == 1 && "Invalid number of operands!");
1533
1534 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1535 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001536 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001537 }
1538
Sam Parker5f934642017-08-31 09:27:04 +00001539 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1540 assert(N == 1 && "Invalid number of operands!");
1541 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1542 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1543 }
1544
1545 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1546 assert(N == 1 && "Invalid number of operands!");
1547 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1548 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1549 }
1550
Tim Northover3b0846e2014-05-24 12:50:23 +00001551 void print(raw_ostream &OS) const override;
1552
David Blaikie960ea3f2014-06-08 16:18:35 +00001553 static std::unique_ptr<AArch64Operand>
1554 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1555 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001556 Op->Tok.Data = Str.data();
1557 Op->Tok.Length = Str.size();
1558 Op->Tok.IsSuffix = IsSuffix;
1559 Op->StartLoc = S;
1560 Op->EndLoc = S;
1561 return Op;
1562 }
1563
David Blaikie960ea3f2014-06-08 16:18:35 +00001564 static std::unique_ptr<AArch64Operand>
Florian Hahnc4422242017-11-07 13:07:50 +00001565 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001566 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001567 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001568 Op->Reg.Kind = Kind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001569 Op->StartLoc = S;
1570 Op->EndLoc = E;
1571 return Op;
1572 }
1573
David Blaikie960ea3f2014-06-08 16:18:35 +00001574 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001575 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1576 SMLoc S, SMLoc E, MCContext &Ctx) {
1577 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1578 Kind == RegKind::SVEPredicateVector) &&
1579 "Invalid vector kind");
Florian Hahn91f11e52017-11-07 16:45:48 +00001580 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1581 Op->Reg.RegNum = RegNum;
1582 Op->Reg.ElementWidth = ElementWidth;
1583 Op->Reg.Kind = Kind;
1584 Op->StartLoc = S;
1585 Op->EndLoc = E;
1586 return Op;
1587 }
1588
1589 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001590 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen73937b72018-04-11 07:36:10 +00001591 unsigned ElementWidth, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001592 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001593 Op->VectorList.RegNum = RegNum;
1594 Op->VectorList.Count = Count;
1595 Op->VectorList.NumElements = NumElements;
Sander de Smalen73937b72018-04-11 07:36:10 +00001596 switch (ElementWidth) {
1597 case 0:
1598 Op->VectorList.ElementKind = 0;
1599 break;
1600 case 8:
1601 Op->VectorList.ElementKind = 'b';
1602 break;
1603 case 16:
1604 Op->VectorList.ElementKind = 'h';
1605 break;
1606 case 32:
1607 Op->VectorList.ElementKind = 's';
1608 break;
1609 case 64:
1610 Op->VectorList.ElementKind = 'd';
1611 break;
1612 default:
1613 llvm_unreachable("Unsupported elementwidth");
1614 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001615 Op->StartLoc = S;
1616 Op->EndLoc = E;
1617 return Op;
1618 }
1619
David Blaikie960ea3f2014-06-08 16:18:35 +00001620 static std::unique_ptr<AArch64Operand>
1621 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1622 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001623 Op->VectorIndex.Val = Idx;
1624 Op->StartLoc = S;
1625 Op->EndLoc = E;
1626 return Op;
1627 }
1628
David Blaikie960ea3f2014-06-08 16:18:35 +00001629 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1630 SMLoc E, MCContext &Ctx) {
1631 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001632 Op->Imm.Val = Val;
1633 Op->StartLoc = S;
1634 Op->EndLoc = E;
1635 return Op;
1636 }
1637
David Blaikie960ea3f2014-06-08 16:18:35 +00001638 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1639 unsigned ShiftAmount,
1640 SMLoc S, SMLoc E,
1641 MCContext &Ctx) {
1642 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001643 Op->ShiftedImm .Val = Val;
1644 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1645 Op->StartLoc = S;
1646 Op->EndLoc = E;
1647 return Op;
1648 }
1649
David Blaikie960ea3f2014-06-08 16:18:35 +00001650 static std::unique_ptr<AArch64Operand>
1651 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1652 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001653 Op->CondCode.Code = Code;
1654 Op->StartLoc = S;
1655 Op->EndLoc = E;
1656 return Op;
1657 }
1658
David Blaikie960ea3f2014-06-08 16:18:35 +00001659 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1660 MCContext &Ctx) {
1661 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001662 Op->FPImm.Val = Val;
1663 Op->StartLoc = S;
1664 Op->EndLoc = S;
1665 return Op;
1666 }
1667
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001668 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1669 StringRef Str,
1670 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001671 MCContext &Ctx) {
1672 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001673 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001674 Op->Barrier.Data = Str.data();
1675 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001676 Op->StartLoc = S;
1677 Op->EndLoc = S;
1678 return Op;
1679 }
1680
Tim Northover7cd58932015-01-22 17:23:04 +00001681 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1682 uint32_t MRSReg,
1683 uint32_t MSRReg,
1684 uint32_t PStateField,
1685 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001686 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001687 Op->SysReg.Data = Str.data();
1688 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001689 Op->SysReg.MRSReg = MRSReg;
1690 Op->SysReg.MSRReg = MSRReg;
1691 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001692 Op->StartLoc = S;
1693 Op->EndLoc = S;
1694 return Op;
1695 }
1696
David Blaikie960ea3f2014-06-08 16:18:35 +00001697 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1698 SMLoc E, MCContext &Ctx) {
1699 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001700 Op->SysCRImm.Val = Val;
1701 Op->StartLoc = S;
1702 Op->EndLoc = E;
1703 return Op;
1704 }
1705
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001706 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1707 StringRef Str,
1708 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001709 MCContext &Ctx) {
1710 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001711 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001712 Op->Barrier.Data = Str.data();
1713 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001714 Op->StartLoc = S;
1715 Op->EndLoc = S;
1716 return Op;
1717 }
1718
Oliver Stannarda34e4702015-12-01 10:48:51 +00001719 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1720 StringRef Str,
1721 SMLoc S,
1722 MCContext &Ctx) {
1723 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1724 Op->PSBHint.Val = Val;
1725 Op->PSBHint.Data = Str.data();
1726 Op->PSBHint.Length = Str.size();
1727 Op->StartLoc = S;
1728 Op->EndLoc = S;
1729 return Op;
1730 }
1731
David Blaikie960ea3f2014-06-08 16:18:35 +00001732 static std::unique_ptr<AArch64Operand>
1733 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1734 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1735 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001736 Op->ShiftExtend.Type = ShOp;
1737 Op->ShiftExtend.Amount = Val;
1738 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1739 Op->StartLoc = S;
1740 Op->EndLoc = E;
1741 return Op;
1742 }
1743};
1744
1745} // end anonymous namespace.
1746
1747void AArch64Operand::print(raw_ostream &OS) const {
1748 switch (Kind) {
1749 case k_FPImm:
1750 OS << "<fpimm " << getFPImm() << "("
1751 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1752 break;
1753 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001754 StringRef Name = getBarrierName();
1755 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001756 OS << "<barrier " << Name << ">";
1757 else
1758 OS << "<barrier invalid #" << getBarrier() << ">";
1759 break;
1760 }
1761 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001762 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001763 break;
1764 case k_ShiftedImm: {
1765 unsigned Shift = getShiftedImmShift();
1766 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001767 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001768 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1769 break;
1770 }
1771 case k_CondCode:
1772 OS << "<condcode " << getCondCode() << ">";
1773 break;
1774 case k_Register:
1775 OS << "<register " << getReg() << ">";
1776 break;
1777 case k_VectorList: {
1778 OS << "<vectorlist ";
1779 unsigned Reg = getVectorListStart();
1780 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1781 OS << Reg + i << " ";
1782 OS << ">";
1783 break;
1784 }
1785 case k_VectorIndex:
1786 OS << "<vectorindex " << getVectorIndex() << ">";
1787 break;
1788 case k_SysReg:
1789 OS << "<sysreg: " << getSysReg() << '>';
1790 break;
1791 case k_Token:
1792 OS << "'" << getToken() << "'";
1793 break;
1794 case k_SysCR:
1795 OS << "c" << getSysCR();
1796 break;
1797 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001798 StringRef Name = getPrefetchName();
1799 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001800 OS << "<prfop " << Name << ">";
1801 else
1802 OS << "<prfop invalid #" << getPrefetch() << ">";
1803 break;
1804 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001805 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001806 OS << getPSBHintName();
1807 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001808 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001809 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1810 << getShiftExtendAmount();
1811 if (!hasShiftExtendAmount())
1812 OS << "<imp>";
1813 OS << '>';
1814 break;
1815 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001816}
1817
1818/// @name Auto-generated Match Functions
1819/// {
1820
1821static unsigned MatchRegisterName(StringRef Name);
1822
1823/// }
1824
Florian Hahnc4422242017-11-07 13:07:50 +00001825static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001826 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001827 .Case("v0", AArch64::Q0)
1828 .Case("v1", AArch64::Q1)
1829 .Case("v2", AArch64::Q2)
1830 .Case("v3", AArch64::Q3)
1831 .Case("v4", AArch64::Q4)
1832 .Case("v5", AArch64::Q5)
1833 .Case("v6", AArch64::Q6)
1834 .Case("v7", AArch64::Q7)
1835 .Case("v8", AArch64::Q8)
1836 .Case("v9", AArch64::Q9)
1837 .Case("v10", AArch64::Q10)
1838 .Case("v11", AArch64::Q11)
1839 .Case("v12", AArch64::Q12)
1840 .Case("v13", AArch64::Q13)
1841 .Case("v14", AArch64::Q14)
1842 .Case("v15", AArch64::Q15)
1843 .Case("v16", AArch64::Q16)
1844 .Case("v17", AArch64::Q17)
1845 .Case("v18", AArch64::Q18)
1846 .Case("v19", AArch64::Q19)
1847 .Case("v20", AArch64::Q20)
1848 .Case("v21", AArch64::Q21)
1849 .Case("v22", AArch64::Q22)
1850 .Case("v23", AArch64::Q23)
1851 .Case("v24", AArch64::Q24)
1852 .Case("v25", AArch64::Q25)
1853 .Case("v26", AArch64::Q26)
1854 .Case("v27", AArch64::Q27)
1855 .Case("v28", AArch64::Q28)
1856 .Case("v29", AArch64::Q29)
1857 .Case("v30", AArch64::Q30)
1858 .Case("v31", AArch64::Q31)
1859 .Default(0);
1860}
1861
Sander de Smalen73937b72018-04-11 07:36:10 +00001862/// Returns an optional pair of (#elements, element-width) if Suffix
1863/// is a valid vector kind. Where the number of elements in a vector
1864/// or the vector width is implicit or explicitly unknown (but still a
1865/// valid suffix kind), 0 is used.
1866static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1867 RegKind VectorKind) {
1868 std::pair<int, int> Res = {-1, -1};
1869
1870 switch (VectorKind) {
1871 case RegKind::NeonVector:
1872 Res =
1873 StringSwitch<std::pair<int, int>>(Suffix.lower())
1874 .Case("", {0, 0})
1875 .Case(".1d", {1, 64})
1876 .Case(".1q", {1, 128})
1877 // '.2h' needed for fp16 scalar pairwise reductions
1878 .Case(".2h", {2, 16})
1879 .Case(".2s", {2, 32})
1880 .Case(".2d", {2, 64})
1881 // '.4b' is another special case for the ARMv8.2a dot product
1882 // operand
1883 .Case(".4b", {4, 8})
1884 .Case(".4h", {4, 16})
1885 .Case(".4s", {4, 32})
1886 .Case(".8b", {8, 8})
1887 .Case(".8h", {8, 16})
1888 .Case(".16b", {16, 8})
1889 // Accept the width neutral ones, too, for verbose syntax. If those
1890 // aren't used in the right places, the token operand won't match so
1891 // all will work out.
1892 .Case(".b", {0, 8})
1893 .Case(".h", {0, 16})
1894 .Case(".s", {0, 32})
1895 .Case(".d", {0, 64})
1896 .Default({-1, -1});
1897 break;
1898 case RegKind::SVEPredicateVector:
1899 case RegKind::SVEDataVector:
1900 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1901 .Case("", {0, 0})
1902 .Case(".b", {0, 8})
1903 .Case(".h", {0, 16})
1904 .Case(".s", {0, 32})
1905 .Case(".d", {0, 64})
1906 .Case(".q", {0, 128})
1907 .Default({-1, -1});
1908 break;
1909 default:
1910 llvm_unreachable("Unsupported RegKind");
1911 }
1912
1913 if (Res == std::make_pair(-1, -1))
1914 return Optional<std::pair<int, int>>();
1915
1916 return Optional<std::pair<int, int>>(Res);
1917}
1918
1919static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1920 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001921}
1922
Florian Hahn91f11e52017-11-07 16:45:48 +00001923static unsigned matchSVEDataVectorRegName(StringRef Name) {
1924 return StringSwitch<unsigned>(Name.lower())
1925 .Case("z0", AArch64::Z0)
1926 .Case("z1", AArch64::Z1)
1927 .Case("z2", AArch64::Z2)
1928 .Case("z3", AArch64::Z3)
1929 .Case("z4", AArch64::Z4)
1930 .Case("z5", AArch64::Z5)
1931 .Case("z6", AArch64::Z6)
1932 .Case("z7", AArch64::Z7)
1933 .Case("z8", AArch64::Z8)
1934 .Case("z9", AArch64::Z9)
1935 .Case("z10", AArch64::Z10)
1936 .Case("z11", AArch64::Z11)
1937 .Case("z12", AArch64::Z12)
1938 .Case("z13", AArch64::Z13)
1939 .Case("z14", AArch64::Z14)
1940 .Case("z15", AArch64::Z15)
1941 .Case("z16", AArch64::Z16)
1942 .Case("z17", AArch64::Z17)
1943 .Case("z18", AArch64::Z18)
1944 .Case("z19", AArch64::Z19)
1945 .Case("z20", AArch64::Z20)
1946 .Case("z21", AArch64::Z21)
1947 .Case("z22", AArch64::Z22)
1948 .Case("z23", AArch64::Z23)
1949 .Case("z24", AArch64::Z24)
1950 .Case("z25", AArch64::Z25)
1951 .Case("z26", AArch64::Z26)
1952 .Case("z27", AArch64::Z27)
1953 .Case("z28", AArch64::Z28)
1954 .Case("z29", AArch64::Z29)
1955 .Case("z30", AArch64::Z30)
1956 .Case("z31", AArch64::Z31)
1957 .Default(0);
1958}
1959
Sander de Smalencd6be962017-12-20 11:02:42 +00001960static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1961 return StringSwitch<unsigned>(Name.lower())
1962 .Case("p0", AArch64::P0)
1963 .Case("p1", AArch64::P1)
1964 .Case("p2", AArch64::P2)
1965 .Case("p3", AArch64::P3)
1966 .Case("p4", AArch64::P4)
1967 .Case("p5", AArch64::P5)
1968 .Case("p6", AArch64::P6)
1969 .Case("p7", AArch64::P7)
1970 .Case("p8", AArch64::P8)
1971 .Case("p9", AArch64::P9)
1972 .Case("p10", AArch64::P10)
1973 .Case("p11", AArch64::P11)
1974 .Case("p12", AArch64::P12)
1975 .Case("p13", AArch64::P13)
1976 .Case("p14", AArch64::P14)
1977 .Case("p15", AArch64::P15)
1978 .Default(0);
1979}
1980
Tim Northover3b0846e2014-05-24 12:50:23 +00001981bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1982 SMLoc &EndLoc) {
1983 StartLoc = getLoc();
1984 RegNo = tryParseRegister();
1985 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1986 return (RegNo == (unsigned)-1);
1987}
1988
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001989// Matches a register name or register alias previously defined by '.req'
1990unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001991 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001992 unsigned RegNum = 0;
1993 if ((RegNum = matchSVEDataVectorRegName(Name)))
1994 return Kind == RegKind::SVEDataVector ? RegNum : 0;
1995
Sander de Smalencd6be962017-12-20 11:02:42 +00001996 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
1997 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
1998
Sander de Smalenc067c302017-12-20 09:45:45 +00001999 if ((RegNum = MatchNeonVectorRegName(Name)))
2000 return Kind == RegKind::NeonVector ? RegNum : 0;
2001
2002 // The parsed register must be of RegKind Scalar
2003 if ((RegNum = MatchRegisterName(Name)))
2004 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002005
Florian Hahnc4422242017-11-07 13:07:50 +00002006 if (!RegNum) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002007 // Check for aliases registered via .req. Canonicalize to lower case.
2008 // That's more consistent since register names are case insensitive, and
2009 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2010 auto Entry = RegisterReqs.find(Name.lower());
2011 if (Entry == RegisterReqs.end())
2012 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002013
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002014 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002015 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002016 RegNum = Entry->getValue().second;
2017 }
2018 return RegNum;
2019}
2020
Tim Northover3b0846e2014-05-24 12:50:23 +00002021/// tryParseRegister - Try to parse a register name. The token must be an
2022/// Identifier when called, and if it is a register name the token is eaten and
2023/// the register is added to the operand list.
2024int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002025 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002026 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002027 if (Tok.isNot(AsmToken::Identifier))
2028 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00002029
2030 std::string lowerCase = Tok.getString().lower();
Florian Hahnc4422242017-11-07 13:07:50 +00002031 unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
Sander de Smalenc067c302017-12-20 09:45:45 +00002032
Tim Northover3b0846e2014-05-24 12:50:23 +00002033 // Also handle a few aliases of registers.
2034 if (RegNum == 0)
2035 RegNum = StringSwitch<unsigned>(lowerCase)
2036 .Case("fp", AArch64::FP)
2037 .Case("lr", AArch64::LR)
2038 .Case("x31", AArch64::XZR)
2039 .Case("w31", AArch64::WZR)
2040 .Default(0);
2041
2042 if (RegNum == 0)
2043 return -1;
2044
2045 Parser.Lex(); // Eat identifier token.
2046 return RegNum;
2047}
2048
Tim Northover3b0846e2014-05-24 12:50:23 +00002049/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002050OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002051AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002052 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002053 SMLoc S = getLoc();
2054
2055 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2056 Error(S, "Expected cN operand where 0 <= N <= 15");
2057 return MatchOperand_ParseFail;
2058 }
2059
2060 StringRef Tok = Parser.getTok().getIdentifier();
2061 if (Tok[0] != 'c' && Tok[0] != 'C') {
2062 Error(S, "Expected cN operand where 0 <= N <= 15");
2063 return MatchOperand_ParseFail;
2064 }
2065
2066 uint32_t CRNum;
2067 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2068 if (BadNum || CRNum > 15) {
2069 Error(S, "Expected cN operand where 0 <= N <= 15");
2070 return MatchOperand_ParseFail;
2071 }
2072
2073 Parser.Lex(); // Eat identifier token.
2074 Operands.push_back(
2075 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2076 return MatchOperand_Success;
2077}
2078
2079/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002080OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002081AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002082 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002083 SMLoc S = getLoc();
2084 const AsmToken &Tok = Parser.getTok();
2085 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002086 // Eat optional hash.
2087 if (parseOptionalToken(AsmToken::Hash) ||
2088 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002089 const MCExpr *ImmVal;
2090 if (getParser().parseExpression(ImmVal))
2091 return MatchOperand_ParseFail;
2092
2093 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2094 if (!MCE) {
2095 TokError("immediate value expected for prefetch operand");
2096 return MatchOperand_ParseFail;
2097 }
2098 unsigned prfop = MCE->getValue();
2099 if (prfop > 31) {
2100 TokError("prefetch operand out of range, [0,31] expected");
2101 return MatchOperand_ParseFail;
2102 }
2103
Tim Northovere6ae6762016-07-05 21:23:04 +00002104 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2105 Operands.push_back(AArch64Operand::CreatePrefetch(
2106 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002107 return MatchOperand_Success;
2108 }
2109
2110 if (Tok.isNot(AsmToken::Identifier)) {
2111 TokError("pre-fetch hint expected");
2112 return MatchOperand_ParseFail;
2113 }
2114
Tim Northovere6ae6762016-07-05 21:23:04 +00002115 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2116 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002117 TokError("pre-fetch hint expected");
2118 return MatchOperand_ParseFail;
2119 }
2120
2121 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002122 Operands.push_back(AArch64Operand::CreatePrefetch(
2123 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002124 return MatchOperand_Success;
2125}
2126
Oliver Stannarda34e4702015-12-01 10:48:51 +00002127/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002128OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002129AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2130 MCAsmParser &Parser = getParser();
2131 SMLoc S = getLoc();
2132 const AsmToken &Tok = Parser.getTok();
2133 if (Tok.isNot(AsmToken::Identifier)) {
2134 TokError("invalid operand for instruction");
2135 return MatchOperand_ParseFail;
2136 }
2137
Tim Northovere6ae6762016-07-05 21:23:04 +00002138 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2139 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002140 TokError("invalid operand for instruction");
2141 return MatchOperand_ParseFail;
2142 }
2143
2144 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002145 Operands.push_back(AArch64Operand::CreatePSBHint(
2146 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002147 return MatchOperand_Success;
2148}
2149
Tim Northover3b0846e2014-05-24 12:50:23 +00002150/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2151/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002152OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002153AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002154 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002155 SMLoc S = getLoc();
2156 const MCExpr *Expr;
2157
2158 if (Parser.getTok().is(AsmToken::Hash)) {
2159 Parser.Lex(); // Eat hash token.
2160 }
2161
2162 if (parseSymbolicImmVal(Expr))
2163 return MatchOperand_ParseFail;
2164
2165 AArch64MCExpr::VariantKind ELFRefKind;
2166 MCSymbolRefExpr::VariantKind DarwinRefKind;
2167 int64_t Addend;
2168 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2169 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2170 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2171 // No modifier was specified at all; this is the syntax for an ELF basic
2172 // ADRP relocation (unfortunately).
2173 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002174 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002175 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2176 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2177 Addend != 0) {
2178 Error(S, "gotpage label reference not allowed an addend");
2179 return MatchOperand_ParseFail;
2180 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2181 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2182 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2183 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2184 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2185 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2186 // The operand must be an @page or @gotpage qualified symbolref.
2187 Error(S, "page or gotpage label reference expected");
2188 return MatchOperand_ParseFail;
2189 }
2190 }
2191
2192 // We have either a label reference possibly with addend or an immediate. The
2193 // addend is a raw value here. The linker will adjust it to only reference the
2194 // page.
2195 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2196 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2197
2198 return MatchOperand_Success;
2199}
2200
2201/// tryParseAdrLabel - Parse and validate a source label for the ADR
2202/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002203OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002204AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2205 SMLoc S = getLoc();
2206 const MCExpr *Expr;
2207
Nirav Davee833c6c2016-11-08 18:31:04 +00002208 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002209 if (getParser().parseExpression(Expr))
2210 return MatchOperand_ParseFail;
2211
2212 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2213 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2214
2215 return MatchOperand_Success;
2216}
2217
2218/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002219OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002220AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002221 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002222 SMLoc S = getLoc();
2223
Nirav Davee833c6c2016-11-08 18:31:04 +00002224 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002225
2226 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002227 bool isNegative = parseOptionalToken(AsmToken::Minus);
2228
Tim Northover3b0846e2014-05-24 12:50:23 +00002229 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002230 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002231 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002232 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002233 Val = Tok.getIntVal();
2234 if (Val > 255 || Val < 0) {
2235 TokError("encoded floating point value out of range");
2236 return MatchOperand_ParseFail;
2237 }
2238 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002239 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002240 if (isNegative)
2241 RealVal.changeSign();
2242
Tim Northover3b0846e2014-05-24 12:50:23 +00002243 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002244 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002245
John Brawn5ca5daa2017-04-20 10:13:54 +00002246 // Check for out of range values. As an exception we let Zero through,
2247 // but as tokens instead of an FPImm so that it can be matched by the
2248 // appropriate alias if one exists.
2249 if (RealVal.isPosZero()) {
2250 Parser.Lex(); // Eat the token.
2251 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2252 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2253 return MatchOperand_Success;
2254 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002255 TokError("expected compatible register or floating-point constant");
2256 return MatchOperand_ParseFail;
2257 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002258 }
2259 Parser.Lex(); // Eat the token.
2260 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2261 return MatchOperand_Success;
2262 }
2263
2264 if (!Hash)
2265 return MatchOperand_NoMatch;
2266
2267 TokError("invalid floating point immediate");
2268 return MatchOperand_ParseFail;
2269}
2270
2271/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002272OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002273AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002274 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002275 SMLoc S = getLoc();
2276
2277 if (Parser.getTok().is(AsmToken::Hash))
2278 Parser.Lex(); // Eat '#'
2279 else if (Parser.getTok().isNot(AsmToken::Integer))
2280 // Operand should start from # or should be integer, emit error otherwise.
2281 return MatchOperand_NoMatch;
2282
2283 const MCExpr *Imm;
2284 if (parseSymbolicImmVal(Imm))
2285 return MatchOperand_ParseFail;
2286 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2287 uint64_t ShiftAmount = 0;
2288 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2289 if (MCE) {
2290 int64_t Val = MCE->getValue();
2291 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002292 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002293 ShiftAmount = 12;
2294 }
2295 }
2296 SMLoc E = Parser.getTok().getLoc();
2297 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2298 getContext()));
2299 return MatchOperand_Success;
2300 }
2301
2302 // Eat ','
2303 Parser.Lex();
2304
2305 // The optional operand must be "lsl #N" where N is non-negative.
2306 if (!Parser.getTok().is(AsmToken::Identifier) ||
2307 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2308 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2309 return MatchOperand_ParseFail;
2310 }
2311
2312 // Eat 'lsl'
2313 Parser.Lex();
2314
Nirav Davee833c6c2016-11-08 18:31:04 +00002315 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002316
2317 if (Parser.getTok().isNot(AsmToken::Integer)) {
2318 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2319 return MatchOperand_ParseFail;
2320 }
2321
2322 int64_t ShiftAmount = Parser.getTok().getIntVal();
2323
2324 if (ShiftAmount < 0) {
2325 Error(Parser.getTok().getLoc(), "positive shift amount required");
2326 return MatchOperand_ParseFail;
2327 }
2328 Parser.Lex(); // Eat the number
2329
2330 SMLoc E = Parser.getTok().getLoc();
2331 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2332 S, E, getContext()));
2333 return MatchOperand_Success;
2334}
2335
2336/// parseCondCodeString - Parse a Condition Code string.
2337AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2338 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2339 .Case("eq", AArch64CC::EQ)
2340 .Case("ne", AArch64CC::NE)
2341 .Case("cs", AArch64CC::HS)
2342 .Case("hs", AArch64CC::HS)
2343 .Case("cc", AArch64CC::LO)
2344 .Case("lo", AArch64CC::LO)
2345 .Case("mi", AArch64CC::MI)
2346 .Case("pl", AArch64CC::PL)
2347 .Case("vs", AArch64CC::VS)
2348 .Case("vc", AArch64CC::VC)
2349 .Case("hi", AArch64CC::HI)
2350 .Case("ls", AArch64CC::LS)
2351 .Case("ge", AArch64CC::GE)
2352 .Case("lt", AArch64CC::LT)
2353 .Case("gt", AArch64CC::GT)
2354 .Case("le", AArch64CC::LE)
2355 .Case("al", AArch64CC::AL)
2356 .Case("nv", AArch64CC::NV)
2357 .Default(AArch64CC::Invalid);
2358 return CC;
2359}
2360
2361/// parseCondCode - Parse a Condition Code operand.
2362bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2363 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002364 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002365 SMLoc S = getLoc();
2366 const AsmToken &Tok = Parser.getTok();
2367 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2368
2369 StringRef Cond = Tok.getString();
2370 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2371 if (CC == AArch64CC::Invalid)
2372 return TokError("invalid condition code");
2373 Parser.Lex(); // Eat identifier token.
2374
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002375 if (invertCondCode) {
2376 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2377 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002378 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002379 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002380
2381 Operands.push_back(
2382 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2383 return false;
2384}
2385
2386/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2387/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002388OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002389AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002390 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002391 const AsmToken &Tok = Parser.getTok();
2392 std::string LowerID = Tok.getString().lower();
2393 AArch64_AM::ShiftExtendType ShOp =
2394 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2395 .Case("lsl", AArch64_AM::LSL)
2396 .Case("lsr", AArch64_AM::LSR)
2397 .Case("asr", AArch64_AM::ASR)
2398 .Case("ror", AArch64_AM::ROR)
2399 .Case("msl", AArch64_AM::MSL)
2400 .Case("uxtb", AArch64_AM::UXTB)
2401 .Case("uxth", AArch64_AM::UXTH)
2402 .Case("uxtw", AArch64_AM::UXTW)
2403 .Case("uxtx", AArch64_AM::UXTX)
2404 .Case("sxtb", AArch64_AM::SXTB)
2405 .Case("sxth", AArch64_AM::SXTH)
2406 .Case("sxtw", AArch64_AM::SXTW)
2407 .Case("sxtx", AArch64_AM::SXTX)
2408 .Default(AArch64_AM::InvalidShiftExtend);
2409
2410 if (ShOp == AArch64_AM::InvalidShiftExtend)
2411 return MatchOperand_NoMatch;
2412
2413 SMLoc S = Tok.getLoc();
2414 Parser.Lex();
2415
Nirav Davee833c6c2016-11-08 18:31:04 +00002416 bool Hash = parseOptionalToken(AsmToken::Hash);
2417
Tim Northover3b0846e2014-05-24 12:50:23 +00002418 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2419 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2420 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2421 ShOp == AArch64_AM::MSL) {
2422 // We expect a number here.
2423 TokError("expected #imm after shift specifier");
2424 return MatchOperand_ParseFail;
2425 }
2426
Chad Rosier2ff37b82016-12-27 16:58:09 +00002427 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002428 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2429 Operands.push_back(
2430 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2431 return MatchOperand_Success;
2432 }
2433
Chad Rosier2ff37b82016-12-27 16:58:09 +00002434 // Make sure we do actually have a number, identifier or a parenthesized
2435 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002436 SMLoc E = Parser.getTok().getLoc();
2437 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002438 !Parser.getTok().is(AsmToken::LParen) &&
2439 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002440 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002441 return MatchOperand_ParseFail;
2442 }
2443
2444 const MCExpr *ImmVal;
2445 if (getParser().parseExpression(ImmVal))
2446 return MatchOperand_ParseFail;
2447
2448 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2449 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002450 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002451 return MatchOperand_ParseFail;
2452 }
2453
Jim Grosbach57fd2622014-09-23 22:16:02 +00002454 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002455 Operands.push_back(AArch64Operand::CreateShiftExtend(
2456 ShOp, MCE->getValue(), true, S, E, getContext()));
2457 return MatchOperand_Success;
2458}
2459
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002460static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2461 if (FBS[AArch64::HasV8_1aOps])
2462 Str += "ARMv8.1a";
2463 else if (FBS[AArch64::HasV8_2aOps])
2464 Str += "ARMv8.2a";
2465 else
2466 Str += "(unknown)";
2467}
2468
2469void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2470 SMLoc S) {
2471 const uint16_t Op2 = Encoding & 7;
2472 const uint16_t Cm = (Encoding & 0x78) >> 3;
2473 const uint16_t Cn = (Encoding & 0x780) >> 7;
2474 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2475
2476 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2477
2478 Operands.push_back(
2479 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2480 Operands.push_back(
2481 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2482 Operands.push_back(
2483 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2484 Expr = MCConstantExpr::create(Op2, getContext());
2485 Operands.push_back(
2486 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2487}
2488
Tim Northover3b0846e2014-05-24 12:50:23 +00002489/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2490/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2491bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2492 OperandVector &Operands) {
2493 if (Name.find('.') != StringRef::npos)
2494 return TokError("invalid operand");
2495
2496 Mnemonic = Name;
2497 Operands.push_back(
2498 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2499
Rafael Espindola961d4692014-11-11 05:18:41 +00002500 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002501 const AsmToken &Tok = Parser.getTok();
2502 StringRef Op = Tok.getString();
2503 SMLoc S = Tok.getLoc();
2504
Tim Northover3b0846e2014-05-24 12:50:23 +00002505 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002506 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2507 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002508 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002509 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2510 std::string Str("IC " + std::string(IC->Name) + " requires ");
2511 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2512 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002513 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002514 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002515 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002516 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2517 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002518 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002519 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2520 std::string Str("DC " + std::string(DC->Name) + " requires ");
2521 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2522 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002523 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002524 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002525 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002526 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2527 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002528 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002529 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2530 std::string Str("AT " + std::string(AT->Name) + " requires ");
2531 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2532 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002533 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002534 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002535 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002536 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2537 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002538 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002539 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2540 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2541 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2542 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002543 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002544 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002545 }
2546
Tim Northover3b0846e2014-05-24 12:50:23 +00002547 Parser.Lex(); // Eat operand.
2548
2549 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2550 bool HasRegister = false;
2551
2552 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002553 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002554 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2555 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002556 HasRegister = true;
2557 }
2558
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002559 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002560 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002561 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002562 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002563
Nirav Davee833c6c2016-11-08 18:31:04 +00002564 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2565 return true;
2566
Tim Northover3b0846e2014-05-24 12:50:23 +00002567 return false;
2568}
2569
Alex Bradbury58eba092016-11-01 16:32:05 +00002570OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002571AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002572 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002573 const AsmToken &Tok = Parser.getTok();
2574
2575 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002576 if (parseOptionalToken(AsmToken::Hash) ||
2577 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002578 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002579 const MCExpr *ImmVal;
2580 SMLoc ExprLoc = getLoc();
2581 if (getParser().parseExpression(ImmVal))
2582 return MatchOperand_ParseFail;
2583 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2584 if (!MCE) {
2585 Error(ExprLoc, "immediate value expected for barrier operand");
2586 return MatchOperand_ParseFail;
2587 }
2588 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2589 Error(ExprLoc, "barrier operand out of range");
2590 return MatchOperand_ParseFail;
2591 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002592 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2593 Operands.push_back(AArch64Operand::CreateBarrier(
2594 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002595 return MatchOperand_Success;
2596 }
2597
2598 if (Tok.isNot(AsmToken::Identifier)) {
2599 TokError("invalid operand for instruction");
2600 return MatchOperand_ParseFail;
2601 }
2602
Tim Northover3b0846e2014-05-24 12:50:23 +00002603 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002604 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2605 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002606 TokError("'sy' or #imm operand expected");
2607 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002608 } else if (!DB) {
2609 TokError("invalid barrier option name");
2610 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002611 }
2612
Tim Northovere6ae6762016-07-05 21:23:04 +00002613 Operands.push_back(AArch64Operand::CreateBarrier(
2614 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002615 Parser.Lex(); // Consume the option
2616
2617 return MatchOperand_Success;
2618}
2619
Alex Bradbury58eba092016-11-01 16:32:05 +00002620OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002621AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002622 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002623 const AsmToken &Tok = Parser.getTok();
2624
2625 if (Tok.isNot(AsmToken::Identifier))
2626 return MatchOperand_NoMatch;
2627
Tim Northovere6ae6762016-07-05 21:23:04 +00002628 int MRSReg, MSRReg;
2629 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2630 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2631 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2632 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2633 } else
2634 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002635
Tim Northovere6ae6762016-07-05 21:23:04 +00002636 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2637 unsigned PStateImm = -1;
2638 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2639 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002640
Tim Northovere6ae6762016-07-05 21:23:04 +00002641 Operands.push_back(
2642 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2643 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002644 Parser.Lex(); // Eat identifier
2645
2646 return MatchOperand_Success;
2647}
2648
Florian Hahnc4422242017-11-07 13:07:50 +00002649/// tryParseNeonVectorRegister - Parse a vector register operand.
2650bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002651 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002652 if (Parser.getTok().isNot(AsmToken::Identifier))
2653 return true;
2654
2655 SMLoc S = getLoc();
2656 // Check for a vector register specifier first.
2657 StringRef Kind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002658 int Reg = -1;
2659 OperandMatchResultTy Res =
2660 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2661 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002662 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002663
2664 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2665 if (!KindRes)
2666 return true;
2667
2668 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002669 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002670 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2671 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002672
Tim Northover3b0846e2014-05-24 12:50:23 +00002673 // If there was an explicit qualifier, that goes on as a literal text
2674 // operand.
2675 if (!Kind.empty())
2676 Operands.push_back(
2677 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2678
2679 // If there is an index specifier following the register, parse that too.
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))
2684 return false;
2685 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2686 if (!MCE) {
2687 TokError("immediate value expected for vector index");
2688 return false;
2689 }
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"))
2694 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002695
2696 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2697 E, getContext()));
2698 }
2699
2700 return false;
2701}
2702
Sander de Smalen73937b72018-04-11 07:36:10 +00002703// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002704// optional kind specifier. If it is a register specifier, eat the token
2705// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002706OperandMatchResultTy
Sander de Smalen73937b72018-04-11 07:36:10 +00002707AArch64AsmParser::tryParseVectorRegister(int &Reg, StringRef &Kind,
2708 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002709 MCAsmParser &Parser = getParser();
2710 const AsmToken &Tok = Parser.getTok();
2711
Florian Hahn91f11e52017-11-07 16:45:48 +00002712 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002713 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002714
2715 StringRef Name = Tok.getString();
2716 // If there is a kind specifier, it's separated from the register name by
2717 // a '.'.
2718 size_t Start = 0, Next = Name.find('.');
2719 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002720 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002721
2722 if (RegNum) {
2723 if (Next != StringRef::npos) {
2724 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002725 if (!isValidVectorKind(Kind, MatchKind)) {
2726 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002727 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002728 }
2729 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002730 Parser.Lex(); // Eat the register token.
2731
2732 Reg = RegNum;
2733 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002734 }
2735
Sander de Smalen8e607342017-11-15 15:44:43 +00002736 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002737}
2738
Sander de Smalencd6be962017-12-20 11:02:42 +00002739/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2740OperandMatchResultTy
2741AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2742 // Check for a SVE predicate register specifier first.
2743 const SMLoc S = getLoc();
2744 StringRef Kind;
2745 int RegNum = -1;
Sander de Smalen73937b72018-04-11 07:36:10 +00002746 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002747 if (Res != MatchOperand_Success)
2748 return Res;
2749
Sander de Smalen73937b72018-04-11 07:36:10 +00002750 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2751 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002752 return MatchOperand_NoMatch;
2753
Sander de Smalen73937b72018-04-11 07:36:10 +00002754 unsigned ElementWidth = KindRes->second;
2755 Operands.push_back(AArch64Operand::CreateVectorReg(
2756 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2757 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002758
Sander de Smalen7868e742018-01-09 11:17:06 +00002759 // Not all predicates are followed by a '/m' or '/z'.
2760 MCAsmParser &Parser = getParser();
2761 if (Parser.getTok().isNot(AsmToken::Slash))
2762 return MatchOperand_Success;
2763
2764 // But when they do they shouldn't have an element type suffix.
2765 if (!Kind.empty()) {
2766 Error(S, "not expecting size suffix");
2767 return MatchOperand_ParseFail;
2768 }
2769
2770 // Add a literal slash as operand
2771 Operands.push_back(
2772 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2773
2774 Parser.Lex(); // Eat the slash.
2775
2776 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002777 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002778 if (Pred != "z" && Pred != "m") {
2779 Error(getLoc(), "expecting 'm' or 'z' predication");
2780 return MatchOperand_ParseFail;
2781 }
2782
2783 // Add zero/merge token.
2784 const char *ZM = Pred == "z" ? "z" : "m";
2785 Operands.push_back(
2786 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2787
2788 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002789 return MatchOperand_Success;
2790}
2791
Tim Northover3b0846e2014-05-24 12:50:23 +00002792/// parseRegister - Parse a non-vector register operand.
2793bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2794 SMLoc S = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00002795 // Try for a vector (neon) register.
2796 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002797 return false;
2798
2799 // Try for a scalar register.
2800 int64_t Reg = tryParseRegister();
2801 if (Reg == -1)
2802 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002803 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2804 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002805
Tim Northover3b0846e2014-05-24 12:50:23 +00002806 return false;
2807}
2808
2809bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002810 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002811 bool HasELFModifier = false;
2812 AArch64MCExpr::VariantKind RefKind;
2813
Nirav Davee833c6c2016-11-08 18:31:04 +00002814 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002815 HasELFModifier = true;
2816
Nirav Davee833c6c2016-11-08 18:31:04 +00002817 if (Parser.getTok().isNot(AsmToken::Identifier))
2818 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002819
2820 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2821 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2822 .Case("lo12", AArch64MCExpr::VK_LO12)
2823 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2824 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2825 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2826 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2827 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2828 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2829 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2830 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2831 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2832 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2833 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2834 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2835 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2836 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2837 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2838 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2839 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2840 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2841 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2842 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2843 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2844 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2845 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2846 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2847 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2848 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2849 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2850 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2851 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2852 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2853 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2854 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2855 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2856 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002857 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2858 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002859 .Default(AArch64MCExpr::VK_INVALID);
2860
Nirav Davee833c6c2016-11-08 18:31:04 +00002861 if (RefKind == AArch64MCExpr::VK_INVALID)
2862 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002863
2864 Parser.Lex(); // Eat identifier
2865
Nirav Davee833c6c2016-11-08 18:31:04 +00002866 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002867 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002868 }
2869
2870 if (getParser().parseExpression(ImmVal))
2871 return true;
2872
2873 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002874 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002875
2876 return false;
2877}
2878
2879/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2880bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002881 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002882 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
Sander de Smalen73937b72018-04-11 07:36:10 +00002883
2884 // Wrapper around parse function
2885 auto ParseVector = [this](int &Reg, StringRef &Kind, SMLoc Loc) {
2886 if (tryParseVectorRegister(Reg, Kind, RegKind::NeonVector) ==
2887 MatchOperand_Success) {
2888 if (parseVectorKind(Kind, RegKind::NeonVector))
2889 return true;
2890 llvm_unreachable("Expected a valid vector kind");
2891 }
2892
2893 Error(Loc, "vector register expected");
2894 return false;
2895 };
2896
Tim Northover3b0846e2014-05-24 12:50:23 +00002897 SMLoc S = getLoc();
2898 Parser.Lex(); // Eat left bracket token.
2899 StringRef Kind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002900 int FirstReg = -1;
2901 if (!ParseVector(FirstReg, Kind, getLoc()))
2902 return true;
2903
Tim Northover3b0846e2014-05-24 12:50:23 +00002904 int64_t PrevReg = FirstReg;
2905 unsigned Count = 1;
2906
Nirav Davee833c6c2016-11-08 18:31:04 +00002907 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002908 SMLoc Loc = getLoc();
2909 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002910
2911 int Reg;
2912 if (!ParseVector(Reg, NextKind, getLoc()))
Tim Northover3b0846e2014-05-24 12:50:23 +00002913 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002914
Tim Northover3b0846e2014-05-24 12:50:23 +00002915 // Any Kind suffices must match on all regs in the list.
2916 if (Kind != NextKind)
2917 return Error(Loc, "mismatched register size suffix");
2918
2919 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2920
2921 if (Space == 0 || Space > 3) {
2922 return Error(Loc, "invalid number of vectors");
2923 }
2924
2925 Count += Space;
2926 }
2927 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002928 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002929 SMLoc Loc = getLoc();
2930 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002931 int Reg;
2932 if (!ParseVector(Reg, NextKind, getLoc()))
Tim Northover3b0846e2014-05-24 12:50:23 +00002933 return true;
2934 // Any Kind suffices must match on all regs in the list.
2935 if (Kind != NextKind)
2936 return Error(Loc, "mismatched register size suffix");
2937
2938 // Registers must be incremental (with wraparound at 31)
2939 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2940 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2941 return Error(Loc, "registers must be sequential");
2942
2943 PrevReg = Reg;
2944 ++Count;
2945 }
2946 }
2947
Nirav Davee833c6c2016-11-08 18:31:04 +00002948 if (parseToken(AsmToken::RCurly, "'}' expected"))
2949 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002950
2951 if (Count > 4)
2952 return Error(S, "invalid number of vectors");
2953
2954 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00002955 unsigned ElementWidth = 0;
2956 if (!Kind.empty()) {
2957 if (const auto &VK = parseVectorKind(Kind, RegKind::NeonVector))
2958 std::tie(NumElements, ElementWidth) = *VK;
2959 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002960
2961 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen73937b72018-04-11 07:36:10 +00002962 FirstReg, Count, NumElements, ElementWidth, S, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002963
2964 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002965 SMLoc SIdx = getLoc();
2966 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002967 const MCExpr *ImmVal;
2968 if (getParser().parseExpression(ImmVal))
2969 return false;
2970 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2971 if (!MCE) {
2972 TokError("immediate value expected for vector index");
2973 return false;
2974 }
2975
2976 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002977 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002978 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002979
2980 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2981 E, getContext()));
2982 }
2983 return false;
2984}
2985
Alex Bradbury58eba092016-11-01 16:32:05 +00002986OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002987AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002988 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002989 const AsmToken &Tok = Parser.getTok();
2990 if (!Tok.is(AsmToken::Identifier))
2991 return MatchOperand_NoMatch;
2992
Florian Hahnc4422242017-11-07 13:07:50 +00002993 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00002994
2995 MCContext &Ctx = getContext();
2996 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
2997 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
2998 return MatchOperand_NoMatch;
2999
3000 SMLoc S = getLoc();
3001 Parser.Lex(); // Eat register
3002
Nirav Davee833c6c2016-11-08 18:31:04 +00003003 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003004 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003005 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003006 return MatchOperand_Success;
3007 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003008
Nirav Davee833c6c2016-11-08 18:31:04 +00003009 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003010
3011 if (Parser.getTok().isNot(AsmToken::Integer)) {
3012 Error(getLoc(), "index must be absent or #0");
3013 return MatchOperand_ParseFail;
3014 }
3015
3016 const MCExpr *ImmVal;
3017 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3018 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3019 Error(getLoc(), "index must be absent or #0");
3020 return MatchOperand_ParseFail;
3021 }
3022
3023 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003024 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003025 return MatchOperand_Success;
3026}
3027
3028/// parseOperand - Parse a arm instruction operand. For now this parses the
3029/// operand regardless of the mnemonic.
3030bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3031 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003032 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003033
3034 OperandMatchResultTy ResTy =
3035 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3036
Tim Northover3b0846e2014-05-24 12:50:23 +00003037 // Check if the current operand has a custom associated parser, if so, try to
3038 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003039 if (ResTy == MatchOperand_Success)
3040 return false;
3041 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3042 // there was a match, but an error occurred, in which case, just return that
3043 // the operand parsing failed.
3044 if (ResTy == MatchOperand_ParseFail)
3045 return true;
3046
3047 // Nothing custom, so do general case parsing.
3048 SMLoc S, E;
3049 switch (getLexer().getKind()) {
3050 default: {
3051 SMLoc S = getLoc();
3052 const MCExpr *Expr;
3053 if (parseSymbolicImmVal(Expr))
3054 return Error(S, "invalid operand");
3055
3056 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3057 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3058 return false;
3059 }
3060 case AsmToken::LBrac: {
3061 SMLoc Loc = Parser.getTok().getLoc();
3062 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3063 getContext()));
3064 Parser.Lex(); // Eat '['
3065
3066 // There's no comma after a '[', so we can parse the next operand
3067 // immediately.
3068 return parseOperand(Operands, false, false);
3069 }
3070 case AsmToken::LCurly:
3071 return parseVectorList(Operands);
3072 case AsmToken::Identifier: {
3073 // If we're expecting a Condition Code operand, then just parse that.
3074 if (isCondCode)
3075 return parseCondCode(Operands, invertCondCode);
3076
3077 // If it's a register name, parse it.
3078 if (!parseRegister(Operands))
3079 return false;
3080
3081 // This could be an optional "shift" or "extend" operand.
3082 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3083 // We can only continue if no tokens were eaten.
3084 if (GotShift != MatchOperand_NoMatch)
3085 return GotShift;
3086
3087 // This was not a register so parse other operands that start with an
3088 // identifier (like labels) as expressions and create them as immediates.
3089 const MCExpr *IdVal;
3090 S = getLoc();
3091 if (getParser().parseExpression(IdVal))
3092 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003093 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3094 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3095 return false;
3096 }
3097 case AsmToken::Integer:
3098 case AsmToken::Real:
3099 case AsmToken::Hash: {
3100 // #42 -> immediate.
3101 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003102
3103 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003104
3105 // Parse a negative sign
3106 bool isNegative = false;
3107 if (Parser.getTok().is(AsmToken::Minus)) {
3108 isNegative = true;
3109 // We need to consume this token only when we have a Real, otherwise
3110 // we let parseSymbolicImmVal take care of it
3111 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3112 Parser.Lex();
3113 }
3114
3115 // The only Real that should come through here is a literal #0.0 for
3116 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3117 // so convert the value.
3118 const AsmToken &Tok = Parser.getTok();
3119 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003120 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003121 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3122 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3123 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3124 Mnemonic != "fcmlt")
3125 return TokError("unexpected floating point literal");
3126 else if (IntVal != 0 || isNegative)
3127 return TokError("expected floating-point constant #0.0");
3128 Parser.Lex(); // Eat the token.
3129
3130 Operands.push_back(
3131 AArch64Operand::CreateToken("#0", false, S, getContext()));
3132 Operands.push_back(
3133 AArch64Operand::CreateToken(".0", false, S, getContext()));
3134 return false;
3135 }
3136
3137 const MCExpr *ImmVal;
3138 if (parseSymbolicImmVal(ImmVal))
3139 return true;
3140
3141 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3142 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3143 return false;
3144 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003145 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003146 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003147 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003148 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003149 Parser.Lex(); // Eat '='
3150 const MCExpr *SubExprVal;
3151 if (getParser().parseExpression(SubExprVal))
3152 return true;
3153
David Peixottoae5ba762014-07-18 16:05:14 +00003154 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003155 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003156 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003157
3158 bool IsXReg =
3159 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3160 Operands[1]->getReg());
3161
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003162 MCContext& Ctx = getContext();
3163 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3164 // 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 +00003165 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003166 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3167 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3168 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3169 ShiftAmt += 16;
3170 Imm >>= 16;
3171 }
3172 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3173 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3174 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003175 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003176 if (ShiftAmt)
3177 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3178 ShiftAmt, true, S, E, Ctx));
3179 return false;
3180 }
David Peixottoae5ba762014-07-18 16:05:14 +00003181 APInt Simm = APInt(64, Imm << ShiftAmt);
3182 // check if the immediate is an unsigned or signed 32-bit int for W regs
3183 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3184 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003185 }
3186 // 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 +00003187 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003188 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003189 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3190 return false;
3191 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003192 }
3193}
3194
3195/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3196/// operands.
3197bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3198 StringRef Name, SMLoc NameLoc,
3199 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003200 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003201 Name = StringSwitch<StringRef>(Name.lower())
3202 .Case("beq", "b.eq")
3203 .Case("bne", "b.ne")
3204 .Case("bhs", "b.hs")
3205 .Case("bcs", "b.cs")
3206 .Case("blo", "b.lo")
3207 .Case("bcc", "b.cc")
3208 .Case("bmi", "b.mi")
3209 .Case("bpl", "b.pl")
3210 .Case("bvs", "b.vs")
3211 .Case("bvc", "b.vc")
3212 .Case("bhi", "b.hi")
3213 .Case("bls", "b.ls")
3214 .Case("bge", "b.ge")
3215 .Case("blt", "b.lt")
3216 .Case("bgt", "b.gt")
3217 .Case("ble", "b.le")
3218 .Case("bal", "b.al")
3219 .Case("bnv", "b.nv")
3220 .Default(Name);
3221
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003222 // First check for the AArch64-specific .req directive.
3223 if (Parser.getTok().is(AsmToken::Identifier) &&
3224 Parser.getTok().getIdentifier() == ".req") {
3225 parseDirectiveReq(Name, NameLoc);
3226 // We always return 'error' for this, as we're done with this
3227 // statement and don't need to match the 'instruction."
3228 return true;
3229 }
3230
Tim Northover3b0846e2014-05-24 12:50:23 +00003231 // Create the leading tokens for the mnemonic, split by '.' characters.
3232 size_t Start = 0, Next = Name.find('.');
3233 StringRef Head = Name.slice(Start, Next);
3234
3235 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003236 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3237 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003238
3239 Operands.push_back(
3240 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3241 Mnemonic = Head;
3242
3243 // Handle condition codes for a branch mnemonic
3244 if (Head == "b" && Next != StringRef::npos) {
3245 Start = Next;
3246 Next = Name.find('.', Start + 1);
3247 Head = Name.slice(Start + 1, Next);
3248
3249 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3250 (Head.data() - Name.data()));
3251 AArch64CC::CondCode CC = parseCondCodeString(Head);
3252 if (CC == AArch64CC::Invalid)
3253 return Error(SuffixLoc, "invalid condition code");
3254 Operands.push_back(
3255 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3256 Operands.push_back(
3257 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3258 }
3259
3260 // Add the remaining tokens in the mnemonic.
3261 while (Next != StringRef::npos) {
3262 Start = Next;
3263 Next = Name.find('.', Start + 1);
3264 Head = Name.slice(Start, Next);
3265 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3266 (Head.data() - Name.data()) + 1);
3267 Operands.push_back(
3268 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3269 }
3270
3271 // Conditional compare instructions have a Condition Code operand, which needs
3272 // to be parsed and an immediate operand created.
3273 bool condCodeFourthOperand =
3274 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3275 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3276 Head == "csinc" || Head == "csinv" || Head == "csneg");
3277
3278 // These instructions are aliases to some of the conditional select
3279 // instructions. However, the condition code is inverted in the aliased
3280 // instruction.
3281 //
3282 // FIXME: Is this the correct way to handle these? Or should the parser
3283 // generate the aliased instructions directly?
3284 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3285 bool condCodeThirdOperand =
3286 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3287
3288 // Read the remaining operands.
3289 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3290 // Read the first operand.
3291 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003292 return true;
3293 }
3294
3295 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003296 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003297 // Parse and remember the operand.
3298 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3299 (N == 3 && condCodeThirdOperand) ||
3300 (N == 2 && condCodeSecondOperand),
3301 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003302 return true;
3303 }
3304
3305 // After successfully parsing some operands there are two special cases to
3306 // consider (i.e. notional operands not separated by commas). Both are due
3307 // to memory specifiers:
3308 // + An RBrac will end an address for load/store/prefetch
3309 // + An '!' will indicate a pre-indexed operation.
3310 //
3311 // It's someone else's responsibility to make sure these tokens are sane
3312 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003313
Nirav Davee833c6c2016-11-08 18:31:04 +00003314 SMLoc RLoc = Parser.getTok().getLoc();
3315 if (parseOptionalToken(AsmToken::RBrac))
3316 Operands.push_back(
3317 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3318 SMLoc ELoc = Parser.getTok().getLoc();
3319 if (parseOptionalToken(AsmToken::Exclaim))
3320 Operands.push_back(
3321 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003322
3323 ++N;
3324 }
3325 }
3326
Nirav Davee833c6c2016-11-08 18:31:04 +00003327 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3328 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003329
Tim Northover3b0846e2014-05-24 12:50:23 +00003330 return false;
3331}
3332
3333// FIXME: This entire function is a giant hack to provide us with decent
3334// operand range validation/diagnostics until TableGen/MC can be extended
3335// to support autogeneration of this kind of validation.
3336bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3337 SmallVectorImpl<SMLoc> &Loc) {
3338 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3339 // Check for indexed addressing modes w/ the base register being the
3340 // same as a destination/source register or pair load where
3341 // the Rt == Rt2. All of those are undefined behaviour.
3342 switch (Inst.getOpcode()) {
3343 case AArch64::LDPSWpre:
3344 case AArch64::LDPWpost:
3345 case AArch64::LDPWpre:
3346 case AArch64::LDPXpost:
3347 case AArch64::LDPXpre: {
3348 unsigned Rt = Inst.getOperand(1).getReg();
3349 unsigned Rt2 = Inst.getOperand(2).getReg();
3350 unsigned Rn = Inst.getOperand(3).getReg();
3351 if (RI->isSubRegisterEq(Rn, Rt))
3352 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3353 "is also a destination");
3354 if (RI->isSubRegisterEq(Rn, Rt2))
3355 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3356 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003357 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003358 }
3359 case AArch64::LDPDi:
3360 case AArch64::LDPQi:
3361 case AArch64::LDPSi:
3362 case AArch64::LDPSWi:
3363 case AArch64::LDPWi:
3364 case AArch64::LDPXi: {
3365 unsigned Rt = Inst.getOperand(0).getReg();
3366 unsigned Rt2 = Inst.getOperand(1).getReg();
3367 if (Rt == Rt2)
3368 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3369 break;
3370 }
3371 case AArch64::LDPDpost:
3372 case AArch64::LDPDpre:
3373 case AArch64::LDPQpost:
3374 case AArch64::LDPQpre:
3375 case AArch64::LDPSpost:
3376 case AArch64::LDPSpre:
3377 case AArch64::LDPSWpost: {
3378 unsigned Rt = Inst.getOperand(1).getReg();
3379 unsigned Rt2 = Inst.getOperand(2).getReg();
3380 if (Rt == Rt2)
3381 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3382 break;
3383 }
3384 case AArch64::STPDpost:
3385 case AArch64::STPDpre:
3386 case AArch64::STPQpost:
3387 case AArch64::STPQpre:
3388 case AArch64::STPSpost:
3389 case AArch64::STPSpre:
3390 case AArch64::STPWpost:
3391 case AArch64::STPWpre:
3392 case AArch64::STPXpost:
3393 case AArch64::STPXpre: {
3394 unsigned Rt = Inst.getOperand(1).getReg();
3395 unsigned Rt2 = Inst.getOperand(2).getReg();
3396 unsigned Rn = Inst.getOperand(3).getReg();
3397 if (RI->isSubRegisterEq(Rn, Rt))
3398 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3399 "is also a source");
3400 if (RI->isSubRegisterEq(Rn, Rt2))
3401 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3402 "is also a source");
3403 break;
3404 }
3405 case AArch64::LDRBBpre:
3406 case AArch64::LDRBpre:
3407 case AArch64::LDRHHpre:
3408 case AArch64::LDRHpre:
3409 case AArch64::LDRSBWpre:
3410 case AArch64::LDRSBXpre:
3411 case AArch64::LDRSHWpre:
3412 case AArch64::LDRSHXpre:
3413 case AArch64::LDRSWpre:
3414 case AArch64::LDRWpre:
3415 case AArch64::LDRXpre:
3416 case AArch64::LDRBBpost:
3417 case AArch64::LDRBpost:
3418 case AArch64::LDRHHpost:
3419 case AArch64::LDRHpost:
3420 case AArch64::LDRSBWpost:
3421 case AArch64::LDRSBXpost:
3422 case AArch64::LDRSHWpost:
3423 case AArch64::LDRSHXpost:
3424 case AArch64::LDRSWpost:
3425 case AArch64::LDRWpost:
3426 case AArch64::LDRXpost: {
3427 unsigned Rt = Inst.getOperand(1).getReg();
3428 unsigned Rn = Inst.getOperand(2).getReg();
3429 if (RI->isSubRegisterEq(Rn, Rt))
3430 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3431 "is also a source");
3432 break;
3433 }
3434 case AArch64::STRBBpost:
3435 case AArch64::STRBpost:
3436 case AArch64::STRHHpost:
3437 case AArch64::STRHpost:
3438 case AArch64::STRWpost:
3439 case AArch64::STRXpost:
3440 case AArch64::STRBBpre:
3441 case AArch64::STRBpre:
3442 case AArch64::STRHHpre:
3443 case AArch64::STRHpre:
3444 case AArch64::STRWpre:
3445 case AArch64::STRXpre: {
3446 unsigned Rt = Inst.getOperand(1).getReg();
3447 unsigned Rn = Inst.getOperand(2).getReg();
3448 if (RI->isSubRegisterEq(Rn, Rt))
3449 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3450 "is also a source");
3451 break;
3452 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003453 case AArch64::STXRB:
3454 case AArch64::STXRH:
3455 case AArch64::STXRW:
3456 case AArch64::STXRX:
3457 case AArch64::STLXRB:
3458 case AArch64::STLXRH:
3459 case AArch64::STLXRW:
3460 case AArch64::STLXRX: {
3461 unsigned Rs = Inst.getOperand(0).getReg();
3462 unsigned Rt = Inst.getOperand(1).getReg();
3463 unsigned Rn = Inst.getOperand(2).getReg();
3464 if (RI->isSubRegisterEq(Rt, Rs) ||
3465 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3466 return Error(Loc[0],
3467 "unpredictable STXR instruction, status is also a source");
3468 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003469 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003470 case AArch64::STXPW:
3471 case AArch64::STXPX:
3472 case AArch64::STLXPW:
3473 case AArch64::STLXPX: {
3474 unsigned Rs = Inst.getOperand(0).getReg();
3475 unsigned Rt1 = Inst.getOperand(1).getReg();
3476 unsigned Rt2 = Inst.getOperand(2).getReg();
3477 unsigned Rn = Inst.getOperand(3).getReg();
3478 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3479 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3480 return Error(Loc[0],
3481 "unpredictable STXP instruction, status is also a source");
3482 break;
3483 }
3484 }
3485
Tim Northover3b0846e2014-05-24 12:50:23 +00003486
3487 // Now check immediate ranges. Separate from the above as there is overlap
3488 // in the instructions being checked and this keeps the nested conditionals
3489 // to a minimum.
3490 switch (Inst.getOpcode()) {
3491 case AArch64::ADDSWri:
3492 case AArch64::ADDSXri:
3493 case AArch64::ADDWri:
3494 case AArch64::ADDXri:
3495 case AArch64::SUBSWri:
3496 case AArch64::SUBSXri:
3497 case AArch64::SUBWri:
3498 case AArch64::SUBXri: {
3499 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3500 // some slight duplication here.
3501 if (Inst.getOperand(2).isExpr()) {
3502 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3503 AArch64MCExpr::VariantKind ELFRefKind;
3504 MCSymbolRefExpr::VariantKind DarwinRefKind;
3505 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003506 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3507
3508 // Only allow these with ADDXri.
3509 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3510 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3511 Inst.getOpcode() == AArch64::ADDXri)
3512 return false;
3513
3514 // Only allow these with ADDXri/ADDWri
3515 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3516 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3517 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3518 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3519 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3520 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3521 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003522 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3523 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3524 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003525 (Inst.getOpcode() == AArch64::ADDXri ||
3526 Inst.getOpcode() == AArch64::ADDWri))
3527 return false;
3528
3529 // Don't allow symbol refs in the immediate field otherwise
3530 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3531 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3532 // 'cmp w0, 'borked')
3533 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003534 }
Diana Picusc93518d2016-10-11 09:17:47 +00003535 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003536 }
3537 return false;
3538 }
3539 default:
3540 return false;
3541 }
3542}
3543
Craig Topper05515562017-10-26 06:46:41 +00003544static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3545 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003546
3547bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3548 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003549 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003550 case Match_InvalidTiedOperand:
3551 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003552 case Match_MissingFeature:
3553 return Error(Loc,
3554 "instruction requires a CPU feature not currently enabled");
3555 case Match_InvalidOperand:
3556 return Error(Loc, "invalid operand for instruction");
3557 case Match_InvalidSuffix:
3558 return Error(Loc, "invalid type suffix for instruction");
3559 case Match_InvalidCondCode:
3560 return Error(Loc, "expected AArch64 condition code");
3561 case Match_AddSubRegExtendSmall:
3562 return Error(Loc,
3563 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3564 case Match_AddSubRegExtendLarge:
3565 return Error(Loc,
3566 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3567 case Match_AddSubSecondSource:
3568 return Error(Loc,
3569 "expected compatible register, symbol or integer in range [0, 4095]");
3570 case Match_LogicalSecondSource:
3571 return Error(Loc, "expected compatible register or logical immediate");
3572 case Match_InvalidMovImm32Shift:
3573 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3574 case Match_InvalidMovImm64Shift:
3575 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3576 case Match_AddSubRegShift32:
3577 return Error(Loc,
3578 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3579 case Match_AddSubRegShift64:
3580 return Error(Loc,
3581 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3582 case Match_InvalidFPImm:
3583 return Error(Loc,
3584 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003585 case Match_InvalidMemoryIndexedSImm6:
3586 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003587 case Match_InvalidMemoryIndexedSImm5:
3588 return Error(Loc, "index must be an integer in range [-16, 15].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003589 case Match_InvalidMemoryIndexedSImm9:
3590 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003591 case Match_InvalidMemoryIndexedSImm10:
3592 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003593 case Match_InvalidMemoryIndexed4SImm7:
3594 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3595 case Match_InvalidMemoryIndexed8SImm7:
3596 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3597 case Match_InvalidMemoryIndexed16SImm7:
3598 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3599 case Match_InvalidMemoryWExtend8:
3600 return Error(Loc,
3601 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3602 case Match_InvalidMemoryWExtend16:
3603 return Error(Loc,
3604 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3605 case Match_InvalidMemoryWExtend32:
3606 return Error(Loc,
3607 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3608 case Match_InvalidMemoryWExtend64:
3609 return Error(Loc,
3610 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3611 case Match_InvalidMemoryWExtend128:
3612 return Error(Loc,
3613 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3614 case Match_InvalidMemoryXExtend8:
3615 return Error(Loc,
3616 "expected 'lsl' or 'sxtx' with optional shift of #0");
3617 case Match_InvalidMemoryXExtend16:
3618 return Error(Loc,
3619 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3620 case Match_InvalidMemoryXExtend32:
3621 return Error(Loc,
3622 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3623 case Match_InvalidMemoryXExtend64:
3624 return Error(Loc,
3625 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3626 case Match_InvalidMemoryXExtend128:
3627 return Error(Loc,
3628 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3629 case Match_InvalidMemoryIndexed1:
3630 return Error(Loc, "index must be an integer in range [0, 4095].");
3631 case Match_InvalidMemoryIndexed2:
3632 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3633 case Match_InvalidMemoryIndexed4:
3634 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3635 case Match_InvalidMemoryIndexed8:
3636 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3637 case Match_InvalidMemoryIndexed16:
3638 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003639 case Match_InvalidImm0_1:
3640 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003641 case Match_InvalidImm0_7:
3642 return Error(Loc, "immediate must be an integer in range [0, 7].");
3643 case Match_InvalidImm0_15:
3644 return Error(Loc, "immediate must be an integer in range [0, 15].");
3645 case Match_InvalidImm0_31:
3646 return Error(Loc, "immediate must be an integer in range [0, 31].");
3647 case Match_InvalidImm0_63:
3648 return Error(Loc, "immediate must be an integer in range [0, 63].");
3649 case Match_InvalidImm0_127:
3650 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003651 case Match_InvalidImm0_255:
3652 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003653 case Match_InvalidImm0_65535:
3654 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3655 case Match_InvalidImm1_8:
3656 return Error(Loc, "immediate must be an integer in range [1, 8].");
3657 case Match_InvalidImm1_16:
3658 return Error(Loc, "immediate must be an integer in range [1, 16].");
3659 case Match_InvalidImm1_32:
3660 return Error(Loc, "immediate must be an integer in range [1, 32].");
3661 case Match_InvalidImm1_64:
3662 return Error(Loc, "immediate must be an integer in range [1, 64].");
3663 case Match_InvalidIndex1:
3664 return Error(Loc, "expected lane specifier '[1]'");
3665 case Match_InvalidIndexB:
3666 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3667 case Match_InvalidIndexH:
3668 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3669 case Match_InvalidIndexS:
3670 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3671 case Match_InvalidIndexD:
3672 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3673 case Match_InvalidLabel:
3674 return Error(Loc, "expected label or encodable integer pc offset");
3675 case Match_MRS:
3676 return Error(Loc, "expected readable system register");
3677 case Match_MSR:
3678 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003679 case Match_InvalidComplexRotationEven:
3680 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3681 case Match_InvalidComplexRotationOdd:
3682 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003683 case Match_MnemonicFail: {
3684 std::string Suggestion = AArch64MnemonicSpellCheck(
3685 ((AArch64Operand &)*Operands[0]).getToken(),
3686 ComputeAvailableFeatures(STI->getFeatureBits()));
3687 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3688 }
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003689 case Match_InvalidSVEPattern:
3690 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003691 case Match_InvalidSVEPredicateAnyReg:
3692 case Match_InvalidSVEPredicateBReg:
3693 case Match_InvalidSVEPredicateHReg:
3694 case Match_InvalidSVEPredicateSReg:
3695 case Match_InvalidSVEPredicateDReg:
3696 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003697 case Match_InvalidSVEPredicate3bAnyReg:
3698 case Match_InvalidSVEPredicate3bBReg:
3699 case Match_InvalidSVEPredicate3bHReg:
3700 case Match_InvalidSVEPredicate3bSReg:
3701 case Match_InvalidSVEPredicate3bDReg:
3702 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003703 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003704 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003705 }
3706}
3707
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003708static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003709
3710bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3711 OperandVector &Operands,
3712 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003713 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003714 bool MatchingInlineAsm) {
3715 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003716 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3717 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003718
David Blaikie960ea3f2014-06-08 16:18:35 +00003719 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003720 unsigned NumOperands = Operands.size();
3721
3722 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003723 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3724 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003725 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003726 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003727 if (Op3CE) {
3728 uint64_t Op3Val = Op3CE->getValue();
3729 uint64_t NewOp3Val = 0;
3730 uint64_t NewOp4Val = 0;
3731 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003732 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003733 NewOp3Val = (32 - Op3Val) & 0x1f;
3734 NewOp4Val = 31 - Op3Val;
3735 } else {
3736 NewOp3Val = (64 - Op3Val) & 0x3f;
3737 NewOp4Val = 63 - Op3Val;
3738 }
3739
Jim Grosbach13760bd2015-05-30 01:25:56 +00003740 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3741 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003742
3743 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003744 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003745 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003746 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3747 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3748 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003749 }
3750 }
Tim Northover03b99f62015-04-30 18:28:58 +00003751 } else if (NumOperands == 4 && Tok == "bfc") {
3752 // FIXME: Horrible hack to handle BFC->BFM alias.
3753 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3754 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3755 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3756
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003757 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003758 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3759 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3760
3761 if (LSBCE && WidthCE) {
3762 uint64_t LSB = LSBCE->getValue();
3763 uint64_t Width = WidthCE->getValue();
3764
3765 uint64_t RegWidth = 0;
3766 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3767 Op1.getReg()))
3768 RegWidth = 64;
3769 else
3770 RegWidth = 32;
3771
3772 if (LSB >= RegWidth)
3773 return Error(LSBOp.getStartLoc(),
3774 "expected integer in range [0, 31]");
3775 if (Width < 1 || Width > RegWidth)
3776 return Error(WidthOp.getStartLoc(),
3777 "expected integer in range [1, 32]");
3778
3779 uint64_t ImmR = 0;
3780 if (RegWidth == 32)
3781 ImmR = (32 - LSB) & 0x1f;
3782 else
3783 ImmR = (64 - LSB) & 0x3f;
3784
3785 uint64_t ImmS = Width - 1;
3786
3787 if (ImmR != 0 && ImmS >= ImmR)
3788 return Error(WidthOp.getStartLoc(),
3789 "requested insert overflows register");
3790
Jim Grosbach13760bd2015-05-30 01:25:56 +00003791 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3792 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003793 Operands[0] = AArch64Operand::CreateToken(
3794 "bfm", false, Op.getStartLoc(), getContext());
3795 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003796 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3797 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003798 Operands[3] = AArch64Operand::CreateImm(
3799 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3800 Operands.emplace_back(
3801 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3802 WidthOp.getEndLoc(), getContext()));
3803 }
3804 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003805 } else if (NumOperands == 5) {
3806 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3807 // UBFIZ -> UBFM aliases.
3808 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003809 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3810 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3811 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003812
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003813 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003814 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3815 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003816
3817 if (Op3CE && Op4CE) {
3818 uint64_t Op3Val = Op3CE->getValue();
3819 uint64_t Op4Val = Op4CE->getValue();
3820
3821 uint64_t RegWidth = 0;
3822 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003823 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003824 RegWidth = 64;
3825 else
3826 RegWidth = 32;
3827
3828 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003829 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003830 "expected integer in range [0, 31]");
3831 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003832 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003833 "expected integer in range [1, 32]");
3834
3835 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003836 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003837 NewOp3Val = (32 - Op3Val) & 0x1f;
3838 else
3839 NewOp3Val = (64 - Op3Val) & 0x3f;
3840
3841 uint64_t NewOp4Val = Op4Val - 1;
3842
3843 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003844 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003845 "requested insert overflows register");
3846
3847 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003848 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003849 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003850 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003851 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003852 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003853 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003854 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003855 if (Tok == "bfi")
3856 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003857 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003858 else if (Tok == "sbfiz")
3859 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003860 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003861 else if (Tok == "ubfiz")
3862 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003863 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003864 else
3865 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003866 }
3867 }
3868
3869 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3870 // UBFX -> UBFM aliases.
3871 } else if (NumOperands == 5 &&
3872 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003873 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3874 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3875 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003876
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003877 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003878 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3879 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003880
3881 if (Op3CE && Op4CE) {
3882 uint64_t Op3Val = Op3CE->getValue();
3883 uint64_t Op4Val = Op4CE->getValue();
3884
3885 uint64_t RegWidth = 0;
3886 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003887 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003888 RegWidth = 64;
3889 else
3890 RegWidth = 32;
3891
3892 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003893 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003894 "expected integer in range [0, 31]");
3895 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003896 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003897 "expected integer in range [1, 32]");
3898
3899 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3900
3901 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003902 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003903 "requested extract overflows register");
3904
3905 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003906 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003907 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003908 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003909 if (Tok == "bfxil")
3910 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003911 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003912 else if (Tok == "sbfx")
3913 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003914 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003915 else if (Tok == "ubfx")
3916 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003917 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003918 else
3919 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003920 }
3921 }
3922 }
3923 }
Tim Northover9097a072017-12-18 10:36:00 +00003924
3925 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
3926 // instruction for FP registers correctly in some rare circumstances. Convert
3927 // it to a safe instruction and warn (because silently changing someone's
3928 // assembly is rude).
3929 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
3930 NumOperands == 4 && Tok == "movi") {
3931 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3932 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3933 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3934 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
3935 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
3936 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
3937 if (Suffix.lower() == ".2d" &&
3938 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
3939 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
3940 " correctly on this CPU, converting to equivalent movi.16b");
3941 // Switch the suffix to .16b.
3942 unsigned Idx = Op1.isToken() ? 1 : 2;
3943 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
3944 getContext());
3945 }
3946 }
3947 }
3948
Tim Northover3b0846e2014-05-24 12:50:23 +00003949 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3950 // InstAlias can't quite handle this since the reg classes aren't
3951 // subclasses.
3952 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3953 // The source register can be Wn here, but the matcher expects a
3954 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003955 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003956 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003957 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003958 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3959 Op.getStartLoc(), Op.getEndLoc(),
3960 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003961 }
3962 }
3963 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3964 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003965 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003966 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003967 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003968 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003969 // The source register can be Wn here, but the matcher expects a
3970 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003971 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003972 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003973 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003974 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3975 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003976 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003977 }
3978 }
3979 }
3980 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3981 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003982 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003983 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003984 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003985 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003986 // The source register can be Wn here, but the matcher expects a
3987 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003988 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003989 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003990 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003991 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3992 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003993 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003994 }
3995 }
3996 }
3997
Tim Northover3b0846e2014-05-24 12:50:23 +00003998 MCInst Inst;
3999 // First try to match against the secondary set of tables containing the
4000 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4001 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004002 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004003
4004 // If that fails, try against the alternate table containing long-form NEON:
4005 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004006 if (MatchResult != Match_Success) {
4007 // But first, save the short-form match result: we can use it in case the
4008 // long-form match also fails.
4009 auto ShortFormNEONErrorInfo = ErrorInfo;
4010 auto ShortFormNEONMatchResult = MatchResult;
4011
Tim Northover3b0846e2014-05-24 12:50:23 +00004012 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004013 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004014
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004015 // Now, both matches failed, and the long-form match failed on the mnemonic
4016 // suffix token operand. The short-form match failure is probably more
4017 // relevant: use it instead.
4018 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004019 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004020 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4021 MatchResult = ShortFormNEONMatchResult;
4022 ErrorInfo = ShortFormNEONErrorInfo;
4023 }
4024 }
4025
Tim Northover3b0846e2014-05-24 12:50:23 +00004026 switch (MatchResult) {
4027 case Match_Success: {
4028 // Perform range checking and other semantic validations
4029 SmallVector<SMLoc, 8> OperandLocs;
4030 NumOperands = Operands.size();
4031 for (unsigned i = 1; i < NumOperands; ++i)
4032 OperandLocs.push_back(Operands[i]->getStartLoc());
4033 if (validateInstruction(Inst, OperandLocs))
4034 return true;
4035
4036 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004037 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004038 return false;
4039 }
4040 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004041 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004042 // Special case the error message for the very common case where only
4043 // a single subtarget feature is missing (neon, e.g.).
4044 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004045 uint64_t Mask = 1;
4046 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4047 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004048 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004049 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004050 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004051 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004052 }
4053 return Error(IDLoc, Msg);
4054 }
4055 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004056 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004057 case Match_InvalidOperand: {
4058 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004059
Tim Northover26bb14e2014-08-18 11:49:42 +00004060 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004061 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004062 return Error(IDLoc, "too few operands for instruction",
4063 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004064
David Blaikie960ea3f2014-06-08 16:18:35 +00004065 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004066 if (ErrorLoc == SMLoc())
4067 ErrorLoc = IDLoc;
4068 }
4069 // If the match failed on a suffix token operand, tweak the diagnostic
4070 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004071 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4072 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004073 MatchResult = Match_InvalidSuffix;
4074
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004075 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004076 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004077 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004078 case Match_InvalidMemoryIndexed1:
4079 case Match_InvalidMemoryIndexed2:
4080 case Match_InvalidMemoryIndexed4:
4081 case Match_InvalidMemoryIndexed8:
4082 case Match_InvalidMemoryIndexed16:
4083 case Match_InvalidCondCode:
4084 case Match_AddSubRegExtendSmall:
4085 case Match_AddSubRegExtendLarge:
4086 case Match_AddSubSecondSource:
4087 case Match_LogicalSecondSource:
4088 case Match_AddSubRegShift32:
4089 case Match_AddSubRegShift64:
4090 case Match_InvalidMovImm32Shift:
4091 case Match_InvalidMovImm64Shift:
4092 case Match_InvalidFPImm:
4093 case Match_InvalidMemoryWExtend8:
4094 case Match_InvalidMemoryWExtend16:
4095 case Match_InvalidMemoryWExtend32:
4096 case Match_InvalidMemoryWExtend64:
4097 case Match_InvalidMemoryWExtend128:
4098 case Match_InvalidMemoryXExtend8:
4099 case Match_InvalidMemoryXExtend16:
4100 case Match_InvalidMemoryXExtend32:
4101 case Match_InvalidMemoryXExtend64:
4102 case Match_InvalidMemoryXExtend128:
Sander de Smalen909cf952018-01-19 15:22:00 +00004103 case Match_InvalidMemoryIndexedSImm6:
Tim Northover3b0846e2014-05-24 12:50:23 +00004104 case Match_InvalidMemoryIndexed4SImm7:
4105 case Match_InvalidMemoryIndexed8SImm7:
4106 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen30fda452018-04-10 07:01:53 +00004107 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004108 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004109 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004110 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004111 case Match_InvalidImm0_7:
4112 case Match_InvalidImm0_15:
4113 case Match_InvalidImm0_31:
4114 case Match_InvalidImm0_63:
4115 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004116 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004117 case Match_InvalidImm0_65535:
4118 case Match_InvalidImm1_8:
4119 case Match_InvalidImm1_16:
4120 case Match_InvalidImm1_32:
4121 case Match_InvalidImm1_64:
4122 case Match_InvalidIndex1:
4123 case Match_InvalidIndexB:
4124 case Match_InvalidIndexH:
4125 case Match_InvalidIndexS:
4126 case Match_InvalidIndexD:
4127 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004128 case Match_InvalidComplexRotationEven:
4129 case Match_InvalidComplexRotationOdd:
Sander de Smalencd6be962017-12-20 11:02:42 +00004130 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004131 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004132 case Match_InvalidSVEPredicateBReg:
4133 case Match_InvalidSVEPredicateHReg:
4134 case Match_InvalidSVEPredicateSReg:
4135 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004136 case Match_InvalidSVEPredicate3bAnyReg:
4137 case Match_InvalidSVEPredicate3bBReg:
4138 case Match_InvalidSVEPredicate3bHReg:
4139 case Match_InvalidSVEPredicate3bSReg:
4140 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004141 case Match_MSR:
4142 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004143 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004144 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004145 // Any time we get here, there's nothing fancy to do. Just get the
4146 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004147 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004148 if (ErrorLoc == SMLoc())
4149 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004150 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004151 }
4152 }
4153
4154 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004155}
4156
4157/// ParseDirective parses the arm specific directives
4158bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004159 const MCObjectFileInfo::Environment Format =
4160 getContext().getObjectFileInfo()->getObjectFileType();
4161 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4162 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004163
Tim Northover3b0846e2014-05-24 12:50:23 +00004164 StringRef IDVal = DirectiveID.getIdentifier();
4165 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004166 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004167 parseDirectiveArch(Loc);
4168 else if (IDVal == ".cpu")
4169 parseDirectiveCPU(Loc);
4170 else if (IDVal == ".hword")
4171 parseDirectiveWord(2, Loc);
4172 else if (IDVal == ".word")
4173 parseDirectiveWord(4, Loc);
4174 else if (IDVal == ".xword")
4175 parseDirectiveWord(8, Loc);
4176 else if (IDVal == ".tlsdesccall")
4177 parseDirectiveTLSDescCall(Loc);
4178 else if (IDVal == ".ltorg" || IDVal == ".pool")
4179 parseDirectiveLtorg(Loc);
4180 else if (IDVal == ".unreq")
4181 parseDirectiveUnreq(Loc);
4182 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004183 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004184 parseDirectiveInst(Loc);
4185 else
4186 return true;
4187 } else if (IDVal == MCLOHDirectiveName())
4188 parseDirectiveLOH(IDVal, Loc);
4189 else
4190 return true;
4191 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004192}
4193
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004194static const struct {
4195 const char *Name;
4196 const FeatureBitset Features;
4197} ExtensionMap[] = {
4198 { "crc", {AArch64::FeatureCRC} },
4199 { "crypto", {AArch64::FeatureCrypto} },
4200 { "fp", {AArch64::FeatureFPARMv8} },
4201 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004202 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004203 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004204
4205 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004206 { "pan", {} },
4207 { "lor", {} },
4208 { "rdma", {} },
4209 { "profile", {} },
4210};
4211
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004212/// parseDirectiveArch
4213/// ::= .arch token
4214bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4215 SMLoc ArchLoc = getLoc();
4216
4217 StringRef Arch, ExtensionString;
4218 std::tie(Arch, ExtensionString) =
4219 getParser().parseStringToEndOfStatement().trim().split('+');
4220
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004221 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4222 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004223 return Error(ArchLoc, "unknown arch name");
4224
4225 if (parseToken(AsmToken::EndOfStatement))
4226 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004227
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004228 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004229 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004230 AArch64::getArchFeatures(ID, AArch64Features);
4231 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4232 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004233
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004234 MCSubtargetInfo &STI = copySTI();
4235 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4236 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4237
4238 SmallVector<StringRef, 4> RequestedExtensions;
4239 if (!ExtensionString.empty())
4240 ExtensionString.split(RequestedExtensions, '+');
4241
4242 FeatureBitset Features = STI.getFeatureBits();
4243 for (auto Name : RequestedExtensions) {
4244 bool EnableFeature = true;
4245
4246 if (Name.startswith_lower("no")) {
4247 EnableFeature = false;
4248 Name = Name.substr(2);
4249 }
4250
4251 for (const auto &Extension : ExtensionMap) {
4252 if (Extension.Name != Name)
4253 continue;
4254
4255 if (Extension.Features.none())
4256 report_fatal_error("unsupported architectural extension: " + Name);
4257
4258 FeatureBitset ToggleFeatures = EnableFeature
4259 ? (~Features & Extension.Features)
4260 : ( Features & Extension.Features);
4261 uint64_t Features =
4262 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4263 setAvailableFeatures(Features);
4264 break;
4265 }
4266 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004267 return false;
4268}
4269
Tim Northover8b96c7e2017-05-15 19:42:15 +00004270static SMLoc incrementLoc(SMLoc L, int Offset) {
4271 return SMLoc::getFromPointer(L.getPointer() + Offset);
4272}
4273
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004274/// parseDirectiveCPU
4275/// ::= .cpu id
4276bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004277 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004278
4279 StringRef CPU, ExtensionString;
4280 std::tie(CPU, ExtensionString) =
4281 getParser().parseStringToEndOfStatement().trim().split('+');
4282
Nirav Davee833c6c2016-11-08 18:31:04 +00004283 if (parseToken(AsmToken::EndOfStatement))
4284 return true;
4285
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004286 SmallVector<StringRef, 4> RequestedExtensions;
4287 if (!ExtensionString.empty())
4288 ExtensionString.split(RequestedExtensions, '+');
4289
4290 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4291 // once that is tablegen'ed
4292 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004293 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004294 return false;
4295 }
4296
4297 MCSubtargetInfo &STI = copySTI();
4298 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004299 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004300
4301 FeatureBitset Features = STI.getFeatureBits();
4302 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004303 // Advance source location past '+'.
4304 CurLoc = incrementLoc(CurLoc, 1);
4305
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004306 bool EnableFeature = true;
4307
4308 if (Name.startswith_lower("no")) {
4309 EnableFeature = false;
4310 Name = Name.substr(2);
4311 }
4312
Tim Northover8b96c7e2017-05-15 19:42:15 +00004313 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004314 for (const auto &Extension : ExtensionMap) {
4315 if (Extension.Name != Name)
4316 continue;
4317
4318 if (Extension.Features.none())
4319 report_fatal_error("unsupported architectural extension: " + Name);
4320
4321 FeatureBitset ToggleFeatures = EnableFeature
4322 ? (~Features & Extension.Features)
4323 : ( Features & Extension.Features);
4324 uint64_t Features =
4325 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4326 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004327 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004328
4329 break;
4330 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004331
4332 if (!FoundExtension)
4333 Error(CurLoc, "unsupported architectural extension");
4334
4335 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004336 }
4337 return false;
4338}
4339
Tim Northover3b0846e2014-05-24 12:50:23 +00004340/// parseDirectiveWord
4341/// ::= .word [ expression (, expression)* ]
4342bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004343 auto parseOp = [&]() -> bool {
4344 const MCExpr *Value;
4345 if (getParser().parseExpression(Value))
4346 return true;
4347 getParser().getStreamer().EmitValue(Value, Size, L);
4348 return false;
4349 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004350
Nirav Davee833c6c2016-11-08 18:31:04 +00004351 if (parseMany(parseOp))
4352 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004353 return false;
4354}
4355
Chad Rosierdcd2a302014-10-22 20:35:57 +00004356/// parseDirectiveInst
4357/// ::= .inst opcode [, ...]
4358bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004359 if (getLexer().is(AsmToken::EndOfStatement))
4360 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004361
Nirav Davee833c6c2016-11-08 18:31:04 +00004362 auto parseOp = [&]() -> bool {
4363 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004364 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004365 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4366 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004367 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004368 if (check(!Value, L, "expected constant expression"))
4369 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004370 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004371 return false;
4372 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004373
Nirav Davee833c6c2016-11-08 18:31:04 +00004374 if (parseMany(parseOp))
4375 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004376 return false;
4377}
4378
Tim Northover3b0846e2014-05-24 12:50:23 +00004379// parseDirectiveTLSDescCall:
4380// ::= .tlsdesccall symbol
4381bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4382 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004383 if (check(getParser().parseIdentifier(Name), L,
4384 "expected symbol after directive") ||
4385 parseToken(AsmToken::EndOfStatement))
4386 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004387
Jim Grosbach6f482002015-05-18 18:43:14 +00004388 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004389 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4390 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004391
4392 MCInst Inst;
4393 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004394 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004395
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004396 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004397 return false;
4398}
4399
4400/// ::= .loh <lohName | lohId> label1, ..., labelN
4401/// The number of arguments depends on the loh identifier.
4402bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004403 MCLOHType Kind;
4404 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4405 if (getParser().getTok().isNot(AsmToken::Integer))
4406 return TokError("expected an identifier or a number in directive");
4407 // We successfully get a numeric value for the identifier.
4408 // Check if it is valid.
4409 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004410 if (Id <= -1U && !isValidMCLOHType(Id))
4411 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004412 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004413 } else {
4414 StringRef Name = getTok().getIdentifier();
4415 // We successfully parse an identifier.
4416 // Check if it is a recognized one.
4417 int Id = MCLOHNameToId(Name);
4418
4419 if (Id == -1)
4420 return TokError("invalid identifier in directive");
4421 Kind = (MCLOHType)Id;
4422 }
4423 // Consume the identifier.
4424 Lex();
4425 // Get the number of arguments of this LOH.
4426 int NbArgs = MCLOHIdToNbArgs(Kind);
4427
4428 assert(NbArgs != -1 && "Invalid number of arguments");
4429
4430 SmallVector<MCSymbol *, 3> Args;
4431 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4432 StringRef Name;
4433 if (getParser().parseIdentifier(Name))
4434 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004435 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004436
4437 if (Idx + 1 == NbArgs)
4438 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004439 if (parseToken(AsmToken::Comma,
4440 "unexpected token in '" + Twine(IDVal) + "' directive"))
4441 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004442 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004443 if (parseToken(AsmToken::EndOfStatement,
4444 "unexpected token in '" + Twine(IDVal) + "' directive"))
4445 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004446
4447 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4448 return false;
4449}
4450
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004451/// parseDirectiveLtorg
4452/// ::= .ltorg | .pool
4453bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004454 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4455 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004456 getTargetStreamer().emitCurrentConstantPool();
4457 return false;
4458}
4459
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004460/// parseDirectiveReq
4461/// ::= name .req registername
4462bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004463 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004464 Parser.Lex(); // Eat the '.req' token.
4465 SMLoc SRegLoc = getLoc();
Sander de Smalen8e607342017-11-15 15:44:43 +00004466 int RegNum = tryParseRegister();
Florian Hahnc4422242017-11-07 13:07:50 +00004467 RegKind RegisterKind = RegKind::Scalar;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004468
Sander de Smalen8e607342017-11-15 15:44:43 +00004469 if (RegNum == -1) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004470 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004471 RegisterKind = RegKind::NeonVector;
Sander de Smalen73937b72018-04-11 07:36:10 +00004472 OperandMatchResultTy Res =
4473 tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
4474
4475 if (Res == MatchOperand_ParseFail)
4476 return true;
4477
4478 if (Res == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004479 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004480 }
4481
Sander de Smalen8e607342017-11-15 15:44:43 +00004482 if (RegNum == -1) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004483 StringRef Kind;
4484 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen8e607342017-11-15 15:44:43 +00004485 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004486 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004487
4488 if (Res == MatchOperand_ParseFail)
4489 return true;
4490
4491 if (Res == MatchOperand_Success && !Kind.empty())
4492 return Error(SRegLoc,
4493 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004494 }
4495
Sander de Smalencd6be962017-12-20 11:02:42 +00004496 if (RegNum == -1) {
4497 StringRef Kind;
4498 RegisterKind = RegKind::SVEPredicateVector;
4499 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004500 tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004501
4502 if (Res == MatchOperand_ParseFail)
4503 return true;
4504
4505 if (Res == MatchOperand_Success && !Kind.empty())
4506 return Error(SRegLoc,
4507 "sve predicate register without type specifier expected");
4508 }
4509
Sander de Smalen8e607342017-11-15 15:44:43 +00004510 if (RegNum == -1)
Nirav Dave2364748a2016-09-16 18:30:20 +00004511 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004512
4513 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004514 if (parseToken(AsmToken::EndOfStatement,
4515 "unexpected input in .req directive"))
4516 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004517
Sander de Smalen8e607342017-11-15 15:44:43 +00004518 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004519 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004520 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4521
Nirav Dave2364748a2016-09-16 18:30:20 +00004522 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004523}
4524
4525/// parseDirectiveUneq
4526/// ::= .unreq registername
4527bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004528 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004529 if (getTok().isNot(AsmToken::Identifier))
4530 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004531 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4532 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004533 if (parseToken(AsmToken::EndOfStatement))
4534 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004535 return false;
4536}
4537
Tim Northover3b0846e2014-05-24 12:50:23 +00004538bool
4539AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4540 AArch64MCExpr::VariantKind &ELFRefKind,
4541 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4542 int64_t &Addend) {
4543 ELFRefKind = AArch64MCExpr::VK_INVALID;
4544 DarwinRefKind = MCSymbolRefExpr::VK_None;
4545 Addend = 0;
4546
4547 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4548 ELFRefKind = AE->getKind();
4549 Expr = AE->getSubExpr();
4550 }
4551
4552 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4553 if (SE) {
4554 // It's a simple symbol reference with no addend.
4555 DarwinRefKind = SE->getKind();
4556 return true;
4557 }
4558
4559 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4560 if (!BE)
4561 return false;
4562
4563 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4564 if (!SE)
4565 return false;
4566 DarwinRefKind = SE->getKind();
4567
4568 if (BE->getOpcode() != MCBinaryExpr::Add &&
4569 BE->getOpcode() != MCBinaryExpr::Sub)
4570 return false;
4571
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004572 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004573 // on here than we can deal with.
4574 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4575 if (!AddendExpr)
4576 return false;
4577
4578 Addend = AddendExpr->getValue();
4579 if (BE->getOpcode() == MCBinaryExpr::Sub)
4580 Addend = -Addend;
4581
4582 // It's some symbol reference + a constant addend, but really
4583 // shouldn't use both Darwin and ELF syntax.
4584 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4585 DarwinRefKind == MCSymbolRefExpr::VK_None;
4586}
4587
4588/// Force static initialization.
4589extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004590 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4591 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4592 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004593}
4594
4595#define GET_REGISTER_MATCHER
4596#define GET_SUBTARGET_FEATURE_NAME
4597#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004598#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004599#include "AArch64GenAsmMatcher.inc"
4600
4601// Define this matcher function after the auto-generated include so we
4602// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004603unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004604 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004605 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004606 // If the kind is a token for a literal immediate, check if our asm
4607 // operand matches. This is for InstAliases which have a fixed-value
4608 // immediate in the syntax.
4609 int64_t ExpectedVal;
4610 switch (Kind) {
4611 default:
4612 return Match_InvalidOperand;
4613 case MCK__35_0:
4614 ExpectedVal = 0;
4615 break;
4616 case MCK__35_1:
4617 ExpectedVal = 1;
4618 break;
4619 case MCK__35_12:
4620 ExpectedVal = 12;
4621 break;
4622 case MCK__35_16:
4623 ExpectedVal = 16;
4624 break;
4625 case MCK__35_2:
4626 ExpectedVal = 2;
4627 break;
4628 case MCK__35_24:
4629 ExpectedVal = 24;
4630 break;
4631 case MCK__35_3:
4632 ExpectedVal = 3;
4633 break;
4634 case MCK__35_32:
4635 ExpectedVal = 32;
4636 break;
4637 case MCK__35_4:
4638 ExpectedVal = 4;
4639 break;
4640 case MCK__35_48:
4641 ExpectedVal = 48;
4642 break;
4643 case MCK__35_6:
4644 ExpectedVal = 6;
4645 break;
4646 case MCK__35_64:
4647 ExpectedVal = 64;
4648 break;
4649 case MCK__35_8:
4650 ExpectedVal = 8;
4651 break;
4652 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004653 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004654 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004655 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004656 if (!CE)
4657 return Match_InvalidOperand;
4658 if (CE->getValue() == ExpectedVal)
4659 return Match_Success;
4660 return Match_InvalidOperand;
4661}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004662
Alex Bradbury58eba092016-11-01 16:32:05 +00004663OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004664AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4665
4666 SMLoc S = getLoc();
4667
4668 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4669 Error(S, "expected register");
4670 return MatchOperand_ParseFail;
4671 }
4672
4673 int FirstReg = tryParseRegister();
4674 if (FirstReg == -1) {
4675 return MatchOperand_ParseFail;
4676 }
4677 const MCRegisterClass &WRegClass =
4678 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4679 const MCRegisterClass &XRegClass =
4680 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4681
4682 bool isXReg = XRegClass.contains(FirstReg),
4683 isWReg = WRegClass.contains(FirstReg);
4684 if (!isXReg && !isWReg) {
4685 Error(S, "expected first even register of a "
4686 "consecutive same-size even/odd register pair");
4687 return MatchOperand_ParseFail;
4688 }
4689
4690 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4691 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4692
4693 if (FirstEncoding & 0x1) {
4694 Error(S, "expected first even register of a "
4695 "consecutive same-size even/odd register pair");
4696 return MatchOperand_ParseFail;
4697 }
4698
4699 SMLoc M = getLoc();
4700 if (getParser().getTok().isNot(AsmToken::Comma)) {
4701 Error(M, "expected comma");
4702 return MatchOperand_ParseFail;
4703 }
4704 // Eat the comma
4705 getParser().Lex();
4706
4707 SMLoc E = getLoc();
4708 int SecondReg = tryParseRegister();
4709 if (SecondReg ==-1) {
4710 return MatchOperand_ParseFail;
4711 }
4712
Eugene Zelenko049b0172017-01-06 00:30:53 +00004713 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004714 (isXReg && !XRegClass.contains(SecondReg)) ||
4715 (isWReg && !WRegClass.contains(SecondReg))) {
4716 Error(E,"expected second odd register of a "
4717 "consecutive same-size even/odd register pair");
4718 return MatchOperand_ParseFail;
4719 }
Joel Jones504bf332016-10-24 13:37:13 +00004720
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004721 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004722 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004723 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4724 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4725 } else {
4726 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4727 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4728 }
4729
Florian Hahnc4422242017-11-07 13:07:50 +00004730 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4731 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004732
4733 return MatchOperand_Success;
4734}
Florian Hahn91f11e52017-11-07 16:45:48 +00004735
4736template <bool ParseSuffix>
4737OperandMatchResultTy
4738AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004739 const SMLoc S = getLoc();
4740 // Check for a SVE vector register specifier first.
Sander de Smalen8e607342017-11-15 15:44:43 +00004741 int RegNum = -1;
Florian Hahn91f11e52017-11-07 16:45:48 +00004742 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004743
Sander de Smalen8e607342017-11-15 15:44:43 +00004744 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004745 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004746
4747 if (Res != MatchOperand_Success)
4748 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004749
4750 if (ParseSuffix && Kind.empty())
4751 return MatchOperand_NoMatch;
4752
Sander de Smalen73937b72018-04-11 07:36:10 +00004753 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
4754 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00004755 return MatchOperand_NoMatch;
4756
Sander de Smalen73937b72018-04-11 07:36:10 +00004757 unsigned ElementWidth = KindRes->second;
4758 Operands.push_back(AArch64Operand::CreateVectorReg(
4759 RegNum, RegKind::SVEDataVector, ElementWidth, S, S,
4760 getContext()));
Florian Hahn91f11e52017-11-07 16:45:48 +00004761
4762 return MatchOperand_Success;
4763}
Sander de Smalen245e0e62018-01-22 10:46:00 +00004764
4765OperandMatchResultTy
4766AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
4767 MCAsmParser &Parser = getParser();
4768
4769 SMLoc SS = getLoc();
4770 const AsmToken &TokE = Parser.getTok();
4771 bool IsHash = TokE.is(AsmToken::Hash);
4772
4773 if (!IsHash && TokE.isNot(AsmToken::Identifier))
4774 return MatchOperand_NoMatch;
4775
4776 int64_t Pattern;
4777 if (IsHash) {
4778 Parser.Lex(); // Eat hash
4779
4780 // Parse the immediate operand.
4781 const MCExpr *ImmVal;
4782 SS = getLoc();
4783 if (Parser.parseExpression(ImmVal))
4784 return MatchOperand_ParseFail;
4785
4786 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4787 if (!MCE)
4788 return MatchOperand_ParseFail;
4789
4790 Pattern = MCE->getValue();
4791 } else {
4792 // Parse the pattern
4793 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
4794 if (!Pat)
4795 return MatchOperand_NoMatch;
4796
4797 Parser.Lex();
4798 Pattern = Pat->Encoding;
4799 assert(Pattern >= 0 && Pattern < 32);
4800 }
4801
4802 Operands.push_back(
4803 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
4804 SS, getLoc(), getContext()));
4805
4806 return MatchOperand_Success;
4807}