blob: 2401479b38aa7d649da7dc3b542e565400469c6f [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/AArch64AddressingModes.h"
11#include "MCTargetDesc/AArch64MCExpr.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000012#include "MCTargetDesc/AArch64MCTargetDesc.h"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000013#include "MCTargetDesc/AArch64TargetStreamer.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000014#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000015#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000016#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000017#include "llvm/ADT/ArrayRef.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000018#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "llvm/ADT/SmallVector.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000020#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000021#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000023#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000025#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000028#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000029#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000030#include "llvm/MC/MCParser/MCAsmLexer.h"
31#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000032#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000033#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000034#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000035#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSubtargetInfo.h"
38#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000039#include "llvm/MC/MCTargetOptions.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000043#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000044#include "llvm/Support/MathExtras.h"
45#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000046#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000047#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000049#include <cassert>
50#include <cctype>
51#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000052#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000053#include <string>
54#include <tuple>
55#include <utility>
56#include <vector>
57
Tim Northover3b0846e2014-05-24 12:50:23 +000058using namespace llvm;
59
60namespace {
61
Sander de Smalencd6be962017-12-20 11:02:42 +000062enum class RegKind {
63 Scalar,
64 NeonVector,
65 SVEDataVector,
66 SVEPredicateVector
67};
Florian Hahnc4422242017-11-07 13:07:50 +000068
Tim Northover3b0846e2014-05-24 12:50:23 +000069class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000070private:
71 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000072
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000073 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000074 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000075
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000076 AArch64TargetStreamer &getTargetStreamer() {
77 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
78 return static_cast<AArch64TargetStreamer &>(TS);
79 }
80
Rafael Espindola961d4692014-11-11 05:18:41 +000081 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000082
83 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +000084 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +000085 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
86 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +000087 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +000088 int tryParseRegister();
Tim Northover3b0846e2014-05-24 12:50:23 +000089 bool parseRegister(OperandVector &Operands);
90 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
Sander de Smalenc88f9a12018-04-11 14:10:37 +000091 bool parseNeonVectorList(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000092 bool parseOperand(OperandVector &Operands, bool isCondCode,
93 bool invertCondCode);
94
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +000095 bool showMatchError(SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000096
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000097 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000098 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +000099 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +0000100 bool parseDirectiveInst(SMLoc L);
101
Tim Northover3b0846e2014-05-24 12:50:23 +0000102 bool parseDirectiveTLSDescCall(SMLoc L);
103
104 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000105 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000106
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000107 bool parseDirectiveReq(StringRef Name, SMLoc L);
108 bool parseDirectiveUnreq(SMLoc L);
109
Tim Northover3b0846e2014-05-24 12:50:23 +0000110 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
111 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
112 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000113 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000114 bool MatchingInlineAsm) override;
115/// @name Auto-generated Match Functions
116/// {
117
118#define GET_ASSEMBLER_HEADER
119#include "AArch64GenAsmMatcher.inc"
120
121 /// }
122
Sander de Smalen73937b72018-04-11 07:36:10 +0000123 OperandMatchResultTy tryParseVectorRegister(int &Reg, StringRef &Kind,
124 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000125 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
126 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
127 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
128 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
129 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
130 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000131 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000132 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
133 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
134 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
135 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
136 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000137 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000138 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000139 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Florian Hahn91f11e52017-11-07 16:45:48 +0000140 template <bool ParseSuffix>
141 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000142 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000143 template <RegKind VectorKind>
144 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
145 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000146 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000147
148public:
149 enum AArch64MatchResultTy {
150 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
151#define GET_OPERAND_DIAGNOSTIC_TYPES
152#include "AArch64GenAsmMatcher.inc"
153 };
Joel Jones504bf332016-10-24 13:37:13 +0000154 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000155
Akira Hatanakab11ef082015-11-14 06:35:56 +0000156 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000157 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000158 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000159 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000160 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000161 MCStreamer &S = getParser().getStreamer();
162 if (S.getTargetStreamer() == nullptr)
163 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000164
165 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000166 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000167 }
168
169 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
170 SMLoc NameLoc, OperandVector &Operands) override;
171 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
172 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000173 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000174 unsigned Kind) override;
175
176 static bool classifySymbolRef(const MCExpr *Expr,
177 AArch64MCExpr::VariantKind &ELFRefKind,
178 MCSymbolRefExpr::VariantKind &DarwinRefKind,
179 int64_t &Addend);
180};
Tim Northover3b0846e2014-05-24 12:50:23 +0000181
182/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
183/// instruction.
184class AArch64Operand : public MCParsedAsmOperand {
185private:
186 enum KindTy {
187 k_Immediate,
188 k_ShiftedImm,
189 k_CondCode,
190 k_Register,
191 k_VectorList,
192 k_VectorIndex,
193 k_Token,
194 k_SysReg,
195 k_SysCR,
196 k_Prefetch,
197 k_ShiftExtend,
198 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000199 k_Barrier,
200 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000201 } Kind;
202
203 SMLoc StartLoc, EndLoc;
204
205 struct TokOp {
206 const char *Data;
207 unsigned Length;
208 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
209 };
210
211 struct RegOp {
212 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000213 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000214
215 int ElementWidth;
Tim Northover3b0846e2014-05-24 12:50:23 +0000216 };
217
218 struct VectorListOp {
219 unsigned RegNum;
220 unsigned Count;
221 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000222 unsigned ElementWidth;
223 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000224 };
225
226 struct VectorIndexOp {
227 unsigned Val;
228 };
229
230 struct ImmOp {
231 const MCExpr *Val;
232 };
233
234 struct ShiftedImmOp {
235 const MCExpr *Val;
236 unsigned ShiftAmount;
237 };
238
239 struct CondCodeOp {
240 AArch64CC::CondCode Code;
241 };
242
243 struct FPImmOp {
244 unsigned Val; // Encoded 8-bit representation.
245 };
246
247 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000248 const char *Data;
249 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000250 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000251 };
252
253 struct SysRegOp {
254 const char *Data;
255 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000256 uint32_t MRSReg;
257 uint32_t MSRReg;
258 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000259 };
260
261 struct SysCRImmOp {
262 unsigned Val;
263 };
264
265 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000266 const char *Data;
267 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000268 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000269 };
270
Oliver Stannarda34e4702015-12-01 10:48:51 +0000271 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000272 const char *Data;
273 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000274 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000275 };
276
Tim Northover3b0846e2014-05-24 12:50:23 +0000277 struct ShiftExtendOp {
278 AArch64_AM::ShiftExtendType Type;
279 unsigned Amount;
280 bool HasExplicitAmount;
281 };
282
283 struct ExtendOp {
284 unsigned Val;
285 };
286
287 union {
288 struct TokOp Tok;
289 struct RegOp Reg;
290 struct VectorListOp VectorList;
291 struct VectorIndexOp VectorIndex;
292 struct ImmOp Imm;
293 struct ShiftedImmOp ShiftedImm;
294 struct CondCodeOp CondCode;
295 struct FPImmOp FPImm;
296 struct BarrierOp Barrier;
297 struct SysRegOp SysReg;
298 struct SysCRImmOp SysCRImm;
299 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000300 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000301 struct ShiftExtendOp ShiftExtend;
302 };
303
304 // Keep the MCContext around as the MCExprs may need manipulated during
305 // the add<>Operands() calls.
306 MCContext &Ctx;
307
David Blaikie960ea3f2014-06-08 16:18:35 +0000308public:
David Blaikie9f380a32015-03-16 18:06:57 +0000309 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000310
Tim Northover3b0846e2014-05-24 12:50:23 +0000311 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
312 Kind = o.Kind;
313 StartLoc = o.StartLoc;
314 EndLoc = o.EndLoc;
315 switch (Kind) {
316 case k_Token:
317 Tok = o.Tok;
318 break;
319 case k_Immediate:
320 Imm = o.Imm;
321 break;
322 case k_ShiftedImm:
323 ShiftedImm = o.ShiftedImm;
324 break;
325 case k_CondCode:
326 CondCode = o.CondCode;
327 break;
328 case k_FPImm:
329 FPImm = o.FPImm;
330 break;
331 case k_Barrier:
332 Barrier = o.Barrier;
333 break;
334 case k_Register:
335 Reg = o.Reg;
336 break;
337 case k_VectorList:
338 VectorList = o.VectorList;
339 break;
340 case k_VectorIndex:
341 VectorIndex = o.VectorIndex;
342 break;
343 case k_SysReg:
344 SysReg = o.SysReg;
345 break;
346 case k_SysCR:
347 SysCRImm = o.SysCRImm;
348 break;
349 case k_Prefetch:
350 Prefetch = o.Prefetch;
351 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000352 case k_PSBHint:
353 PSBHint = o.PSBHint;
354 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000355 case k_ShiftExtend:
356 ShiftExtend = o.ShiftExtend;
357 break;
358 }
359 }
360
361 /// getStartLoc - Get the location of the first token of this operand.
362 SMLoc getStartLoc() const override { return StartLoc; }
363 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000364 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000365
366 StringRef getToken() const {
367 assert(Kind == k_Token && "Invalid access!");
368 return StringRef(Tok.Data, Tok.Length);
369 }
370
371 bool isTokenSuffix() const {
372 assert(Kind == k_Token && "Invalid access!");
373 return Tok.IsSuffix;
374 }
375
376 const MCExpr *getImm() const {
377 assert(Kind == k_Immediate && "Invalid access!");
378 return Imm.Val;
379 }
380
381 const MCExpr *getShiftedImmVal() const {
382 assert(Kind == k_ShiftedImm && "Invalid access!");
383 return ShiftedImm.Val;
384 }
385
386 unsigned getShiftedImmShift() const {
387 assert(Kind == k_ShiftedImm && "Invalid access!");
388 return ShiftedImm.ShiftAmount;
389 }
390
391 AArch64CC::CondCode getCondCode() const {
392 assert(Kind == k_CondCode && "Invalid access!");
393 return CondCode.Code;
394 }
395
396 unsigned getFPImm() const {
397 assert(Kind == k_FPImm && "Invalid access!");
398 return FPImm.Val;
399 }
400
401 unsigned getBarrier() const {
402 assert(Kind == k_Barrier && "Invalid access!");
403 return Barrier.Val;
404 }
405
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000406 StringRef getBarrierName() const {
407 assert(Kind == k_Barrier && "Invalid access!");
408 return StringRef(Barrier.Data, Barrier.Length);
409 }
410
Tim Northover3b0846e2014-05-24 12:50:23 +0000411 unsigned getReg() const override {
412 assert(Kind == k_Register && "Invalid access!");
413 return Reg.RegNum;
414 }
415
416 unsigned getVectorListStart() const {
417 assert(Kind == k_VectorList && "Invalid access!");
418 return VectorList.RegNum;
419 }
420
421 unsigned getVectorListCount() const {
422 assert(Kind == k_VectorList && "Invalid access!");
423 return VectorList.Count;
424 }
425
426 unsigned getVectorIndex() const {
427 assert(Kind == k_VectorIndex && "Invalid access!");
428 return VectorIndex.Val;
429 }
430
431 StringRef getSysReg() const {
432 assert(Kind == k_SysReg && "Invalid access!");
433 return StringRef(SysReg.Data, SysReg.Length);
434 }
435
Tim Northover3b0846e2014-05-24 12:50:23 +0000436 unsigned getSysCR() const {
437 assert(Kind == k_SysCR && "Invalid access!");
438 return SysCRImm.Val;
439 }
440
441 unsigned getPrefetch() const {
442 assert(Kind == k_Prefetch && "Invalid access!");
443 return Prefetch.Val;
444 }
445
Oliver Stannarda34e4702015-12-01 10:48:51 +0000446 unsigned getPSBHint() const {
447 assert(Kind == k_PSBHint && "Invalid access!");
448 return PSBHint.Val;
449 }
450
451 StringRef getPSBHintName() const {
452 assert(Kind == k_PSBHint && "Invalid access!");
453 return StringRef(PSBHint.Data, PSBHint.Length);
454 }
455
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000456 StringRef getPrefetchName() const {
457 assert(Kind == k_Prefetch && "Invalid access!");
458 return StringRef(Prefetch.Data, Prefetch.Length);
459 }
460
Tim Northover3b0846e2014-05-24 12:50:23 +0000461 AArch64_AM::ShiftExtendType getShiftExtendType() const {
462 assert(Kind == k_ShiftExtend && "Invalid access!");
463 return ShiftExtend.Type;
464 }
465
466 unsigned getShiftExtendAmount() const {
467 assert(Kind == k_ShiftExtend && "Invalid access!");
468 return ShiftExtend.Amount;
469 }
470
471 bool hasShiftExtendAmount() const {
472 assert(Kind == k_ShiftExtend && "Invalid access!");
473 return ShiftExtend.HasExplicitAmount;
474 }
475
476 bool isImm() const override { return Kind == k_Immediate; }
477 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000478
479 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
480
481 template <int Bits, int Scale> bool isSImmScaled() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000482 if (!isImm())
483 return false;
484 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
485 if (!MCE)
486 return false;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000487
488 int64_t Shift = Bits - 1;
489 int64_t MinVal = (int64_t(1) << Shift) * -Scale;
490 int64_t MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
491
Tim Northover3b0846e2014-05-24 12:50:23 +0000492 int64_t Val = MCE->getValue();
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000493 return Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0;
Tim Northover3b0846e2014-05-24 12:50:23 +0000494 }
495
Sander de Smalen245e0e62018-01-22 10:46:00 +0000496 bool isSVEPattern() const {
497 if (!isImm())
498 return false;
499 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
500 if (!MCE)
501 return false;
502 int64_t Val = MCE->getValue();
503 return Val >= 0 && Val < 32;
504 }
505
Tim Northover3b0846e2014-05-24 12:50:23 +0000506 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
507 AArch64MCExpr::VariantKind ELFRefKind;
508 MCSymbolRefExpr::VariantKind DarwinRefKind;
509 int64_t Addend;
510 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
511 Addend)) {
512 // If we don't understand the expression, assume the best and
513 // let the fixup and relocation code deal with it.
514 return true;
515 }
516
517 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
518 ELFRefKind == AArch64MCExpr::VK_LO12 ||
519 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
520 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
521 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
522 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
523 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
524 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000525 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
526 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
527 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000528 // Note that we don't range-check the addend. It's adjusted modulo page
529 // size when converted, so there is no "out of range" condition when using
530 // @pageoff.
531 return Addend >= 0 && (Addend % Scale) == 0;
532 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
533 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
534 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
535 return Addend == 0;
536 }
537
538 return false;
539 }
540
541 template <int Scale> bool isUImm12Offset() const {
542 if (!isImm())
543 return false;
544
545 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
546 if (!MCE)
547 return isSymbolicUImm12Offset(getImm(), Scale);
548
549 int64_t Val = MCE->getValue();
550 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
551 }
552
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000553 template <int N, int M>
554 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000555 if (!isImm())
556 return false;
557 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
558 if (!MCE)
559 return false;
560 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000561 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000562 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000563
Sander de Smalena1c259c2018-01-29 13:05:38 +0000564 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
565 // a logical immediate can always be represented when inverted.
566 template <typename T>
567 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000568 if (!isImm())
569 return false;
570 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
571 if (!MCE)
572 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000573
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000574 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000575 int64_t SVal = typename std::make_signed<T>::type(Val);
576 int64_t UVal = typename std::make_unsigned<T>::type(Val);
577 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000578 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000579
Sander de Smalena1c259c2018-01-29 13:05:38 +0000580 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000581 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000582
Tim Northover3b0846e2014-05-24 12:50:23 +0000583 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000584
Tim Northover3b0846e2014-05-24 12:50:23 +0000585 bool isAddSubImm() const {
586 if (!isShiftedImm() && !isImm())
587 return false;
588
589 const MCExpr *Expr;
590
591 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
592 if (isShiftedImm()) {
593 unsigned Shift = ShiftedImm.ShiftAmount;
594 Expr = ShiftedImm.Val;
595 if (Shift != 0 && Shift != 12)
596 return false;
597 } else {
598 Expr = getImm();
599 }
600
601 AArch64MCExpr::VariantKind ELFRefKind;
602 MCSymbolRefExpr::VariantKind DarwinRefKind;
603 int64_t Addend;
604 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
605 DarwinRefKind, Addend)) {
606 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
607 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
608 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
609 || ELFRefKind == AArch64MCExpr::VK_LO12
610 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
611 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
612 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
613 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
614 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
615 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000616 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
617 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
618 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000619 }
620
Diana Picusc93518d2016-10-11 09:17:47 +0000621 // If it's a constant, it should be a real immediate in range:
622 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
623 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
624
625 // If it's an expression, we hope for the best and let the fixup/relocation
626 // code deal with it.
627 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000628 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000629
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000630 bool isAddSubImmNeg() const {
631 if (!isShiftedImm() && !isImm())
632 return false;
633
634 const MCExpr *Expr;
635
636 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
637 if (isShiftedImm()) {
638 unsigned Shift = ShiftedImm.ShiftAmount;
639 Expr = ShiftedImm.Val;
640 if (Shift != 0 && Shift != 12)
641 return false;
642 } else
643 Expr = getImm();
644
645 // Otherwise it should be a real negative immediate in range:
646 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
647 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
648 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000649
Tim Northover3b0846e2014-05-24 12:50:23 +0000650 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000651
Tim Northover3b0846e2014-05-24 12:50:23 +0000652 bool isSIMDImmType10() const {
653 if (!isImm())
654 return false;
655 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
656 if (!MCE)
657 return false;
658 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
659 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000660
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000661 template<int N>
662 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000663 if (!isImm())
664 return false;
665 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
666 if (!MCE)
667 return true;
668 int64_t Val = MCE->getValue();
669 if (Val & 0x3)
670 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000671 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
672 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000673 }
674
675 bool
676 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
677 if (!isImm())
678 return false;
679
680 AArch64MCExpr::VariantKind ELFRefKind;
681 MCSymbolRefExpr::VariantKind DarwinRefKind;
682 int64_t Addend;
683 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
684 DarwinRefKind, Addend)) {
685 return false;
686 }
687 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
688 return false;
689
690 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
691 if (ELFRefKind == AllowedModifiers[i])
692 return Addend == 0;
693 }
694
695 return false;
696 }
697
698 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000699 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000700 }
701
702 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000703 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
704 AArch64MCExpr::VK_TPREL_G2,
705 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000706 }
707
708 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000709 return isMovWSymbol({
710 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000711 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
712 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000713 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000714 }
715
716 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000717 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
718 AArch64MCExpr::VK_TPREL_G0,
719 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000720 }
721
722 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000723 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000724 }
725
726 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000727 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000728 }
729
730 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000731 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
732 AArch64MCExpr::VK_TPREL_G1_NC,
733 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000734 }
735
736 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000737 return isMovWSymbol(
738 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
739 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000740 }
741
742 template<int RegWidth, int Shift>
743 bool isMOVZMovAlias() const {
744 if (!isImm()) return false;
745
746 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
747 if (!CE) return false;
748 uint64_t Value = CE->getValue();
749
Tim Northoverdaa1c012016-06-16 01:42:25 +0000750 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000751 }
752
753 template<int RegWidth, int Shift>
754 bool isMOVNMovAlias() const {
755 if (!isImm()) return false;
756
757 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
758 if (!CE) return false;
759 uint64_t Value = CE->getValue();
760
Tim Northoverdaa1c012016-06-16 01:42:25 +0000761 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000762 }
763
764 bool isFPImm() const { return Kind == k_FPImm; }
765 bool isBarrier() const { return Kind == k_Barrier; }
766 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000767
Tim Northover3b0846e2014-05-24 12:50:23 +0000768 bool isMRSSystemRegister() const {
769 if (!isSysReg()) return false;
770
Tim Northover7cd58932015-01-22 17:23:04 +0000771 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000772 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000773
Tim Northover3b0846e2014-05-24 12:50:23 +0000774 bool isMSRSystemRegister() const {
775 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000776 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000777 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000778
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000779 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000780 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000781 return (SysReg.PStateField == AArch64PState::PAN ||
782 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000783 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000784
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000785 bool isSystemPStateFieldWithImm0_15() const {
786 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000787 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000788 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000789
Florian Hahnc4422242017-11-07 13:07:50 +0000790 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000791 return Kind == k_Register;
792 }
793
794 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000795 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
796 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000797
Florian Hahnc4422242017-11-07 13:07:50 +0000798 bool isNeonVectorReg() const {
799 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
800 }
801
802 bool isNeonVectorRegLo() const {
803 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000804 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
805 Reg.RegNum);
806 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000807
Sander de Smalencd6be962017-12-20 11:02:42 +0000808 template <unsigned Class> bool isSVEVectorReg() const {
809 RegKind RK;
810 switch (Class) {
811 case AArch64::ZPRRegClassID:
812 RK = RegKind::SVEDataVector;
813 break;
814 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000815 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000816 RK = RegKind::SVEPredicateVector;
817 break;
818 default:
819 llvm_unreachable("Unsupport register class");
820 }
821
822 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000823 AArch64MCRegisterClasses[Class].contains(getReg());
824 }
825
Sander de Smalencd6be962017-12-20 11:02:42 +0000826 template <int ElementWidth, unsigned Class>
827 bool isSVEVectorRegOfWidth() const {
828 return isSVEVectorReg<Class>() &&
Sander de Smalen73937b72018-04-11 07:36:10 +0000829 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth);
Florian Hahn91f11e52017-11-07 16:45:48 +0000830 }
831
Tim Northover3b0846e2014-05-24 12:50:23 +0000832 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000833 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000834 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
835 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000836
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000837 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000838 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000839 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
840 Reg.RegNum);
841 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000842
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000843 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000844 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000845 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
846 Reg.RegNum);
847 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000848
849 bool isGPR64sp0() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000850 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000851 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
852 }
853
Sam Parker5f934642017-08-31 09:27:04 +0000854 template<int64_t Angle, int64_t Remainder>
855 bool isComplexRotation() const {
856 if (!isImm()) return false;
857
858 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
859 if (!CE) return false;
860 uint64_t Value = CE->getValue();
861
862 return (Value % Angle == Remainder && Value <= 270);
863 }
864
Tim Northover3b0846e2014-05-24 12:50:23 +0000865 /// Is this a vector list with the type implicit (presumably attached to the
866 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +0000867 template <RegKind VectorKind, unsigned NumRegs>
868 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000869 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +0000870 VectorList.NumElements == 0 &&
871 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000872 }
873
Sander de Smalen650234b2018-04-12 11:40:52 +0000874 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
875 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +0000876 bool isTypedVectorList() const {
877 if (Kind != k_VectorList)
878 return false;
879 if (VectorList.Count != NumRegs)
880 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +0000881 if (VectorList.RegisterKind != VectorKind)
882 return false;
883 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +0000884 return false;
885 return VectorList.NumElements == NumElements;
886 }
887
888 bool isVectorIndex1() const {
889 return Kind == k_VectorIndex && VectorIndex.Val == 1;
890 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000891
Tim Northover3b0846e2014-05-24 12:50:23 +0000892 bool isVectorIndexB() const {
893 return Kind == k_VectorIndex && VectorIndex.Val < 16;
894 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000895
Tim Northover3b0846e2014-05-24 12:50:23 +0000896 bool isVectorIndexH() const {
897 return Kind == k_VectorIndex && VectorIndex.Val < 8;
898 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000899
Tim Northover3b0846e2014-05-24 12:50:23 +0000900 bool isVectorIndexS() const {
901 return Kind == k_VectorIndex && VectorIndex.Val < 4;
902 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000903
Tim Northover3b0846e2014-05-24 12:50:23 +0000904 bool isVectorIndexD() const {
905 return Kind == k_VectorIndex && VectorIndex.Val < 2;
906 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000907
Tim Northover3b0846e2014-05-24 12:50:23 +0000908 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000909
Tim Northover3b0846e2014-05-24 12:50:23 +0000910 bool isTokenEqual(StringRef Str) const {
911 return Kind == k_Token && getToken() == Str;
912 }
913 bool isSysCR() const { return Kind == k_SysCR; }
914 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000915 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000916 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
917 bool isShifter() const {
918 if (!isShiftExtend())
919 return false;
920
921 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
922 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
923 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
924 ST == AArch64_AM::MSL);
925 }
926 bool isExtend() const {
927 if (!isShiftExtend())
928 return false;
929
930 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
931 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
932 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
933 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
934 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
935 ET == AArch64_AM::LSL) &&
936 getShiftExtendAmount() <= 4;
937 }
938
939 bool isExtend64() const {
940 if (!isExtend())
941 return false;
942 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
943 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
944 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
945 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000946
Tim Northover3b0846e2014-05-24 12:50:23 +0000947 bool isExtendLSL64() const {
948 if (!isExtend())
949 return false;
950 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
951 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
952 ET == AArch64_AM::LSL) &&
953 getShiftExtendAmount() <= 4;
954 }
955
956 template<int Width> bool isMemXExtend() const {
957 if (!isExtend())
958 return false;
959 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
960 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
961 (getShiftExtendAmount() == Log2_32(Width / 8) ||
962 getShiftExtendAmount() == 0);
963 }
964
965 template<int Width> bool isMemWExtend() const {
966 if (!isExtend())
967 return false;
968 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
969 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
970 (getShiftExtendAmount() == Log2_32(Width / 8) ||
971 getShiftExtendAmount() == 0);
972 }
973
974 template <unsigned width>
975 bool isArithmeticShifter() const {
976 if (!isShifter())
977 return false;
978
979 // An arithmetic shifter is LSL, LSR, or ASR.
980 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
981 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
982 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
983 }
984
985 template <unsigned width>
986 bool isLogicalShifter() const {
987 if (!isShifter())
988 return false;
989
990 // A logical shifter is LSL, LSR, ASR or ROR.
991 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
992 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
993 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
994 getShiftExtendAmount() < width;
995 }
996
997 bool isMovImm32Shifter() const {
998 if (!isShifter())
999 return false;
1000
1001 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1002 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1003 if (ST != AArch64_AM::LSL)
1004 return false;
1005 uint64_t Val = getShiftExtendAmount();
1006 return (Val == 0 || Val == 16);
1007 }
1008
1009 bool isMovImm64Shifter() const {
1010 if (!isShifter())
1011 return false;
1012
1013 // A MOVi shifter is LSL of 0 or 16.
1014 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1015 if (ST != AArch64_AM::LSL)
1016 return false;
1017 uint64_t Val = getShiftExtendAmount();
1018 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1019 }
1020
1021 bool isLogicalVecShifter() const {
1022 if (!isShifter())
1023 return false;
1024
1025 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1026 unsigned Shift = getShiftExtendAmount();
1027 return getShiftExtendType() == AArch64_AM::LSL &&
1028 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1029 }
1030
1031 bool isLogicalVecHalfWordShifter() const {
1032 if (!isLogicalVecShifter())
1033 return false;
1034
1035 // A logical vector shifter is a left shift by 0 or 8.
1036 unsigned Shift = getShiftExtendAmount();
1037 return getShiftExtendType() == AArch64_AM::LSL &&
1038 (Shift == 0 || Shift == 8);
1039 }
1040
1041 bool isMoveVecShifter() const {
1042 if (!isShiftExtend())
1043 return false;
1044
1045 // A logical vector shifter is a left shift by 8 or 16.
1046 unsigned Shift = getShiftExtendAmount();
1047 return getShiftExtendType() == AArch64_AM::MSL &&
1048 (Shift == 8 || Shift == 16);
1049 }
1050
1051 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1052 // to LDUR/STUR when the offset is not legal for the former but is for
1053 // the latter. As such, in addition to checking for being a legal unscaled
1054 // address, also check that it is not a legal scaled address. This avoids
1055 // ambiguity in the matcher.
1056 template<int Width>
1057 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001058 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001059 }
1060
1061 bool isAdrpLabel() const {
1062 // Validation was handled during parsing, so we just sanity check that
1063 // something didn't go haywire.
1064 if (!isImm())
1065 return false;
1066
1067 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1068 int64_t Val = CE->getValue();
1069 int64_t Min = - (4096 * (1LL << (21 - 1)));
1070 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1071 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1072 }
1073
1074 return true;
1075 }
1076
1077 bool isAdrLabel() const {
1078 // Validation was handled during parsing, so we just sanity check that
1079 // something didn't go haywire.
1080 if (!isImm())
1081 return false;
1082
1083 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1084 int64_t Val = CE->getValue();
1085 int64_t Min = - (1LL << (21 - 1));
1086 int64_t Max = ((1LL << (21 - 1)) - 1);
1087 return Val >= Min && Val <= Max;
1088 }
1089
1090 return true;
1091 }
1092
1093 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1094 // Add as immediates when possible. Null MCExpr = 0.
1095 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001096 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001097 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001098 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001099 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001100 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001101 }
1102
1103 void addRegOperands(MCInst &Inst, unsigned N) const {
1104 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001105 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001106 }
1107
1108 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1109 assert(N == 1 && "Invalid number of operands!");
1110 assert(
1111 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1112
1113 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1114 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1115 RI->getEncodingValue(getReg()));
1116
Jim Grosbache9119e42015-05-13 18:37:00 +00001117 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001118 }
1119
1120 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1121 assert(N == 1 && "Invalid number of operands!");
1122 assert(
1123 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001124 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001125 }
1126
1127 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1128 assert(N == 1 && "Invalid number of operands!");
1129 assert(
1130 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001131 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001132 }
1133
1134 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1135 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001136 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001137 }
1138
1139 template <unsigned NumRegs>
1140 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1141 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001142 static const unsigned FirstRegs[] = { AArch64::D0,
1143 AArch64::D0_D1,
1144 AArch64::D0_D1_D2,
1145 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001146 unsigned FirstReg = FirstRegs[NumRegs - 1];
1147
1148 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001149 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001150 }
1151
1152 template <unsigned NumRegs>
1153 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1154 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001155 static const unsigned FirstRegs[] = { AArch64::Q0,
1156 AArch64::Q0_Q1,
1157 AArch64::Q0_Q1_Q2,
1158 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001159 unsigned FirstReg = FirstRegs[NumRegs - 1];
1160
1161 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001162 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001163 }
1164
1165 void addVectorIndex1Operands(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 addVectorIndexBOperands(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 addVectorIndexHOperands(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 addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1181 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001182 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001183 }
1184
1185 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1186 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001187 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001188 }
1189
1190 void addImmOperands(MCInst &Inst, unsigned N) const {
1191 assert(N == 1 && "Invalid number of operands!");
1192 // If this is a pageoff symrefexpr with an addend, adjust the addend
1193 // to be only the page-offset portion. Otherwise, just add the expr
1194 // as-is.
1195 addExpr(Inst, getImm());
1196 }
1197
1198 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1199 assert(N == 2 && "Invalid number of operands!");
1200 if (isShiftedImm()) {
1201 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001202 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001203 } else {
1204 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001205 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001206 }
1207 }
1208
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001209 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1210 assert(N == 2 && "Invalid number of operands!");
1211
1212 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1213 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1214 int64_t Val = -CE->getValue();
1215 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1216
1217 Inst.addOperand(MCOperand::createImm(Val));
1218 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1219 }
1220
Tim Northover3b0846e2014-05-24 12:50:23 +00001221 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1222 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001223 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001224 }
1225
1226 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1227 assert(N == 1 && "Invalid number of operands!");
1228 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1229 if (!MCE)
1230 addExpr(Inst, getImm());
1231 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001232 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001233 }
1234
1235 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1236 addImmOperands(Inst, N);
1237 }
1238
1239 template<int Scale>
1240 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1241 assert(N == 1 && "Invalid number of operands!");
1242 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1243
1244 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001245 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001246 return;
1247 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001248 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001249 }
1250
1251 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1252 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001253 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001254 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001255 }
1256
Sam Parker6d42de72017-08-11 13:14:00 +00001257 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1258 assert(N == 1 && "Invalid number of operands!");
1259 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1260 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1261 }
1262
Tim Northover3b0846e2014-05-24 12:50:23 +00001263 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1264 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001265 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001266 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001267 }
1268
1269 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1270 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001271 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001272 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001273 }
1274
1275 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1276 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001277 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001278 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001279 }
1280
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001281 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1282 assert(N == 1 && "Invalid number of operands!");
1283 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1284 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1285 }
1286
Tim Northover3b0846e2014-05-24 12:50:23 +00001287 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1288 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001289 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001290 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001291 }
1292
1293 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1294 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001295 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001296 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001297 }
1298
1299 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1300 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001301 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001302 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001303 }
1304
1305 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1306 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001307 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001308 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001309 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001310 }
1311
1312 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1313 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001314 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001315 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001316 }
1317
1318 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1319 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001320 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001321 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001322 }
1323
1324 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1325 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001326 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001327 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001328 }
1329
1330 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1331 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001332 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001333 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001334 }
1335
1336 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1337 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001338 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001339 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001340 }
1341
1342 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1343 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001344 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001345 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001346 }
1347
1348 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1349 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001350 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001351 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001352 }
1353
1354 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1355 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001356 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001357 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001358 }
1359
1360 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1361 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001362 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001363 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001364 }
1365
1366 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1367 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001368 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001369 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001370 }
1371
Sander de Smalena1c259c2018-01-29 13:05:38 +00001372 template <typename T>
1373 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001374 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001375 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001376 typename std::make_unsigned<T>::type Val = MCE->getValue();
1377 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001378 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001379 }
1380
Sander de Smalena1c259c2018-01-29 13:05:38 +00001381 template <typename T>
1382 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001383 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001384 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001385 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1386 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001387 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001388 }
1389
Tim Northover3b0846e2014-05-24 12:50:23 +00001390 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1391 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001392 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001393 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001394 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001395 }
1396
1397 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1398 // Branch operands don't encode the low bits, so shift them off
1399 // here. If it's a label, however, just put it on directly as there's
1400 // not enough information now to do anything.
1401 assert(N == 1 && "Invalid number of operands!");
1402 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1403 if (!MCE) {
1404 addExpr(Inst, getImm());
1405 return;
1406 }
1407 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001408 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001409 }
1410
1411 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1412 // Branch operands don't encode the low bits, so shift them off
1413 // here. If it's a label, however, just put it on directly as there's
1414 // not enough information now to do anything.
1415 assert(N == 1 && "Invalid number of operands!");
1416 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1417 if (!MCE) {
1418 addExpr(Inst, getImm());
1419 return;
1420 }
1421 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001422 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001423 }
1424
1425 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1426 // Branch operands don't encode the low bits, so shift them off
1427 // here. If it's a label, however, just put it on directly as there's
1428 // not enough information now to do anything.
1429 assert(N == 1 && "Invalid number of operands!");
1430 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1431 if (!MCE) {
1432 addExpr(Inst, getImm());
1433 return;
1434 }
1435 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001436 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001437 }
1438
1439 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1440 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001441 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001442 }
1443
1444 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1445 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001446 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001447 }
1448
1449 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1450 assert(N == 1 && "Invalid number of operands!");
1451
Jim Grosbache9119e42015-05-13 18:37:00 +00001452 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001453 }
1454
1455 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1456 assert(N == 1 && "Invalid number of operands!");
1457
Jim Grosbache9119e42015-05-13 18:37:00 +00001458 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001459 }
1460
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001461 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1462 assert(N == 1 && "Invalid number of operands!");
1463
1464 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1465 }
1466
1467 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001468 assert(N == 1 && "Invalid number of operands!");
1469
Jim Grosbache9119e42015-05-13 18:37:00 +00001470 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001471 }
1472
1473 void addSysCROperands(MCInst &Inst, unsigned N) const {
1474 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001475 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001476 }
1477
1478 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1479 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001480 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001481 }
1482
Oliver Stannarda34e4702015-12-01 10:48:51 +00001483 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1484 assert(N == 1 && "Invalid number of operands!");
1485 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1486 }
1487
Tim Northover3b0846e2014-05-24 12:50:23 +00001488 void addShifterOperands(MCInst &Inst, unsigned N) const {
1489 assert(N == 1 && "Invalid number of operands!");
1490 unsigned Imm =
1491 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001492 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001493 }
1494
1495 void addExtendOperands(MCInst &Inst, unsigned N) const {
1496 assert(N == 1 && "Invalid number of operands!");
1497 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1498 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1499 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001500 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001501 }
1502
1503 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1504 assert(N == 1 && "Invalid number of operands!");
1505 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1506 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1507 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001508 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001509 }
1510
1511 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1512 assert(N == 2 && "Invalid number of operands!");
1513 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1514 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001515 Inst.addOperand(MCOperand::createImm(IsSigned));
1516 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001517 }
1518
1519 // For 8-bit load/store instructions with a register offset, both the
1520 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1521 // they're disambiguated by whether the shift was explicit or implicit rather
1522 // than its size.
1523 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1524 assert(N == 2 && "Invalid number of operands!");
1525 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1526 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001527 Inst.addOperand(MCOperand::createImm(IsSigned));
1528 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001529 }
1530
1531 template<int Shift>
1532 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1533 assert(N == 1 && "Invalid number of operands!");
1534
1535 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1536 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001537 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001538 }
1539
1540 template<int Shift>
1541 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1542 assert(N == 1 && "Invalid number of operands!");
1543
1544 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1545 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001546 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001547 }
1548
Sam Parker5f934642017-08-31 09:27:04 +00001549 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1550 assert(N == 1 && "Invalid number of operands!");
1551 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1552 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1553 }
1554
1555 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1556 assert(N == 1 && "Invalid number of operands!");
1557 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1558 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1559 }
1560
Tim Northover3b0846e2014-05-24 12:50:23 +00001561 void print(raw_ostream &OS) const override;
1562
David Blaikie960ea3f2014-06-08 16:18:35 +00001563 static std::unique_ptr<AArch64Operand>
1564 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1565 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001566 Op->Tok.Data = Str.data();
1567 Op->Tok.Length = Str.size();
1568 Op->Tok.IsSuffix = IsSuffix;
1569 Op->StartLoc = S;
1570 Op->EndLoc = S;
1571 return Op;
1572 }
1573
David Blaikie960ea3f2014-06-08 16:18:35 +00001574 static std::unique_ptr<AArch64Operand>
Florian Hahnc4422242017-11-07 13:07:50 +00001575 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001576 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001577 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001578 Op->Reg.Kind = Kind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001579 Op->StartLoc = S;
1580 Op->EndLoc = E;
1581 return Op;
1582 }
1583
David Blaikie960ea3f2014-06-08 16:18:35 +00001584 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001585 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1586 SMLoc S, SMLoc E, MCContext &Ctx) {
1587 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1588 Kind == RegKind::SVEPredicateVector) &&
1589 "Invalid vector kind");
Florian Hahn91f11e52017-11-07 16:45:48 +00001590 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1591 Op->Reg.RegNum = RegNum;
1592 Op->Reg.ElementWidth = ElementWidth;
1593 Op->Reg.Kind = Kind;
1594 Op->StartLoc = S;
1595 Op->EndLoc = E;
1596 return Op;
1597 }
1598
1599 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001600 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001601 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1602 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001603 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001604 Op->VectorList.RegNum = RegNum;
1605 Op->VectorList.Count = Count;
1606 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001607 Op->VectorList.ElementWidth = ElementWidth;
1608 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001609 Op->StartLoc = S;
1610 Op->EndLoc = E;
1611 return Op;
1612 }
1613
David Blaikie960ea3f2014-06-08 16:18:35 +00001614 static std::unique_ptr<AArch64Operand>
1615 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1616 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001617 Op->VectorIndex.Val = Idx;
1618 Op->StartLoc = S;
1619 Op->EndLoc = E;
1620 return Op;
1621 }
1622
David Blaikie960ea3f2014-06-08 16:18:35 +00001623 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1624 SMLoc E, MCContext &Ctx) {
1625 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001626 Op->Imm.Val = Val;
1627 Op->StartLoc = S;
1628 Op->EndLoc = E;
1629 return Op;
1630 }
1631
David Blaikie960ea3f2014-06-08 16:18:35 +00001632 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1633 unsigned ShiftAmount,
1634 SMLoc S, SMLoc E,
1635 MCContext &Ctx) {
1636 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001637 Op->ShiftedImm .Val = Val;
1638 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1639 Op->StartLoc = S;
1640 Op->EndLoc = E;
1641 return Op;
1642 }
1643
David Blaikie960ea3f2014-06-08 16:18:35 +00001644 static std::unique_ptr<AArch64Operand>
1645 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1646 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001647 Op->CondCode.Code = Code;
1648 Op->StartLoc = S;
1649 Op->EndLoc = E;
1650 return Op;
1651 }
1652
David Blaikie960ea3f2014-06-08 16:18:35 +00001653 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1654 MCContext &Ctx) {
1655 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001656 Op->FPImm.Val = Val;
1657 Op->StartLoc = S;
1658 Op->EndLoc = S;
1659 return Op;
1660 }
1661
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001662 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1663 StringRef Str,
1664 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001665 MCContext &Ctx) {
1666 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001667 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001668 Op->Barrier.Data = Str.data();
1669 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001670 Op->StartLoc = S;
1671 Op->EndLoc = S;
1672 return Op;
1673 }
1674
Tim Northover7cd58932015-01-22 17:23:04 +00001675 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1676 uint32_t MRSReg,
1677 uint32_t MSRReg,
1678 uint32_t PStateField,
1679 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001680 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001681 Op->SysReg.Data = Str.data();
1682 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001683 Op->SysReg.MRSReg = MRSReg;
1684 Op->SysReg.MSRReg = MSRReg;
1685 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001686 Op->StartLoc = S;
1687 Op->EndLoc = S;
1688 return Op;
1689 }
1690
David Blaikie960ea3f2014-06-08 16:18:35 +00001691 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1692 SMLoc E, MCContext &Ctx) {
1693 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001694 Op->SysCRImm.Val = Val;
1695 Op->StartLoc = S;
1696 Op->EndLoc = E;
1697 return Op;
1698 }
1699
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001700 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1701 StringRef Str,
1702 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001703 MCContext &Ctx) {
1704 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001705 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001706 Op->Barrier.Data = Str.data();
1707 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001708 Op->StartLoc = S;
1709 Op->EndLoc = S;
1710 return Op;
1711 }
1712
Oliver Stannarda34e4702015-12-01 10:48:51 +00001713 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1714 StringRef Str,
1715 SMLoc S,
1716 MCContext &Ctx) {
1717 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1718 Op->PSBHint.Val = Val;
1719 Op->PSBHint.Data = Str.data();
1720 Op->PSBHint.Length = Str.size();
1721 Op->StartLoc = S;
1722 Op->EndLoc = S;
1723 return Op;
1724 }
1725
David Blaikie960ea3f2014-06-08 16:18:35 +00001726 static std::unique_ptr<AArch64Operand>
1727 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1728 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1729 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001730 Op->ShiftExtend.Type = ShOp;
1731 Op->ShiftExtend.Amount = Val;
1732 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1733 Op->StartLoc = S;
1734 Op->EndLoc = E;
1735 return Op;
1736 }
1737};
1738
1739} // end anonymous namespace.
1740
1741void AArch64Operand::print(raw_ostream &OS) const {
1742 switch (Kind) {
1743 case k_FPImm:
1744 OS << "<fpimm " << getFPImm() << "("
1745 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1746 break;
1747 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001748 StringRef Name = getBarrierName();
1749 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001750 OS << "<barrier " << Name << ">";
1751 else
1752 OS << "<barrier invalid #" << getBarrier() << ">";
1753 break;
1754 }
1755 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001756 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001757 break;
1758 case k_ShiftedImm: {
1759 unsigned Shift = getShiftedImmShift();
1760 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001761 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001762 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1763 break;
1764 }
1765 case k_CondCode:
1766 OS << "<condcode " << getCondCode() << ">";
1767 break;
1768 case k_Register:
1769 OS << "<register " << getReg() << ">";
1770 break;
1771 case k_VectorList: {
1772 OS << "<vectorlist ";
1773 unsigned Reg = getVectorListStart();
1774 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1775 OS << Reg + i << " ";
1776 OS << ">";
1777 break;
1778 }
1779 case k_VectorIndex:
1780 OS << "<vectorindex " << getVectorIndex() << ">";
1781 break;
1782 case k_SysReg:
1783 OS << "<sysreg: " << getSysReg() << '>';
1784 break;
1785 case k_Token:
1786 OS << "'" << getToken() << "'";
1787 break;
1788 case k_SysCR:
1789 OS << "c" << getSysCR();
1790 break;
1791 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001792 StringRef Name = getPrefetchName();
1793 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001794 OS << "<prfop " << Name << ">";
1795 else
1796 OS << "<prfop invalid #" << getPrefetch() << ">";
1797 break;
1798 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001799 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001800 OS << getPSBHintName();
1801 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001802 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001803 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1804 << getShiftExtendAmount();
1805 if (!hasShiftExtendAmount())
1806 OS << "<imp>";
1807 OS << '>';
1808 break;
1809 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001810}
1811
1812/// @name Auto-generated Match Functions
1813/// {
1814
1815static unsigned MatchRegisterName(StringRef Name);
1816
1817/// }
1818
Florian Hahnc4422242017-11-07 13:07:50 +00001819static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001820 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001821 .Case("v0", AArch64::Q0)
1822 .Case("v1", AArch64::Q1)
1823 .Case("v2", AArch64::Q2)
1824 .Case("v3", AArch64::Q3)
1825 .Case("v4", AArch64::Q4)
1826 .Case("v5", AArch64::Q5)
1827 .Case("v6", AArch64::Q6)
1828 .Case("v7", AArch64::Q7)
1829 .Case("v8", AArch64::Q8)
1830 .Case("v9", AArch64::Q9)
1831 .Case("v10", AArch64::Q10)
1832 .Case("v11", AArch64::Q11)
1833 .Case("v12", AArch64::Q12)
1834 .Case("v13", AArch64::Q13)
1835 .Case("v14", AArch64::Q14)
1836 .Case("v15", AArch64::Q15)
1837 .Case("v16", AArch64::Q16)
1838 .Case("v17", AArch64::Q17)
1839 .Case("v18", AArch64::Q18)
1840 .Case("v19", AArch64::Q19)
1841 .Case("v20", AArch64::Q20)
1842 .Case("v21", AArch64::Q21)
1843 .Case("v22", AArch64::Q22)
1844 .Case("v23", AArch64::Q23)
1845 .Case("v24", AArch64::Q24)
1846 .Case("v25", AArch64::Q25)
1847 .Case("v26", AArch64::Q26)
1848 .Case("v27", AArch64::Q27)
1849 .Case("v28", AArch64::Q28)
1850 .Case("v29", AArch64::Q29)
1851 .Case("v30", AArch64::Q30)
1852 .Case("v31", AArch64::Q31)
1853 .Default(0);
1854}
1855
Sander de Smalen73937b72018-04-11 07:36:10 +00001856/// Returns an optional pair of (#elements, element-width) if Suffix
1857/// is a valid vector kind. Where the number of elements in a vector
1858/// or the vector width is implicit or explicitly unknown (but still a
1859/// valid suffix kind), 0 is used.
1860static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1861 RegKind VectorKind) {
1862 std::pair<int, int> Res = {-1, -1};
1863
1864 switch (VectorKind) {
1865 case RegKind::NeonVector:
1866 Res =
1867 StringSwitch<std::pair<int, int>>(Suffix.lower())
1868 .Case("", {0, 0})
1869 .Case(".1d", {1, 64})
1870 .Case(".1q", {1, 128})
1871 // '.2h' needed for fp16 scalar pairwise reductions
1872 .Case(".2h", {2, 16})
1873 .Case(".2s", {2, 32})
1874 .Case(".2d", {2, 64})
1875 // '.4b' is another special case for the ARMv8.2a dot product
1876 // operand
1877 .Case(".4b", {4, 8})
1878 .Case(".4h", {4, 16})
1879 .Case(".4s", {4, 32})
1880 .Case(".8b", {8, 8})
1881 .Case(".8h", {8, 16})
1882 .Case(".16b", {16, 8})
1883 // Accept the width neutral ones, too, for verbose syntax. If those
1884 // aren't used in the right places, the token operand won't match so
1885 // all will work out.
1886 .Case(".b", {0, 8})
1887 .Case(".h", {0, 16})
1888 .Case(".s", {0, 32})
1889 .Case(".d", {0, 64})
1890 .Default({-1, -1});
1891 break;
1892 case RegKind::SVEPredicateVector:
1893 case RegKind::SVEDataVector:
1894 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1895 .Case("", {0, 0})
1896 .Case(".b", {0, 8})
1897 .Case(".h", {0, 16})
1898 .Case(".s", {0, 32})
1899 .Case(".d", {0, 64})
1900 .Case(".q", {0, 128})
1901 .Default({-1, -1});
1902 break;
1903 default:
1904 llvm_unreachable("Unsupported RegKind");
1905 }
1906
1907 if (Res == std::make_pair(-1, -1))
1908 return Optional<std::pair<int, int>>();
1909
1910 return Optional<std::pair<int, int>>(Res);
1911}
1912
1913static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1914 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001915}
1916
Florian Hahn91f11e52017-11-07 16:45:48 +00001917static unsigned matchSVEDataVectorRegName(StringRef Name) {
1918 return StringSwitch<unsigned>(Name.lower())
1919 .Case("z0", AArch64::Z0)
1920 .Case("z1", AArch64::Z1)
1921 .Case("z2", AArch64::Z2)
1922 .Case("z3", AArch64::Z3)
1923 .Case("z4", AArch64::Z4)
1924 .Case("z5", AArch64::Z5)
1925 .Case("z6", AArch64::Z6)
1926 .Case("z7", AArch64::Z7)
1927 .Case("z8", AArch64::Z8)
1928 .Case("z9", AArch64::Z9)
1929 .Case("z10", AArch64::Z10)
1930 .Case("z11", AArch64::Z11)
1931 .Case("z12", AArch64::Z12)
1932 .Case("z13", AArch64::Z13)
1933 .Case("z14", AArch64::Z14)
1934 .Case("z15", AArch64::Z15)
1935 .Case("z16", AArch64::Z16)
1936 .Case("z17", AArch64::Z17)
1937 .Case("z18", AArch64::Z18)
1938 .Case("z19", AArch64::Z19)
1939 .Case("z20", AArch64::Z20)
1940 .Case("z21", AArch64::Z21)
1941 .Case("z22", AArch64::Z22)
1942 .Case("z23", AArch64::Z23)
1943 .Case("z24", AArch64::Z24)
1944 .Case("z25", AArch64::Z25)
1945 .Case("z26", AArch64::Z26)
1946 .Case("z27", AArch64::Z27)
1947 .Case("z28", AArch64::Z28)
1948 .Case("z29", AArch64::Z29)
1949 .Case("z30", AArch64::Z30)
1950 .Case("z31", AArch64::Z31)
1951 .Default(0);
1952}
1953
Sander de Smalencd6be962017-12-20 11:02:42 +00001954static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1955 return StringSwitch<unsigned>(Name.lower())
1956 .Case("p0", AArch64::P0)
1957 .Case("p1", AArch64::P1)
1958 .Case("p2", AArch64::P2)
1959 .Case("p3", AArch64::P3)
1960 .Case("p4", AArch64::P4)
1961 .Case("p5", AArch64::P5)
1962 .Case("p6", AArch64::P6)
1963 .Case("p7", AArch64::P7)
1964 .Case("p8", AArch64::P8)
1965 .Case("p9", AArch64::P9)
1966 .Case("p10", AArch64::P10)
1967 .Case("p11", AArch64::P11)
1968 .Case("p12", AArch64::P12)
1969 .Case("p13", AArch64::P13)
1970 .Case("p14", AArch64::P14)
1971 .Case("p15", AArch64::P15)
1972 .Default(0);
1973}
1974
Tim Northover3b0846e2014-05-24 12:50:23 +00001975bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1976 SMLoc &EndLoc) {
1977 StartLoc = getLoc();
1978 RegNo = tryParseRegister();
1979 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1980 return (RegNo == (unsigned)-1);
1981}
1982
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001983// Matches a register name or register alias previously defined by '.req'
1984unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001985 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001986 unsigned RegNum = 0;
1987 if ((RegNum = matchSVEDataVectorRegName(Name)))
1988 return Kind == RegKind::SVEDataVector ? RegNum : 0;
1989
Sander de Smalencd6be962017-12-20 11:02:42 +00001990 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
1991 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
1992
Sander de Smalenc067c302017-12-20 09:45:45 +00001993 if ((RegNum = MatchNeonVectorRegName(Name)))
1994 return Kind == RegKind::NeonVector ? RegNum : 0;
1995
1996 // The parsed register must be of RegKind Scalar
1997 if ((RegNum = MatchRegisterName(Name)))
1998 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001999
Florian Hahnc4422242017-11-07 13:07:50 +00002000 if (!RegNum) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002001 // Check for aliases registered via .req. Canonicalize to lower case.
2002 // That's more consistent since register names are case insensitive, and
2003 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2004 auto Entry = RegisterReqs.find(Name.lower());
2005 if (Entry == RegisterReqs.end())
2006 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002007
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002008 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002009 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002010 RegNum = Entry->getValue().second;
2011 }
2012 return RegNum;
2013}
2014
Tim Northover3b0846e2014-05-24 12:50:23 +00002015/// tryParseRegister - Try to parse a register name. The token must be an
2016/// Identifier when called, and if it is a register name the token is eaten and
2017/// the register is added to the operand list.
2018int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002019 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002020 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002021 if (Tok.isNot(AsmToken::Identifier))
2022 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00002023
2024 std::string lowerCase = Tok.getString().lower();
Florian Hahnc4422242017-11-07 13:07:50 +00002025 unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
Sander de Smalenc067c302017-12-20 09:45:45 +00002026
Tim Northover3b0846e2014-05-24 12:50:23 +00002027 // Also handle a few aliases of registers.
2028 if (RegNum == 0)
2029 RegNum = StringSwitch<unsigned>(lowerCase)
2030 .Case("fp", AArch64::FP)
2031 .Case("lr", AArch64::LR)
2032 .Case("x31", AArch64::XZR)
2033 .Case("w31", AArch64::WZR)
2034 .Default(0);
2035
2036 if (RegNum == 0)
2037 return -1;
2038
2039 Parser.Lex(); // Eat identifier token.
2040 return RegNum;
2041}
2042
Tim Northover3b0846e2014-05-24 12:50:23 +00002043/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002044OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002045AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002046 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002047 SMLoc S = getLoc();
2048
2049 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2050 Error(S, "Expected cN operand where 0 <= N <= 15");
2051 return MatchOperand_ParseFail;
2052 }
2053
2054 StringRef Tok = Parser.getTok().getIdentifier();
2055 if (Tok[0] != 'c' && Tok[0] != 'C') {
2056 Error(S, "Expected cN operand where 0 <= N <= 15");
2057 return MatchOperand_ParseFail;
2058 }
2059
2060 uint32_t CRNum;
2061 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2062 if (BadNum || CRNum > 15) {
2063 Error(S, "Expected cN operand where 0 <= N <= 15");
2064 return MatchOperand_ParseFail;
2065 }
2066
2067 Parser.Lex(); // Eat identifier token.
2068 Operands.push_back(
2069 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2070 return MatchOperand_Success;
2071}
2072
2073/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002074OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002075AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002076 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002077 SMLoc S = getLoc();
2078 const AsmToken &Tok = Parser.getTok();
2079 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002080 // Eat optional hash.
2081 if (parseOptionalToken(AsmToken::Hash) ||
2082 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002083 const MCExpr *ImmVal;
2084 if (getParser().parseExpression(ImmVal))
2085 return MatchOperand_ParseFail;
2086
2087 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2088 if (!MCE) {
2089 TokError("immediate value expected for prefetch operand");
2090 return MatchOperand_ParseFail;
2091 }
2092 unsigned prfop = MCE->getValue();
2093 if (prfop > 31) {
2094 TokError("prefetch operand out of range, [0,31] expected");
2095 return MatchOperand_ParseFail;
2096 }
2097
Tim Northovere6ae6762016-07-05 21:23:04 +00002098 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2099 Operands.push_back(AArch64Operand::CreatePrefetch(
2100 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002101 return MatchOperand_Success;
2102 }
2103
2104 if (Tok.isNot(AsmToken::Identifier)) {
2105 TokError("pre-fetch hint expected");
2106 return MatchOperand_ParseFail;
2107 }
2108
Tim Northovere6ae6762016-07-05 21:23:04 +00002109 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2110 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002111 TokError("pre-fetch hint expected");
2112 return MatchOperand_ParseFail;
2113 }
2114
2115 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002116 Operands.push_back(AArch64Operand::CreatePrefetch(
2117 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002118 return MatchOperand_Success;
2119}
2120
Oliver Stannarda34e4702015-12-01 10:48:51 +00002121/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002122OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002123AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2124 MCAsmParser &Parser = getParser();
2125 SMLoc S = getLoc();
2126 const AsmToken &Tok = Parser.getTok();
2127 if (Tok.isNot(AsmToken::Identifier)) {
2128 TokError("invalid operand for instruction");
2129 return MatchOperand_ParseFail;
2130 }
2131
Tim Northovere6ae6762016-07-05 21:23:04 +00002132 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2133 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002134 TokError("invalid operand for instruction");
2135 return MatchOperand_ParseFail;
2136 }
2137
2138 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002139 Operands.push_back(AArch64Operand::CreatePSBHint(
2140 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002141 return MatchOperand_Success;
2142}
2143
Tim Northover3b0846e2014-05-24 12:50:23 +00002144/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2145/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002146OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002147AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002148 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002149 SMLoc S = getLoc();
2150 const MCExpr *Expr;
2151
2152 if (Parser.getTok().is(AsmToken::Hash)) {
2153 Parser.Lex(); // Eat hash token.
2154 }
2155
2156 if (parseSymbolicImmVal(Expr))
2157 return MatchOperand_ParseFail;
2158
2159 AArch64MCExpr::VariantKind ELFRefKind;
2160 MCSymbolRefExpr::VariantKind DarwinRefKind;
2161 int64_t Addend;
2162 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2163 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2164 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2165 // No modifier was specified at all; this is the syntax for an ELF basic
2166 // ADRP relocation (unfortunately).
2167 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002168 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002169 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2170 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2171 Addend != 0) {
2172 Error(S, "gotpage label reference not allowed an addend");
2173 return MatchOperand_ParseFail;
2174 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2175 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2176 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2177 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2178 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2179 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2180 // The operand must be an @page or @gotpage qualified symbolref.
2181 Error(S, "page or gotpage label reference expected");
2182 return MatchOperand_ParseFail;
2183 }
2184 }
2185
2186 // We have either a label reference possibly with addend or an immediate. The
2187 // addend is a raw value here. The linker will adjust it to only reference the
2188 // page.
2189 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2190 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2191
2192 return MatchOperand_Success;
2193}
2194
2195/// tryParseAdrLabel - Parse and validate a source label for the ADR
2196/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002197OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002198AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2199 SMLoc S = getLoc();
2200 const MCExpr *Expr;
2201
Nirav Davee833c6c2016-11-08 18:31:04 +00002202 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002203 if (getParser().parseExpression(Expr))
2204 return MatchOperand_ParseFail;
2205
2206 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2207 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2208
2209 return MatchOperand_Success;
2210}
2211
2212/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002213OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002214AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002215 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002216 SMLoc S = getLoc();
2217
Nirav Davee833c6c2016-11-08 18:31:04 +00002218 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002219
2220 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002221 bool isNegative = parseOptionalToken(AsmToken::Minus);
2222
Tim Northover3b0846e2014-05-24 12:50:23 +00002223 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002224 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002225 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002226 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002227 Val = Tok.getIntVal();
2228 if (Val > 255 || Val < 0) {
2229 TokError("encoded floating point value out of range");
2230 return MatchOperand_ParseFail;
2231 }
2232 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002233 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002234 if (isNegative)
2235 RealVal.changeSign();
2236
Tim Northover3b0846e2014-05-24 12:50:23 +00002237 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002238 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002239
John Brawn5ca5daa2017-04-20 10:13:54 +00002240 // Check for out of range values. As an exception we let Zero through,
2241 // but as tokens instead of an FPImm so that it can be matched by the
2242 // appropriate alias if one exists.
2243 if (RealVal.isPosZero()) {
2244 Parser.Lex(); // Eat the token.
2245 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2246 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2247 return MatchOperand_Success;
2248 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002249 TokError("expected compatible register or floating-point constant");
2250 return MatchOperand_ParseFail;
2251 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002252 }
2253 Parser.Lex(); // Eat the token.
2254 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2255 return MatchOperand_Success;
2256 }
2257
2258 if (!Hash)
2259 return MatchOperand_NoMatch;
2260
2261 TokError("invalid floating point immediate");
2262 return MatchOperand_ParseFail;
2263}
2264
2265/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002266OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002267AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002268 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002269 SMLoc S = getLoc();
2270
2271 if (Parser.getTok().is(AsmToken::Hash))
2272 Parser.Lex(); // Eat '#'
2273 else if (Parser.getTok().isNot(AsmToken::Integer))
2274 // Operand should start from # or should be integer, emit error otherwise.
2275 return MatchOperand_NoMatch;
2276
2277 const MCExpr *Imm;
2278 if (parseSymbolicImmVal(Imm))
2279 return MatchOperand_ParseFail;
2280 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2281 uint64_t ShiftAmount = 0;
2282 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2283 if (MCE) {
2284 int64_t Val = MCE->getValue();
2285 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002286 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002287 ShiftAmount = 12;
2288 }
2289 }
2290 SMLoc E = Parser.getTok().getLoc();
2291 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2292 getContext()));
2293 return MatchOperand_Success;
2294 }
2295
2296 // Eat ','
2297 Parser.Lex();
2298
2299 // The optional operand must be "lsl #N" where N is non-negative.
2300 if (!Parser.getTok().is(AsmToken::Identifier) ||
2301 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2302 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2303 return MatchOperand_ParseFail;
2304 }
2305
2306 // Eat 'lsl'
2307 Parser.Lex();
2308
Nirav Davee833c6c2016-11-08 18:31:04 +00002309 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002310
2311 if (Parser.getTok().isNot(AsmToken::Integer)) {
2312 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2313 return MatchOperand_ParseFail;
2314 }
2315
2316 int64_t ShiftAmount = Parser.getTok().getIntVal();
2317
2318 if (ShiftAmount < 0) {
2319 Error(Parser.getTok().getLoc(), "positive shift amount required");
2320 return MatchOperand_ParseFail;
2321 }
2322 Parser.Lex(); // Eat the number
2323
2324 SMLoc E = Parser.getTok().getLoc();
2325 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2326 S, E, getContext()));
2327 return MatchOperand_Success;
2328}
2329
2330/// parseCondCodeString - Parse a Condition Code string.
2331AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2332 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2333 .Case("eq", AArch64CC::EQ)
2334 .Case("ne", AArch64CC::NE)
2335 .Case("cs", AArch64CC::HS)
2336 .Case("hs", AArch64CC::HS)
2337 .Case("cc", AArch64CC::LO)
2338 .Case("lo", AArch64CC::LO)
2339 .Case("mi", AArch64CC::MI)
2340 .Case("pl", AArch64CC::PL)
2341 .Case("vs", AArch64CC::VS)
2342 .Case("vc", AArch64CC::VC)
2343 .Case("hi", AArch64CC::HI)
2344 .Case("ls", AArch64CC::LS)
2345 .Case("ge", AArch64CC::GE)
2346 .Case("lt", AArch64CC::LT)
2347 .Case("gt", AArch64CC::GT)
2348 .Case("le", AArch64CC::LE)
2349 .Case("al", AArch64CC::AL)
2350 .Case("nv", AArch64CC::NV)
2351 .Default(AArch64CC::Invalid);
2352 return CC;
2353}
2354
2355/// parseCondCode - Parse a Condition Code operand.
2356bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2357 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002358 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002359 SMLoc S = getLoc();
2360 const AsmToken &Tok = Parser.getTok();
2361 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2362
2363 StringRef Cond = Tok.getString();
2364 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2365 if (CC == AArch64CC::Invalid)
2366 return TokError("invalid condition code");
2367 Parser.Lex(); // Eat identifier token.
2368
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002369 if (invertCondCode) {
2370 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2371 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002372 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002373 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002374
2375 Operands.push_back(
2376 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2377 return false;
2378}
2379
2380/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2381/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002382OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002383AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002384 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002385 const AsmToken &Tok = Parser.getTok();
2386 std::string LowerID = Tok.getString().lower();
2387 AArch64_AM::ShiftExtendType ShOp =
2388 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2389 .Case("lsl", AArch64_AM::LSL)
2390 .Case("lsr", AArch64_AM::LSR)
2391 .Case("asr", AArch64_AM::ASR)
2392 .Case("ror", AArch64_AM::ROR)
2393 .Case("msl", AArch64_AM::MSL)
2394 .Case("uxtb", AArch64_AM::UXTB)
2395 .Case("uxth", AArch64_AM::UXTH)
2396 .Case("uxtw", AArch64_AM::UXTW)
2397 .Case("uxtx", AArch64_AM::UXTX)
2398 .Case("sxtb", AArch64_AM::SXTB)
2399 .Case("sxth", AArch64_AM::SXTH)
2400 .Case("sxtw", AArch64_AM::SXTW)
2401 .Case("sxtx", AArch64_AM::SXTX)
2402 .Default(AArch64_AM::InvalidShiftExtend);
2403
2404 if (ShOp == AArch64_AM::InvalidShiftExtend)
2405 return MatchOperand_NoMatch;
2406
2407 SMLoc S = Tok.getLoc();
2408 Parser.Lex();
2409
Nirav Davee833c6c2016-11-08 18:31:04 +00002410 bool Hash = parseOptionalToken(AsmToken::Hash);
2411
Tim Northover3b0846e2014-05-24 12:50:23 +00002412 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2413 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2414 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2415 ShOp == AArch64_AM::MSL) {
2416 // We expect a number here.
2417 TokError("expected #imm after shift specifier");
2418 return MatchOperand_ParseFail;
2419 }
2420
Chad Rosier2ff37b82016-12-27 16:58:09 +00002421 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002422 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2423 Operands.push_back(
2424 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2425 return MatchOperand_Success;
2426 }
2427
Chad Rosier2ff37b82016-12-27 16:58:09 +00002428 // Make sure we do actually have a number, identifier or a parenthesized
2429 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002430 SMLoc E = Parser.getTok().getLoc();
2431 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002432 !Parser.getTok().is(AsmToken::LParen) &&
2433 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002434 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002435 return MatchOperand_ParseFail;
2436 }
2437
2438 const MCExpr *ImmVal;
2439 if (getParser().parseExpression(ImmVal))
2440 return MatchOperand_ParseFail;
2441
2442 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2443 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002444 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002445 return MatchOperand_ParseFail;
2446 }
2447
Jim Grosbach57fd2622014-09-23 22:16:02 +00002448 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002449 Operands.push_back(AArch64Operand::CreateShiftExtend(
2450 ShOp, MCE->getValue(), true, S, E, getContext()));
2451 return MatchOperand_Success;
2452}
2453
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002454static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2455 if (FBS[AArch64::HasV8_1aOps])
2456 Str += "ARMv8.1a";
2457 else if (FBS[AArch64::HasV8_2aOps])
2458 Str += "ARMv8.2a";
2459 else
2460 Str += "(unknown)";
2461}
2462
2463void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2464 SMLoc S) {
2465 const uint16_t Op2 = Encoding & 7;
2466 const uint16_t Cm = (Encoding & 0x78) >> 3;
2467 const uint16_t Cn = (Encoding & 0x780) >> 7;
2468 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2469
2470 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2471
2472 Operands.push_back(
2473 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2474 Operands.push_back(
2475 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2476 Operands.push_back(
2477 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2478 Expr = MCConstantExpr::create(Op2, getContext());
2479 Operands.push_back(
2480 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2481}
2482
Tim Northover3b0846e2014-05-24 12:50:23 +00002483/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2484/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2485bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2486 OperandVector &Operands) {
2487 if (Name.find('.') != StringRef::npos)
2488 return TokError("invalid operand");
2489
2490 Mnemonic = Name;
2491 Operands.push_back(
2492 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2493
Rafael Espindola961d4692014-11-11 05:18:41 +00002494 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002495 const AsmToken &Tok = Parser.getTok();
2496 StringRef Op = Tok.getString();
2497 SMLoc S = Tok.getLoc();
2498
Tim Northover3b0846e2014-05-24 12:50:23 +00002499 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002500 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2501 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002502 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002503 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2504 std::string Str("IC " + std::string(IC->Name) + " requires ");
2505 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2506 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002507 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002508 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002509 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002510 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2511 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002512 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002513 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2514 std::string Str("DC " + std::string(DC->Name) + " requires ");
2515 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2516 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002517 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002518 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002519 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002520 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2521 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002522 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002523 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2524 std::string Str("AT " + std::string(AT->Name) + " requires ");
2525 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2526 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002527 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002528 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002529 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002530 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2531 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002532 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002533 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2534 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2535 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2536 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002537 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002538 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002539 }
2540
Tim Northover3b0846e2014-05-24 12:50:23 +00002541 Parser.Lex(); // Eat operand.
2542
2543 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2544 bool HasRegister = false;
2545
2546 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002547 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002548 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2549 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002550 HasRegister = true;
2551 }
2552
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002553 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002554 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002555 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002556 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002557
Nirav Davee833c6c2016-11-08 18:31:04 +00002558 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2559 return true;
2560
Tim Northover3b0846e2014-05-24 12:50:23 +00002561 return false;
2562}
2563
Alex Bradbury58eba092016-11-01 16:32:05 +00002564OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002565AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002566 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002567 const AsmToken &Tok = Parser.getTok();
2568
2569 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002570 if (parseOptionalToken(AsmToken::Hash) ||
2571 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002572 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002573 const MCExpr *ImmVal;
2574 SMLoc ExprLoc = getLoc();
2575 if (getParser().parseExpression(ImmVal))
2576 return MatchOperand_ParseFail;
2577 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2578 if (!MCE) {
2579 Error(ExprLoc, "immediate value expected for barrier operand");
2580 return MatchOperand_ParseFail;
2581 }
2582 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2583 Error(ExprLoc, "barrier operand out of range");
2584 return MatchOperand_ParseFail;
2585 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002586 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2587 Operands.push_back(AArch64Operand::CreateBarrier(
2588 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002589 return MatchOperand_Success;
2590 }
2591
2592 if (Tok.isNot(AsmToken::Identifier)) {
2593 TokError("invalid operand for instruction");
2594 return MatchOperand_ParseFail;
2595 }
2596
Tim Northover3b0846e2014-05-24 12:50:23 +00002597 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002598 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2599 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002600 TokError("'sy' or #imm operand expected");
2601 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002602 } else if (!DB) {
2603 TokError("invalid barrier option name");
2604 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002605 }
2606
Tim Northovere6ae6762016-07-05 21:23:04 +00002607 Operands.push_back(AArch64Operand::CreateBarrier(
2608 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002609 Parser.Lex(); // Consume the option
2610
2611 return MatchOperand_Success;
2612}
2613
Alex Bradbury58eba092016-11-01 16:32:05 +00002614OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002615AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002616 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002617 const AsmToken &Tok = Parser.getTok();
2618
2619 if (Tok.isNot(AsmToken::Identifier))
2620 return MatchOperand_NoMatch;
2621
Tim Northovere6ae6762016-07-05 21:23:04 +00002622 int MRSReg, MSRReg;
2623 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2624 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2625 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2626 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2627 } else
2628 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002629
Tim Northovere6ae6762016-07-05 21:23:04 +00002630 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2631 unsigned PStateImm = -1;
2632 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2633 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002634
Tim Northovere6ae6762016-07-05 21:23:04 +00002635 Operands.push_back(
2636 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2637 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002638 Parser.Lex(); // Eat identifier
2639
2640 return MatchOperand_Success;
2641}
2642
Florian Hahnc4422242017-11-07 13:07:50 +00002643/// tryParseNeonVectorRegister - Parse a vector register operand.
2644bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002645 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002646 if (Parser.getTok().isNot(AsmToken::Identifier))
2647 return true;
2648
2649 SMLoc S = getLoc();
2650 // Check for a vector register specifier first.
2651 StringRef Kind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002652 int Reg = -1;
2653 OperandMatchResultTy Res =
2654 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2655 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002656 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002657
2658 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2659 if (!KindRes)
2660 return true;
2661
2662 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002663 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002664 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2665 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002666
Tim Northover3b0846e2014-05-24 12:50:23 +00002667 // If there was an explicit qualifier, that goes on as a literal text
2668 // operand.
2669 if (!Kind.empty())
2670 Operands.push_back(
2671 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2672
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002673 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2674}
2675
2676OperandMatchResultTy
2677AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002678 SMLoc SIdx = getLoc();
2679 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002680 const MCExpr *ImmVal;
2681 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002682 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002683 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2684 if (!MCE) {
2685 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002686 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002687 }
2688
2689 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002690
Nirav Davee833c6c2016-11-08 18:31:04 +00002691 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002692 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002693
2694 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2695 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002696 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002697 }
2698
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002699 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002700}
2701
Sander de Smalen73937b72018-04-11 07:36:10 +00002702// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002703// optional kind specifier. If it is a register specifier, eat the token
2704// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002705OperandMatchResultTy
Sander de Smalen73937b72018-04-11 07:36:10 +00002706AArch64AsmParser::tryParseVectorRegister(int &Reg, StringRef &Kind,
2707 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002708 MCAsmParser &Parser = getParser();
2709 const AsmToken &Tok = Parser.getTok();
2710
Florian Hahn91f11e52017-11-07 16:45:48 +00002711 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002712 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002713
2714 StringRef Name = Tok.getString();
2715 // If there is a kind specifier, it's separated from the register name by
2716 // a '.'.
2717 size_t Start = 0, Next = Name.find('.');
2718 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002719 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002720
2721 if (RegNum) {
2722 if (Next != StringRef::npos) {
2723 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002724 if (!isValidVectorKind(Kind, MatchKind)) {
2725 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002726 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002727 }
2728 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002729 Parser.Lex(); // Eat the register token.
2730
2731 Reg = RegNum;
2732 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002733 }
2734
Sander de Smalen8e607342017-11-15 15:44:43 +00002735 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002736}
2737
Sander de Smalencd6be962017-12-20 11:02:42 +00002738/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2739OperandMatchResultTy
2740AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2741 // Check for a SVE predicate register specifier first.
2742 const SMLoc S = getLoc();
2743 StringRef Kind;
2744 int RegNum = -1;
Sander de Smalen73937b72018-04-11 07:36:10 +00002745 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002746 if (Res != MatchOperand_Success)
2747 return Res;
2748
Sander de Smalen73937b72018-04-11 07:36:10 +00002749 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2750 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002751 return MatchOperand_NoMatch;
2752
Sander de Smalen73937b72018-04-11 07:36:10 +00002753 unsigned ElementWidth = KindRes->second;
2754 Operands.push_back(AArch64Operand::CreateVectorReg(
2755 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2756 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002757
Sander de Smalen7868e742018-01-09 11:17:06 +00002758 // Not all predicates are followed by a '/m' or '/z'.
2759 MCAsmParser &Parser = getParser();
2760 if (Parser.getTok().isNot(AsmToken::Slash))
2761 return MatchOperand_Success;
2762
2763 // But when they do they shouldn't have an element type suffix.
2764 if (!Kind.empty()) {
2765 Error(S, "not expecting size suffix");
2766 return MatchOperand_ParseFail;
2767 }
2768
2769 // Add a literal slash as operand
2770 Operands.push_back(
2771 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2772
2773 Parser.Lex(); // Eat the slash.
2774
2775 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002776 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002777 if (Pred != "z" && Pred != "m") {
2778 Error(getLoc(), "expecting 'm' or 'z' predication");
2779 return MatchOperand_ParseFail;
2780 }
2781
2782 // Add zero/merge token.
2783 const char *ZM = Pred == "z" ? "z" : "m";
2784 Operands.push_back(
2785 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2786
2787 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002788 return MatchOperand_Success;
2789}
2790
Tim Northover3b0846e2014-05-24 12:50:23 +00002791/// parseRegister - Parse a non-vector register operand.
2792bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2793 SMLoc S = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00002794 // Try for a vector (neon) register.
2795 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002796 return false;
2797
2798 // Try for a scalar register.
2799 int64_t Reg = tryParseRegister();
2800 if (Reg == -1)
2801 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002802 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2803 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002804
Tim Northover3b0846e2014-05-24 12:50:23 +00002805 return false;
2806}
2807
2808bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002809 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002810 bool HasELFModifier = false;
2811 AArch64MCExpr::VariantKind RefKind;
2812
Nirav Davee833c6c2016-11-08 18:31:04 +00002813 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002814 HasELFModifier = true;
2815
Nirav Davee833c6c2016-11-08 18:31:04 +00002816 if (Parser.getTok().isNot(AsmToken::Identifier))
2817 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002818
2819 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2820 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2821 .Case("lo12", AArch64MCExpr::VK_LO12)
2822 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2823 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2824 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2825 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2826 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2827 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2828 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2829 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2830 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2831 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2832 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2833 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2834 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2835 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2836 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2837 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2838 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2839 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2840 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2841 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2842 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2843 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2844 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2845 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2846 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2847 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2848 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2849 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2850 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2851 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2852 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2853 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2854 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2855 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002856 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2857 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002858 .Default(AArch64MCExpr::VK_INVALID);
2859
Nirav Davee833c6c2016-11-08 18:31:04 +00002860 if (RefKind == AArch64MCExpr::VK_INVALID)
2861 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002862
2863 Parser.Lex(); // Eat identifier
2864
Nirav Davee833c6c2016-11-08 18:31:04 +00002865 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002866 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002867 }
2868
2869 if (getParser().parseExpression(ImmVal))
2870 return true;
2871
2872 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002873 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002874
2875 return false;
2876}
2877
Sander de Smalen650234b2018-04-12 11:40:52 +00002878template <RegKind VectorKind>
2879OperandMatchResultTy
2880AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
2881 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002882 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00002883 if (!Parser.getTok().is(AsmToken::LCurly))
2884 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002885
2886 // Wrapper around parse function
Sander de Smalen650234b2018-04-12 11:40:52 +00002887 auto ParseVector = [this, &Parser](int &Reg, StringRef &Kind, SMLoc Loc,
2888 bool NoMatchIsError) {
2889 auto RegTok = Parser.getTok();
2890 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
2891 if (ParseRes == MatchOperand_Success) {
Sander de Smalen73937b72018-04-11 07:36:10 +00002892 if (parseVectorKind(Kind, RegKind::NeonVector))
Sander de Smalen650234b2018-04-12 11:40:52 +00002893 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002894 llvm_unreachable("Expected a valid vector kind");
2895 }
2896
Sander de Smalen650234b2018-04-12 11:40:52 +00002897 if (RegTok.isNot(AsmToken::Identifier) ||
2898 ParseRes == MatchOperand_ParseFail ||
2899 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
2900 Error(Loc, "vector register expected");
2901 return MatchOperand_ParseFail;
2902 }
2903
2904 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002905 };
2906
Tim Northover3b0846e2014-05-24 12:50:23 +00002907 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00002908 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00002909 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00002910
Tim Northover3b0846e2014-05-24 12:50:23 +00002911 StringRef Kind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002912 int FirstReg = -1;
Sander de Smalen650234b2018-04-12 11:40:52 +00002913 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
2914
2915 // Put back the original left bracket if there was no match, so that
2916 // different types of list-operands can be matched (e.g. SVE, Neon).
2917 if (ParseRes == MatchOperand_NoMatch)
2918 Parser.getLexer().UnLex(LCurly);
2919
2920 if (ParseRes != MatchOperand_Success)
2921 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002922
Tim Northover3b0846e2014-05-24 12:50:23 +00002923 int64_t PrevReg = FirstReg;
2924 unsigned Count = 1;
2925
Nirav Davee833c6c2016-11-08 18:31:04 +00002926 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002927 SMLoc Loc = getLoc();
2928 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002929
2930 int Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002931 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2932 if (ParseRes != MatchOperand_Success)
2933 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002934
Tim Northover3b0846e2014-05-24 12:50:23 +00002935 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002936 if (Kind != NextKind) {
2937 Error(Loc, "mismatched register size suffix");
2938 return MatchOperand_ParseFail;
2939 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002940
2941 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2942
2943 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002944 Error(Loc, "invalid number of vectors");
2945 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002946 }
2947
2948 Count += Space;
2949 }
2950 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002951 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002952 SMLoc Loc = getLoc();
2953 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002954 int Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002955 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2956 if (ParseRes != MatchOperand_Success)
2957 return ParseRes;
2958
Tim Northover3b0846e2014-05-24 12:50:23 +00002959 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002960 if (Kind != NextKind) {
2961 Error(Loc, "mismatched register size suffix");
2962 return MatchOperand_ParseFail;
2963 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002964
2965 // Registers must be incremental (with wraparound at 31)
2966 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00002967 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
2968 Error(Loc, "registers must be sequential");
2969 return MatchOperand_ParseFail;
2970 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002971
2972 PrevReg = Reg;
2973 ++Count;
2974 }
2975 }
2976
Nirav Davee833c6c2016-11-08 18:31:04 +00002977 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00002978 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002979
Sander de Smalen650234b2018-04-12 11:40:52 +00002980 if (Count > 4) {
2981 Error(S, "invalid number of vectors");
2982 return MatchOperand_ParseFail;
2983 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002984
2985 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00002986 unsigned ElementWidth = 0;
2987 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002988 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00002989 std::tie(NumElements, ElementWidth) = *VK;
2990 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002991
2992 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00002993 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
2994 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002995
Sander de Smalen650234b2018-04-12 11:40:52 +00002996 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002997}
2998
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002999/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3000bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003001 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3002 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003003 return true;
3004
3005 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3006}
3007
Alex Bradbury58eba092016-11-01 16:32:05 +00003008OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003009AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003010 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003011 const AsmToken &Tok = Parser.getTok();
3012 if (!Tok.is(AsmToken::Identifier))
3013 return MatchOperand_NoMatch;
3014
Florian Hahnc4422242017-11-07 13:07:50 +00003015 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00003016
3017 MCContext &Ctx = getContext();
3018 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
3019 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
3020 return MatchOperand_NoMatch;
3021
3022 SMLoc S = getLoc();
3023 Parser.Lex(); // Eat register
3024
Nirav Davee833c6c2016-11-08 18:31:04 +00003025 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003026 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003027 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003028 return MatchOperand_Success;
3029 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003030
Nirav Davee833c6c2016-11-08 18:31:04 +00003031 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003032
3033 if (Parser.getTok().isNot(AsmToken::Integer)) {
3034 Error(getLoc(), "index must be absent or #0");
3035 return MatchOperand_ParseFail;
3036 }
3037
3038 const MCExpr *ImmVal;
3039 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3040 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3041 Error(getLoc(), "index must be absent or #0");
3042 return MatchOperand_ParseFail;
3043 }
3044
3045 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003046 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003047 return MatchOperand_Success;
3048}
3049
3050/// parseOperand - Parse a arm instruction operand. For now this parses the
3051/// operand regardless of the mnemonic.
3052bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3053 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003054 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003055
3056 OperandMatchResultTy ResTy =
3057 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3058
Tim Northover3b0846e2014-05-24 12:50:23 +00003059 // Check if the current operand has a custom associated parser, if so, try to
3060 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003061 if (ResTy == MatchOperand_Success)
3062 return false;
3063 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3064 // there was a match, but an error occurred, in which case, just return that
3065 // the operand parsing failed.
3066 if (ResTy == MatchOperand_ParseFail)
3067 return true;
3068
3069 // Nothing custom, so do general case parsing.
3070 SMLoc S, E;
3071 switch (getLexer().getKind()) {
3072 default: {
3073 SMLoc S = getLoc();
3074 const MCExpr *Expr;
3075 if (parseSymbolicImmVal(Expr))
3076 return Error(S, "invalid operand");
3077
3078 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3079 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3080 return false;
3081 }
3082 case AsmToken::LBrac: {
3083 SMLoc Loc = Parser.getTok().getLoc();
3084 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3085 getContext()));
3086 Parser.Lex(); // Eat '['
3087
3088 // There's no comma after a '[', so we can parse the next operand
3089 // immediately.
3090 return parseOperand(Operands, false, false);
3091 }
3092 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003093 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003094 case AsmToken::Identifier: {
3095 // If we're expecting a Condition Code operand, then just parse that.
3096 if (isCondCode)
3097 return parseCondCode(Operands, invertCondCode);
3098
3099 // If it's a register name, parse it.
3100 if (!parseRegister(Operands))
3101 return false;
3102
3103 // This could be an optional "shift" or "extend" operand.
3104 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3105 // We can only continue if no tokens were eaten.
3106 if (GotShift != MatchOperand_NoMatch)
3107 return GotShift;
3108
3109 // This was not a register so parse other operands that start with an
3110 // identifier (like labels) as expressions and create them as immediates.
3111 const MCExpr *IdVal;
3112 S = getLoc();
3113 if (getParser().parseExpression(IdVal))
3114 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003115 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3116 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3117 return false;
3118 }
3119 case AsmToken::Integer:
3120 case AsmToken::Real:
3121 case AsmToken::Hash: {
3122 // #42 -> immediate.
3123 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003124
3125 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003126
3127 // Parse a negative sign
3128 bool isNegative = false;
3129 if (Parser.getTok().is(AsmToken::Minus)) {
3130 isNegative = true;
3131 // We need to consume this token only when we have a Real, otherwise
3132 // we let parseSymbolicImmVal take care of it
3133 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3134 Parser.Lex();
3135 }
3136
3137 // The only Real that should come through here is a literal #0.0 for
3138 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3139 // so convert the value.
3140 const AsmToken &Tok = Parser.getTok();
3141 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003142 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003143 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3144 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3145 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3146 Mnemonic != "fcmlt")
3147 return TokError("unexpected floating point literal");
3148 else if (IntVal != 0 || isNegative)
3149 return TokError("expected floating-point constant #0.0");
3150 Parser.Lex(); // Eat the token.
3151
3152 Operands.push_back(
3153 AArch64Operand::CreateToken("#0", false, S, getContext()));
3154 Operands.push_back(
3155 AArch64Operand::CreateToken(".0", false, S, getContext()));
3156 return false;
3157 }
3158
3159 const MCExpr *ImmVal;
3160 if (parseSymbolicImmVal(ImmVal))
3161 return true;
3162
3163 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3164 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3165 return false;
3166 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003167 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003168 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003169 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003170 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003171 Parser.Lex(); // Eat '='
3172 const MCExpr *SubExprVal;
3173 if (getParser().parseExpression(SubExprVal))
3174 return true;
3175
David Peixottoae5ba762014-07-18 16:05:14 +00003176 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003177 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003178 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003179
3180 bool IsXReg =
3181 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3182 Operands[1]->getReg());
3183
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003184 MCContext& Ctx = getContext();
3185 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3186 // 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 +00003187 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003188 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3189 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3190 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3191 ShiftAmt += 16;
3192 Imm >>= 16;
3193 }
3194 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3195 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3196 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003197 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003198 if (ShiftAmt)
3199 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3200 ShiftAmt, true, S, E, Ctx));
3201 return false;
3202 }
David Peixottoae5ba762014-07-18 16:05:14 +00003203 APInt Simm = APInt(64, Imm << ShiftAmt);
3204 // check if the immediate is an unsigned or signed 32-bit int for W regs
3205 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3206 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003207 }
3208 // 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 +00003209 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003210 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003211 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3212 return false;
3213 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003214 }
3215}
3216
3217/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3218/// operands.
3219bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3220 StringRef Name, SMLoc NameLoc,
3221 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003222 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003223 Name = StringSwitch<StringRef>(Name.lower())
3224 .Case("beq", "b.eq")
3225 .Case("bne", "b.ne")
3226 .Case("bhs", "b.hs")
3227 .Case("bcs", "b.cs")
3228 .Case("blo", "b.lo")
3229 .Case("bcc", "b.cc")
3230 .Case("bmi", "b.mi")
3231 .Case("bpl", "b.pl")
3232 .Case("bvs", "b.vs")
3233 .Case("bvc", "b.vc")
3234 .Case("bhi", "b.hi")
3235 .Case("bls", "b.ls")
3236 .Case("bge", "b.ge")
3237 .Case("blt", "b.lt")
3238 .Case("bgt", "b.gt")
3239 .Case("ble", "b.le")
3240 .Case("bal", "b.al")
3241 .Case("bnv", "b.nv")
3242 .Default(Name);
3243
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003244 // First check for the AArch64-specific .req directive.
3245 if (Parser.getTok().is(AsmToken::Identifier) &&
3246 Parser.getTok().getIdentifier() == ".req") {
3247 parseDirectiveReq(Name, NameLoc);
3248 // We always return 'error' for this, as we're done with this
3249 // statement and don't need to match the 'instruction."
3250 return true;
3251 }
3252
Tim Northover3b0846e2014-05-24 12:50:23 +00003253 // Create the leading tokens for the mnemonic, split by '.' characters.
3254 size_t Start = 0, Next = Name.find('.');
3255 StringRef Head = Name.slice(Start, Next);
3256
3257 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003258 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3259 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003260
3261 Operands.push_back(
3262 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3263 Mnemonic = Head;
3264
3265 // Handle condition codes for a branch mnemonic
3266 if (Head == "b" && Next != StringRef::npos) {
3267 Start = Next;
3268 Next = Name.find('.', Start + 1);
3269 Head = Name.slice(Start + 1, Next);
3270
3271 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3272 (Head.data() - Name.data()));
3273 AArch64CC::CondCode CC = parseCondCodeString(Head);
3274 if (CC == AArch64CC::Invalid)
3275 return Error(SuffixLoc, "invalid condition code");
3276 Operands.push_back(
3277 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3278 Operands.push_back(
3279 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3280 }
3281
3282 // Add the remaining tokens in the mnemonic.
3283 while (Next != StringRef::npos) {
3284 Start = Next;
3285 Next = Name.find('.', Start + 1);
3286 Head = Name.slice(Start, Next);
3287 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3288 (Head.data() - Name.data()) + 1);
3289 Operands.push_back(
3290 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3291 }
3292
3293 // Conditional compare instructions have a Condition Code operand, which needs
3294 // to be parsed and an immediate operand created.
3295 bool condCodeFourthOperand =
3296 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3297 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3298 Head == "csinc" || Head == "csinv" || Head == "csneg");
3299
3300 // These instructions are aliases to some of the conditional select
3301 // instructions. However, the condition code is inverted in the aliased
3302 // instruction.
3303 //
3304 // FIXME: Is this the correct way to handle these? Or should the parser
3305 // generate the aliased instructions directly?
3306 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3307 bool condCodeThirdOperand =
3308 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3309
3310 // Read the remaining operands.
3311 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3312 // Read the first operand.
3313 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003314 return true;
3315 }
3316
3317 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003318 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003319 // Parse and remember the operand.
3320 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3321 (N == 3 && condCodeThirdOperand) ||
3322 (N == 2 && condCodeSecondOperand),
3323 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003324 return true;
3325 }
3326
3327 // After successfully parsing some operands there are two special cases to
3328 // consider (i.e. notional operands not separated by commas). Both are due
3329 // to memory specifiers:
3330 // + An RBrac will end an address for load/store/prefetch
3331 // + An '!' will indicate a pre-indexed operation.
3332 //
3333 // It's someone else's responsibility to make sure these tokens are sane
3334 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003335
Nirav Davee833c6c2016-11-08 18:31:04 +00003336 SMLoc RLoc = Parser.getTok().getLoc();
3337 if (parseOptionalToken(AsmToken::RBrac))
3338 Operands.push_back(
3339 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3340 SMLoc ELoc = Parser.getTok().getLoc();
3341 if (parseOptionalToken(AsmToken::Exclaim))
3342 Operands.push_back(
3343 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003344
3345 ++N;
3346 }
3347 }
3348
Nirav Davee833c6c2016-11-08 18:31:04 +00003349 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3350 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003351
Tim Northover3b0846e2014-05-24 12:50:23 +00003352 return false;
3353}
3354
3355// FIXME: This entire function is a giant hack to provide us with decent
3356// operand range validation/diagnostics until TableGen/MC can be extended
3357// to support autogeneration of this kind of validation.
3358bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3359 SmallVectorImpl<SMLoc> &Loc) {
3360 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3361 // Check for indexed addressing modes w/ the base register being the
3362 // same as a destination/source register or pair load where
3363 // the Rt == Rt2. All of those are undefined behaviour.
3364 switch (Inst.getOpcode()) {
3365 case AArch64::LDPSWpre:
3366 case AArch64::LDPWpost:
3367 case AArch64::LDPWpre:
3368 case AArch64::LDPXpost:
3369 case AArch64::LDPXpre: {
3370 unsigned Rt = Inst.getOperand(1).getReg();
3371 unsigned Rt2 = Inst.getOperand(2).getReg();
3372 unsigned Rn = Inst.getOperand(3).getReg();
3373 if (RI->isSubRegisterEq(Rn, Rt))
3374 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3375 "is also a destination");
3376 if (RI->isSubRegisterEq(Rn, Rt2))
3377 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3378 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003379 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003380 }
3381 case AArch64::LDPDi:
3382 case AArch64::LDPQi:
3383 case AArch64::LDPSi:
3384 case AArch64::LDPSWi:
3385 case AArch64::LDPWi:
3386 case AArch64::LDPXi: {
3387 unsigned Rt = Inst.getOperand(0).getReg();
3388 unsigned Rt2 = Inst.getOperand(1).getReg();
3389 if (Rt == Rt2)
3390 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3391 break;
3392 }
3393 case AArch64::LDPDpost:
3394 case AArch64::LDPDpre:
3395 case AArch64::LDPQpost:
3396 case AArch64::LDPQpre:
3397 case AArch64::LDPSpost:
3398 case AArch64::LDPSpre:
3399 case AArch64::LDPSWpost: {
3400 unsigned Rt = Inst.getOperand(1).getReg();
3401 unsigned Rt2 = Inst.getOperand(2).getReg();
3402 if (Rt == Rt2)
3403 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3404 break;
3405 }
3406 case AArch64::STPDpost:
3407 case AArch64::STPDpre:
3408 case AArch64::STPQpost:
3409 case AArch64::STPQpre:
3410 case AArch64::STPSpost:
3411 case AArch64::STPSpre:
3412 case AArch64::STPWpost:
3413 case AArch64::STPWpre:
3414 case AArch64::STPXpost:
3415 case AArch64::STPXpre: {
3416 unsigned Rt = Inst.getOperand(1).getReg();
3417 unsigned Rt2 = Inst.getOperand(2).getReg();
3418 unsigned Rn = Inst.getOperand(3).getReg();
3419 if (RI->isSubRegisterEq(Rn, Rt))
3420 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3421 "is also a source");
3422 if (RI->isSubRegisterEq(Rn, Rt2))
3423 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3424 "is also a source");
3425 break;
3426 }
3427 case AArch64::LDRBBpre:
3428 case AArch64::LDRBpre:
3429 case AArch64::LDRHHpre:
3430 case AArch64::LDRHpre:
3431 case AArch64::LDRSBWpre:
3432 case AArch64::LDRSBXpre:
3433 case AArch64::LDRSHWpre:
3434 case AArch64::LDRSHXpre:
3435 case AArch64::LDRSWpre:
3436 case AArch64::LDRWpre:
3437 case AArch64::LDRXpre:
3438 case AArch64::LDRBBpost:
3439 case AArch64::LDRBpost:
3440 case AArch64::LDRHHpost:
3441 case AArch64::LDRHpost:
3442 case AArch64::LDRSBWpost:
3443 case AArch64::LDRSBXpost:
3444 case AArch64::LDRSHWpost:
3445 case AArch64::LDRSHXpost:
3446 case AArch64::LDRSWpost:
3447 case AArch64::LDRWpost:
3448 case AArch64::LDRXpost: {
3449 unsigned Rt = Inst.getOperand(1).getReg();
3450 unsigned Rn = Inst.getOperand(2).getReg();
3451 if (RI->isSubRegisterEq(Rn, Rt))
3452 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3453 "is also a source");
3454 break;
3455 }
3456 case AArch64::STRBBpost:
3457 case AArch64::STRBpost:
3458 case AArch64::STRHHpost:
3459 case AArch64::STRHpost:
3460 case AArch64::STRWpost:
3461 case AArch64::STRXpost:
3462 case AArch64::STRBBpre:
3463 case AArch64::STRBpre:
3464 case AArch64::STRHHpre:
3465 case AArch64::STRHpre:
3466 case AArch64::STRWpre:
3467 case AArch64::STRXpre: {
3468 unsigned Rt = Inst.getOperand(1).getReg();
3469 unsigned Rn = Inst.getOperand(2).getReg();
3470 if (RI->isSubRegisterEq(Rn, Rt))
3471 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3472 "is also a source");
3473 break;
3474 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003475 case AArch64::STXRB:
3476 case AArch64::STXRH:
3477 case AArch64::STXRW:
3478 case AArch64::STXRX:
3479 case AArch64::STLXRB:
3480 case AArch64::STLXRH:
3481 case AArch64::STLXRW:
3482 case AArch64::STLXRX: {
3483 unsigned Rs = Inst.getOperand(0).getReg();
3484 unsigned Rt = Inst.getOperand(1).getReg();
3485 unsigned Rn = Inst.getOperand(2).getReg();
3486 if (RI->isSubRegisterEq(Rt, Rs) ||
3487 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3488 return Error(Loc[0],
3489 "unpredictable STXR instruction, status is also a source");
3490 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003491 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003492 case AArch64::STXPW:
3493 case AArch64::STXPX:
3494 case AArch64::STLXPW:
3495 case AArch64::STLXPX: {
3496 unsigned Rs = Inst.getOperand(0).getReg();
3497 unsigned Rt1 = Inst.getOperand(1).getReg();
3498 unsigned Rt2 = Inst.getOperand(2).getReg();
3499 unsigned Rn = Inst.getOperand(3).getReg();
3500 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3501 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3502 return Error(Loc[0],
3503 "unpredictable STXP instruction, status is also a source");
3504 break;
3505 }
3506 }
3507
Tim Northover3b0846e2014-05-24 12:50:23 +00003508
3509 // Now check immediate ranges. Separate from the above as there is overlap
3510 // in the instructions being checked and this keeps the nested conditionals
3511 // to a minimum.
3512 switch (Inst.getOpcode()) {
3513 case AArch64::ADDSWri:
3514 case AArch64::ADDSXri:
3515 case AArch64::ADDWri:
3516 case AArch64::ADDXri:
3517 case AArch64::SUBSWri:
3518 case AArch64::SUBSXri:
3519 case AArch64::SUBWri:
3520 case AArch64::SUBXri: {
3521 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3522 // some slight duplication here.
3523 if (Inst.getOperand(2).isExpr()) {
3524 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3525 AArch64MCExpr::VariantKind ELFRefKind;
3526 MCSymbolRefExpr::VariantKind DarwinRefKind;
3527 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003528 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3529
3530 // Only allow these with ADDXri.
3531 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3532 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3533 Inst.getOpcode() == AArch64::ADDXri)
3534 return false;
3535
3536 // Only allow these with ADDXri/ADDWri
3537 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3538 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3539 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3540 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3541 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3542 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3543 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003544 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3545 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3546 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003547 (Inst.getOpcode() == AArch64::ADDXri ||
3548 Inst.getOpcode() == AArch64::ADDWri))
3549 return false;
3550
3551 // Don't allow symbol refs in the immediate field otherwise
3552 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3553 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3554 // 'cmp w0, 'borked')
3555 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003556 }
Diana Picusc93518d2016-10-11 09:17:47 +00003557 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003558 }
3559 return false;
3560 }
3561 default:
3562 return false;
3563 }
3564}
3565
Craig Topper05515562017-10-26 06:46:41 +00003566static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3567 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003568
3569bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3570 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003571 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003572 case Match_InvalidTiedOperand:
3573 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003574 case Match_MissingFeature:
3575 return Error(Loc,
3576 "instruction requires a CPU feature not currently enabled");
3577 case Match_InvalidOperand:
3578 return Error(Loc, "invalid operand for instruction");
3579 case Match_InvalidSuffix:
3580 return Error(Loc, "invalid type suffix for instruction");
3581 case Match_InvalidCondCode:
3582 return Error(Loc, "expected AArch64 condition code");
3583 case Match_AddSubRegExtendSmall:
3584 return Error(Loc,
3585 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3586 case Match_AddSubRegExtendLarge:
3587 return Error(Loc,
3588 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3589 case Match_AddSubSecondSource:
3590 return Error(Loc,
3591 "expected compatible register, symbol or integer in range [0, 4095]");
3592 case Match_LogicalSecondSource:
3593 return Error(Loc, "expected compatible register or logical immediate");
3594 case Match_InvalidMovImm32Shift:
3595 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3596 case Match_InvalidMovImm64Shift:
3597 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3598 case Match_AddSubRegShift32:
3599 return Error(Loc,
3600 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3601 case Match_AddSubRegShift64:
3602 return Error(Loc,
3603 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3604 case Match_InvalidFPImm:
3605 return Error(Loc,
3606 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003607 case Match_InvalidMemoryIndexedSImm6:
3608 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003609 case Match_InvalidMemoryIndexedSImm5:
3610 return Error(Loc, "index must be an integer in range [-16, 15].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003611 case Match_InvalidMemoryIndexedSImm9:
3612 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003613 case Match_InvalidMemoryIndexedSImm10:
3614 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003615 case Match_InvalidMemoryIndexed4SImm7:
3616 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3617 case Match_InvalidMemoryIndexed8SImm7:
3618 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3619 case Match_InvalidMemoryIndexed16SImm7:
3620 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3621 case Match_InvalidMemoryWExtend8:
3622 return Error(Loc,
3623 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3624 case Match_InvalidMemoryWExtend16:
3625 return Error(Loc,
3626 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3627 case Match_InvalidMemoryWExtend32:
3628 return Error(Loc,
3629 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3630 case Match_InvalidMemoryWExtend64:
3631 return Error(Loc,
3632 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3633 case Match_InvalidMemoryWExtend128:
3634 return Error(Loc,
3635 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3636 case Match_InvalidMemoryXExtend8:
3637 return Error(Loc,
3638 "expected 'lsl' or 'sxtx' with optional shift of #0");
3639 case Match_InvalidMemoryXExtend16:
3640 return Error(Loc,
3641 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3642 case Match_InvalidMemoryXExtend32:
3643 return Error(Loc,
3644 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3645 case Match_InvalidMemoryXExtend64:
3646 return Error(Loc,
3647 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3648 case Match_InvalidMemoryXExtend128:
3649 return Error(Loc,
3650 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3651 case Match_InvalidMemoryIndexed1:
3652 return Error(Loc, "index must be an integer in range [0, 4095].");
3653 case Match_InvalidMemoryIndexed2:
3654 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3655 case Match_InvalidMemoryIndexed4:
3656 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3657 case Match_InvalidMemoryIndexed8:
3658 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3659 case Match_InvalidMemoryIndexed16:
3660 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003661 case Match_InvalidImm0_1:
3662 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003663 case Match_InvalidImm0_7:
3664 return Error(Loc, "immediate must be an integer in range [0, 7].");
3665 case Match_InvalidImm0_15:
3666 return Error(Loc, "immediate must be an integer in range [0, 15].");
3667 case Match_InvalidImm0_31:
3668 return Error(Loc, "immediate must be an integer in range [0, 31].");
3669 case Match_InvalidImm0_63:
3670 return Error(Loc, "immediate must be an integer in range [0, 63].");
3671 case Match_InvalidImm0_127:
3672 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003673 case Match_InvalidImm0_255:
3674 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003675 case Match_InvalidImm0_65535:
3676 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3677 case Match_InvalidImm1_8:
3678 return Error(Loc, "immediate must be an integer in range [1, 8].");
3679 case Match_InvalidImm1_16:
3680 return Error(Loc, "immediate must be an integer in range [1, 16].");
3681 case Match_InvalidImm1_32:
3682 return Error(Loc, "immediate must be an integer in range [1, 32].");
3683 case Match_InvalidImm1_64:
3684 return Error(Loc, "immediate must be an integer in range [1, 64].");
3685 case Match_InvalidIndex1:
3686 return Error(Loc, "expected lane specifier '[1]'");
3687 case Match_InvalidIndexB:
3688 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3689 case Match_InvalidIndexH:
3690 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3691 case Match_InvalidIndexS:
3692 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3693 case Match_InvalidIndexD:
3694 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3695 case Match_InvalidLabel:
3696 return Error(Loc, "expected label or encodable integer pc offset");
3697 case Match_MRS:
3698 return Error(Loc, "expected readable system register");
3699 case Match_MSR:
3700 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003701 case Match_InvalidComplexRotationEven:
3702 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3703 case Match_InvalidComplexRotationOdd:
3704 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003705 case Match_MnemonicFail: {
3706 std::string Suggestion = AArch64MnemonicSpellCheck(
3707 ((AArch64Operand &)*Operands[0]).getToken(),
3708 ComputeAvailableFeatures(STI->getFeatureBits()));
3709 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3710 }
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003711 case Match_InvalidSVEPattern:
3712 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003713 case Match_InvalidSVEPredicateAnyReg:
3714 case Match_InvalidSVEPredicateBReg:
3715 case Match_InvalidSVEPredicateHReg:
3716 case Match_InvalidSVEPredicateSReg:
3717 case Match_InvalidSVEPredicateDReg:
3718 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003719 case Match_InvalidSVEPredicate3bAnyReg:
3720 case Match_InvalidSVEPredicate3bBReg:
3721 case Match_InvalidSVEPredicate3bHReg:
3722 case Match_InvalidSVEPredicate3bSReg:
3723 case Match_InvalidSVEPredicate3bDReg:
3724 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003725 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003726 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003727 }
3728}
3729
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003730static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003731
3732bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3733 OperandVector &Operands,
3734 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003735 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003736 bool MatchingInlineAsm) {
3737 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003738 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3739 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003740
David Blaikie960ea3f2014-06-08 16:18:35 +00003741 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003742 unsigned NumOperands = Operands.size();
3743
3744 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003745 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3746 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003747 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003748 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003749 if (Op3CE) {
3750 uint64_t Op3Val = Op3CE->getValue();
3751 uint64_t NewOp3Val = 0;
3752 uint64_t NewOp4Val = 0;
3753 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003754 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003755 NewOp3Val = (32 - Op3Val) & 0x1f;
3756 NewOp4Val = 31 - Op3Val;
3757 } else {
3758 NewOp3Val = (64 - Op3Val) & 0x3f;
3759 NewOp4Val = 63 - Op3Val;
3760 }
3761
Jim Grosbach13760bd2015-05-30 01:25:56 +00003762 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3763 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003764
3765 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003766 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003767 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003768 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3769 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3770 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003771 }
3772 }
Tim Northover03b99f62015-04-30 18:28:58 +00003773 } else if (NumOperands == 4 && Tok == "bfc") {
3774 // FIXME: Horrible hack to handle BFC->BFM alias.
3775 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3776 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3777 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3778
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003779 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003780 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3781 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3782
3783 if (LSBCE && WidthCE) {
3784 uint64_t LSB = LSBCE->getValue();
3785 uint64_t Width = WidthCE->getValue();
3786
3787 uint64_t RegWidth = 0;
3788 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3789 Op1.getReg()))
3790 RegWidth = 64;
3791 else
3792 RegWidth = 32;
3793
3794 if (LSB >= RegWidth)
3795 return Error(LSBOp.getStartLoc(),
3796 "expected integer in range [0, 31]");
3797 if (Width < 1 || Width > RegWidth)
3798 return Error(WidthOp.getStartLoc(),
3799 "expected integer in range [1, 32]");
3800
3801 uint64_t ImmR = 0;
3802 if (RegWidth == 32)
3803 ImmR = (32 - LSB) & 0x1f;
3804 else
3805 ImmR = (64 - LSB) & 0x3f;
3806
3807 uint64_t ImmS = Width - 1;
3808
3809 if (ImmR != 0 && ImmS >= ImmR)
3810 return Error(WidthOp.getStartLoc(),
3811 "requested insert overflows register");
3812
Jim Grosbach13760bd2015-05-30 01:25:56 +00003813 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3814 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003815 Operands[0] = AArch64Operand::CreateToken(
3816 "bfm", false, Op.getStartLoc(), getContext());
3817 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003818 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3819 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003820 Operands[3] = AArch64Operand::CreateImm(
3821 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3822 Operands.emplace_back(
3823 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3824 WidthOp.getEndLoc(), getContext()));
3825 }
3826 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003827 } else if (NumOperands == 5) {
3828 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3829 // UBFIZ -> UBFM aliases.
3830 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003831 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3832 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3833 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003834
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003835 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003836 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3837 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003838
3839 if (Op3CE && Op4CE) {
3840 uint64_t Op3Val = Op3CE->getValue();
3841 uint64_t Op4Val = Op4CE->getValue();
3842
3843 uint64_t RegWidth = 0;
3844 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003845 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003846 RegWidth = 64;
3847 else
3848 RegWidth = 32;
3849
3850 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003851 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003852 "expected integer in range [0, 31]");
3853 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003854 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003855 "expected integer in range [1, 32]");
3856
3857 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003858 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003859 NewOp3Val = (32 - Op3Val) & 0x1f;
3860 else
3861 NewOp3Val = (64 - Op3Val) & 0x3f;
3862
3863 uint64_t NewOp4Val = Op4Val - 1;
3864
3865 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003866 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003867 "requested insert overflows register");
3868
3869 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003870 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003871 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003872 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003873 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003874 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003875 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003876 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003877 if (Tok == "bfi")
3878 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003879 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003880 else if (Tok == "sbfiz")
3881 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003882 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003883 else if (Tok == "ubfiz")
3884 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003885 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003886 else
3887 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003888 }
3889 }
3890
3891 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3892 // UBFX -> UBFM aliases.
3893 } else if (NumOperands == 5 &&
3894 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003895 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3896 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3897 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003898
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003899 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003900 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3901 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003902
3903 if (Op3CE && Op4CE) {
3904 uint64_t Op3Val = Op3CE->getValue();
3905 uint64_t Op4Val = Op4CE->getValue();
3906
3907 uint64_t RegWidth = 0;
3908 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003909 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003910 RegWidth = 64;
3911 else
3912 RegWidth = 32;
3913
3914 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003915 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003916 "expected integer in range [0, 31]");
3917 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003918 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003919 "expected integer in range [1, 32]");
3920
3921 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3922
3923 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003924 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003925 "requested extract overflows register");
3926
3927 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003928 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003929 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003930 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003931 if (Tok == "bfxil")
3932 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003933 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003934 else if (Tok == "sbfx")
3935 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003936 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003937 else if (Tok == "ubfx")
3938 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003939 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003940 else
3941 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003942 }
3943 }
3944 }
3945 }
Tim Northover9097a072017-12-18 10:36:00 +00003946
3947 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
3948 // instruction for FP registers correctly in some rare circumstances. Convert
3949 // it to a safe instruction and warn (because silently changing someone's
3950 // assembly is rude).
3951 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
3952 NumOperands == 4 && Tok == "movi") {
3953 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3954 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3955 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3956 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
3957 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
3958 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
3959 if (Suffix.lower() == ".2d" &&
3960 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
3961 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
3962 " correctly on this CPU, converting to equivalent movi.16b");
3963 // Switch the suffix to .16b.
3964 unsigned Idx = Op1.isToken() ? 1 : 2;
3965 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
3966 getContext());
3967 }
3968 }
3969 }
3970
Tim Northover3b0846e2014-05-24 12:50:23 +00003971 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3972 // InstAlias can't quite handle this since the reg classes aren't
3973 // subclasses.
3974 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3975 // The source register can be Wn here, but the matcher expects a
3976 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003977 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003978 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003979 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003980 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3981 Op.getStartLoc(), Op.getEndLoc(),
3982 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003983 }
3984 }
3985 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3986 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003987 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003988 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003989 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003990 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003991 // The source register can be Wn here, but the matcher expects a
3992 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003993 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003994 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003995 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003996 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3997 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003998 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003999 }
4000 }
4001 }
4002 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4003 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004004 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004005 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004006 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004007 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004008 // The source register can be Wn here, but the matcher expects a
4009 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004010 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004011 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004012 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004013 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4014 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004015 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004016 }
4017 }
4018 }
4019
Tim Northover3b0846e2014-05-24 12:50:23 +00004020 MCInst Inst;
4021 // First try to match against the secondary set of tables containing the
4022 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4023 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004024 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004025
4026 // If that fails, try against the alternate table containing long-form NEON:
4027 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004028 if (MatchResult != Match_Success) {
4029 // But first, save the short-form match result: we can use it in case the
4030 // long-form match also fails.
4031 auto ShortFormNEONErrorInfo = ErrorInfo;
4032 auto ShortFormNEONMatchResult = MatchResult;
4033
Tim Northover3b0846e2014-05-24 12:50:23 +00004034 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004035 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004036
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004037 // Now, both matches failed, and the long-form match failed on the mnemonic
4038 // suffix token operand. The short-form match failure is probably more
4039 // relevant: use it instead.
4040 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004041 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004042 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4043 MatchResult = ShortFormNEONMatchResult;
4044 ErrorInfo = ShortFormNEONErrorInfo;
4045 }
4046 }
4047
Tim Northover3b0846e2014-05-24 12:50:23 +00004048 switch (MatchResult) {
4049 case Match_Success: {
4050 // Perform range checking and other semantic validations
4051 SmallVector<SMLoc, 8> OperandLocs;
4052 NumOperands = Operands.size();
4053 for (unsigned i = 1; i < NumOperands; ++i)
4054 OperandLocs.push_back(Operands[i]->getStartLoc());
4055 if (validateInstruction(Inst, OperandLocs))
4056 return true;
4057
4058 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004059 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004060 return false;
4061 }
4062 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004063 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004064 // Special case the error message for the very common case where only
4065 // a single subtarget feature is missing (neon, e.g.).
4066 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004067 uint64_t Mask = 1;
4068 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4069 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004070 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004071 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004072 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004073 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004074 }
4075 return Error(IDLoc, Msg);
4076 }
4077 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004078 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004079 case Match_InvalidOperand: {
4080 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004081
Tim Northover26bb14e2014-08-18 11:49:42 +00004082 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004083 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004084 return Error(IDLoc, "too few operands for instruction",
4085 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004086
David Blaikie960ea3f2014-06-08 16:18:35 +00004087 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004088 if (ErrorLoc == SMLoc())
4089 ErrorLoc = IDLoc;
4090 }
4091 // If the match failed on a suffix token operand, tweak the diagnostic
4092 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004093 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4094 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004095 MatchResult = Match_InvalidSuffix;
4096
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004097 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004098 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004099 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004100 case Match_InvalidMemoryIndexed1:
4101 case Match_InvalidMemoryIndexed2:
4102 case Match_InvalidMemoryIndexed4:
4103 case Match_InvalidMemoryIndexed8:
4104 case Match_InvalidMemoryIndexed16:
4105 case Match_InvalidCondCode:
4106 case Match_AddSubRegExtendSmall:
4107 case Match_AddSubRegExtendLarge:
4108 case Match_AddSubSecondSource:
4109 case Match_LogicalSecondSource:
4110 case Match_AddSubRegShift32:
4111 case Match_AddSubRegShift64:
4112 case Match_InvalidMovImm32Shift:
4113 case Match_InvalidMovImm64Shift:
4114 case Match_InvalidFPImm:
4115 case Match_InvalidMemoryWExtend8:
4116 case Match_InvalidMemoryWExtend16:
4117 case Match_InvalidMemoryWExtend32:
4118 case Match_InvalidMemoryWExtend64:
4119 case Match_InvalidMemoryWExtend128:
4120 case Match_InvalidMemoryXExtend8:
4121 case Match_InvalidMemoryXExtend16:
4122 case Match_InvalidMemoryXExtend32:
4123 case Match_InvalidMemoryXExtend64:
4124 case Match_InvalidMemoryXExtend128:
Sander de Smalen909cf952018-01-19 15:22:00 +00004125 case Match_InvalidMemoryIndexedSImm6:
Tim Northover3b0846e2014-05-24 12:50:23 +00004126 case Match_InvalidMemoryIndexed4SImm7:
4127 case Match_InvalidMemoryIndexed8SImm7:
4128 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen30fda452018-04-10 07:01:53 +00004129 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004130 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004131 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004132 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004133 case Match_InvalidImm0_7:
4134 case Match_InvalidImm0_15:
4135 case Match_InvalidImm0_31:
4136 case Match_InvalidImm0_63:
4137 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004138 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004139 case Match_InvalidImm0_65535:
4140 case Match_InvalidImm1_8:
4141 case Match_InvalidImm1_16:
4142 case Match_InvalidImm1_32:
4143 case Match_InvalidImm1_64:
4144 case Match_InvalidIndex1:
4145 case Match_InvalidIndexB:
4146 case Match_InvalidIndexH:
4147 case Match_InvalidIndexS:
4148 case Match_InvalidIndexD:
4149 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004150 case Match_InvalidComplexRotationEven:
4151 case Match_InvalidComplexRotationOdd:
Sander de Smalencd6be962017-12-20 11:02:42 +00004152 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004153 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004154 case Match_InvalidSVEPredicateBReg:
4155 case Match_InvalidSVEPredicateHReg:
4156 case Match_InvalidSVEPredicateSReg:
4157 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004158 case Match_InvalidSVEPredicate3bAnyReg:
4159 case Match_InvalidSVEPredicate3bBReg:
4160 case Match_InvalidSVEPredicate3bHReg:
4161 case Match_InvalidSVEPredicate3bSReg:
4162 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004163 case Match_MSR:
4164 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004165 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004166 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004167 // Any time we get here, there's nothing fancy to do. Just get the
4168 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004169 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004170 if (ErrorLoc == SMLoc())
4171 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004172 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004173 }
4174 }
4175
4176 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004177}
4178
4179/// ParseDirective parses the arm specific directives
4180bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004181 const MCObjectFileInfo::Environment Format =
4182 getContext().getObjectFileInfo()->getObjectFileType();
4183 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4184 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004185
Tim Northover3b0846e2014-05-24 12:50:23 +00004186 StringRef IDVal = DirectiveID.getIdentifier();
4187 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004188 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004189 parseDirectiveArch(Loc);
4190 else if (IDVal == ".cpu")
4191 parseDirectiveCPU(Loc);
4192 else if (IDVal == ".hword")
4193 parseDirectiveWord(2, Loc);
4194 else if (IDVal == ".word")
4195 parseDirectiveWord(4, Loc);
4196 else if (IDVal == ".xword")
4197 parseDirectiveWord(8, Loc);
4198 else if (IDVal == ".tlsdesccall")
4199 parseDirectiveTLSDescCall(Loc);
4200 else if (IDVal == ".ltorg" || IDVal == ".pool")
4201 parseDirectiveLtorg(Loc);
4202 else if (IDVal == ".unreq")
4203 parseDirectiveUnreq(Loc);
4204 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004205 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004206 parseDirectiveInst(Loc);
4207 else
4208 return true;
4209 } else if (IDVal == MCLOHDirectiveName())
4210 parseDirectiveLOH(IDVal, Loc);
4211 else
4212 return true;
4213 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004214}
4215
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004216static const struct {
4217 const char *Name;
4218 const FeatureBitset Features;
4219} ExtensionMap[] = {
4220 { "crc", {AArch64::FeatureCRC} },
4221 { "crypto", {AArch64::FeatureCrypto} },
4222 { "fp", {AArch64::FeatureFPARMv8} },
4223 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004224 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004225 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004226
4227 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004228 { "pan", {} },
4229 { "lor", {} },
4230 { "rdma", {} },
4231 { "profile", {} },
4232};
4233
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004234/// parseDirectiveArch
4235/// ::= .arch token
4236bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4237 SMLoc ArchLoc = getLoc();
4238
4239 StringRef Arch, ExtensionString;
4240 std::tie(Arch, ExtensionString) =
4241 getParser().parseStringToEndOfStatement().trim().split('+');
4242
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004243 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4244 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004245 return Error(ArchLoc, "unknown arch name");
4246
4247 if (parseToken(AsmToken::EndOfStatement))
4248 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004249
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004250 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004251 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004252 AArch64::getArchFeatures(ID, AArch64Features);
4253 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4254 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004255
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004256 MCSubtargetInfo &STI = copySTI();
4257 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4258 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4259
4260 SmallVector<StringRef, 4> RequestedExtensions;
4261 if (!ExtensionString.empty())
4262 ExtensionString.split(RequestedExtensions, '+');
4263
4264 FeatureBitset Features = STI.getFeatureBits();
4265 for (auto Name : RequestedExtensions) {
4266 bool EnableFeature = true;
4267
4268 if (Name.startswith_lower("no")) {
4269 EnableFeature = false;
4270 Name = Name.substr(2);
4271 }
4272
4273 for (const auto &Extension : ExtensionMap) {
4274 if (Extension.Name != Name)
4275 continue;
4276
4277 if (Extension.Features.none())
4278 report_fatal_error("unsupported architectural extension: " + Name);
4279
4280 FeatureBitset ToggleFeatures = EnableFeature
4281 ? (~Features & Extension.Features)
4282 : ( Features & Extension.Features);
4283 uint64_t Features =
4284 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4285 setAvailableFeatures(Features);
4286 break;
4287 }
4288 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004289 return false;
4290}
4291
Tim Northover8b96c7e2017-05-15 19:42:15 +00004292static SMLoc incrementLoc(SMLoc L, int Offset) {
4293 return SMLoc::getFromPointer(L.getPointer() + Offset);
4294}
4295
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004296/// parseDirectiveCPU
4297/// ::= .cpu id
4298bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004299 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004300
4301 StringRef CPU, ExtensionString;
4302 std::tie(CPU, ExtensionString) =
4303 getParser().parseStringToEndOfStatement().trim().split('+');
4304
Nirav Davee833c6c2016-11-08 18:31:04 +00004305 if (parseToken(AsmToken::EndOfStatement))
4306 return true;
4307
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004308 SmallVector<StringRef, 4> RequestedExtensions;
4309 if (!ExtensionString.empty())
4310 ExtensionString.split(RequestedExtensions, '+');
4311
4312 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4313 // once that is tablegen'ed
4314 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004315 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004316 return false;
4317 }
4318
4319 MCSubtargetInfo &STI = copySTI();
4320 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004321 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004322
4323 FeatureBitset Features = STI.getFeatureBits();
4324 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004325 // Advance source location past '+'.
4326 CurLoc = incrementLoc(CurLoc, 1);
4327
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004328 bool EnableFeature = true;
4329
4330 if (Name.startswith_lower("no")) {
4331 EnableFeature = false;
4332 Name = Name.substr(2);
4333 }
4334
Tim Northover8b96c7e2017-05-15 19:42:15 +00004335 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004336 for (const auto &Extension : ExtensionMap) {
4337 if (Extension.Name != Name)
4338 continue;
4339
4340 if (Extension.Features.none())
4341 report_fatal_error("unsupported architectural extension: " + Name);
4342
4343 FeatureBitset ToggleFeatures = EnableFeature
4344 ? (~Features & Extension.Features)
4345 : ( Features & Extension.Features);
4346 uint64_t Features =
4347 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4348 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004349 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004350
4351 break;
4352 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004353
4354 if (!FoundExtension)
4355 Error(CurLoc, "unsupported architectural extension");
4356
4357 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004358 }
4359 return false;
4360}
4361
Tim Northover3b0846e2014-05-24 12:50:23 +00004362/// parseDirectiveWord
4363/// ::= .word [ expression (, expression)* ]
4364bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004365 auto parseOp = [&]() -> bool {
4366 const MCExpr *Value;
4367 if (getParser().parseExpression(Value))
4368 return true;
4369 getParser().getStreamer().EmitValue(Value, Size, L);
4370 return false;
4371 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004372
Nirav Davee833c6c2016-11-08 18:31:04 +00004373 if (parseMany(parseOp))
4374 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004375 return false;
4376}
4377
Chad Rosierdcd2a302014-10-22 20:35:57 +00004378/// parseDirectiveInst
4379/// ::= .inst opcode [, ...]
4380bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004381 if (getLexer().is(AsmToken::EndOfStatement))
4382 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004383
Nirav Davee833c6c2016-11-08 18:31:04 +00004384 auto parseOp = [&]() -> bool {
4385 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004386 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004387 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4388 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004389 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004390 if (check(!Value, L, "expected constant expression"))
4391 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004392 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004393 return false;
4394 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004395
Nirav Davee833c6c2016-11-08 18:31:04 +00004396 if (parseMany(parseOp))
4397 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004398 return false;
4399}
4400
Tim Northover3b0846e2014-05-24 12:50:23 +00004401// parseDirectiveTLSDescCall:
4402// ::= .tlsdesccall symbol
4403bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4404 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004405 if (check(getParser().parseIdentifier(Name), L,
4406 "expected symbol after directive") ||
4407 parseToken(AsmToken::EndOfStatement))
4408 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004409
Jim Grosbach6f482002015-05-18 18:43:14 +00004410 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004411 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4412 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004413
4414 MCInst Inst;
4415 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004416 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004417
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004418 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004419 return false;
4420}
4421
4422/// ::= .loh <lohName | lohId> label1, ..., labelN
4423/// The number of arguments depends on the loh identifier.
4424bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004425 MCLOHType Kind;
4426 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4427 if (getParser().getTok().isNot(AsmToken::Integer))
4428 return TokError("expected an identifier or a number in directive");
4429 // We successfully get a numeric value for the identifier.
4430 // Check if it is valid.
4431 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004432 if (Id <= -1U && !isValidMCLOHType(Id))
4433 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004434 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004435 } else {
4436 StringRef Name = getTok().getIdentifier();
4437 // We successfully parse an identifier.
4438 // Check if it is a recognized one.
4439 int Id = MCLOHNameToId(Name);
4440
4441 if (Id == -1)
4442 return TokError("invalid identifier in directive");
4443 Kind = (MCLOHType)Id;
4444 }
4445 // Consume the identifier.
4446 Lex();
4447 // Get the number of arguments of this LOH.
4448 int NbArgs = MCLOHIdToNbArgs(Kind);
4449
4450 assert(NbArgs != -1 && "Invalid number of arguments");
4451
4452 SmallVector<MCSymbol *, 3> Args;
4453 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4454 StringRef Name;
4455 if (getParser().parseIdentifier(Name))
4456 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004457 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004458
4459 if (Idx + 1 == NbArgs)
4460 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004461 if (parseToken(AsmToken::Comma,
4462 "unexpected token in '" + Twine(IDVal) + "' directive"))
4463 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004464 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004465 if (parseToken(AsmToken::EndOfStatement,
4466 "unexpected token in '" + Twine(IDVal) + "' directive"))
4467 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004468
4469 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4470 return false;
4471}
4472
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004473/// parseDirectiveLtorg
4474/// ::= .ltorg | .pool
4475bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004476 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4477 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004478 getTargetStreamer().emitCurrentConstantPool();
4479 return false;
4480}
4481
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004482/// parseDirectiveReq
4483/// ::= name .req registername
4484bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004485 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004486 Parser.Lex(); // Eat the '.req' token.
4487 SMLoc SRegLoc = getLoc();
Sander de Smalen8e607342017-11-15 15:44:43 +00004488 int RegNum = tryParseRegister();
Florian Hahnc4422242017-11-07 13:07:50 +00004489 RegKind RegisterKind = RegKind::Scalar;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004490
Sander de Smalen8e607342017-11-15 15:44:43 +00004491 if (RegNum == -1) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004492 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004493 RegisterKind = RegKind::NeonVector;
Sander de Smalen73937b72018-04-11 07:36:10 +00004494 OperandMatchResultTy Res =
4495 tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
4496
4497 if (Res == MatchOperand_ParseFail)
4498 return true;
4499
4500 if (Res == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004501 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004502 }
4503
Sander de Smalen8e607342017-11-15 15:44:43 +00004504 if (RegNum == -1) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004505 StringRef Kind;
4506 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen8e607342017-11-15 15:44:43 +00004507 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004508 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004509
4510 if (Res == MatchOperand_ParseFail)
4511 return true;
4512
4513 if (Res == MatchOperand_Success && !Kind.empty())
4514 return Error(SRegLoc,
4515 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004516 }
4517
Sander de Smalencd6be962017-12-20 11:02:42 +00004518 if (RegNum == -1) {
4519 StringRef Kind;
4520 RegisterKind = RegKind::SVEPredicateVector;
4521 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004522 tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004523
4524 if (Res == MatchOperand_ParseFail)
4525 return true;
4526
4527 if (Res == MatchOperand_Success && !Kind.empty())
4528 return Error(SRegLoc,
4529 "sve predicate register without type specifier expected");
4530 }
4531
Sander de Smalen8e607342017-11-15 15:44:43 +00004532 if (RegNum == -1)
Nirav Dave2364748a2016-09-16 18:30:20 +00004533 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004534
4535 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004536 if (parseToken(AsmToken::EndOfStatement,
4537 "unexpected input in .req directive"))
4538 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004539
Sander de Smalen8e607342017-11-15 15:44:43 +00004540 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004541 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004542 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4543
Nirav Dave2364748a2016-09-16 18:30:20 +00004544 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004545}
4546
4547/// parseDirectiveUneq
4548/// ::= .unreq registername
4549bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004550 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004551 if (getTok().isNot(AsmToken::Identifier))
4552 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004553 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4554 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004555 if (parseToken(AsmToken::EndOfStatement))
4556 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004557 return false;
4558}
4559
Tim Northover3b0846e2014-05-24 12:50:23 +00004560bool
4561AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4562 AArch64MCExpr::VariantKind &ELFRefKind,
4563 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4564 int64_t &Addend) {
4565 ELFRefKind = AArch64MCExpr::VK_INVALID;
4566 DarwinRefKind = MCSymbolRefExpr::VK_None;
4567 Addend = 0;
4568
4569 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4570 ELFRefKind = AE->getKind();
4571 Expr = AE->getSubExpr();
4572 }
4573
4574 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4575 if (SE) {
4576 // It's a simple symbol reference with no addend.
4577 DarwinRefKind = SE->getKind();
4578 return true;
4579 }
4580
4581 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4582 if (!BE)
4583 return false;
4584
4585 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4586 if (!SE)
4587 return false;
4588 DarwinRefKind = SE->getKind();
4589
4590 if (BE->getOpcode() != MCBinaryExpr::Add &&
4591 BE->getOpcode() != MCBinaryExpr::Sub)
4592 return false;
4593
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004594 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004595 // on here than we can deal with.
4596 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4597 if (!AddendExpr)
4598 return false;
4599
4600 Addend = AddendExpr->getValue();
4601 if (BE->getOpcode() == MCBinaryExpr::Sub)
4602 Addend = -Addend;
4603
4604 // It's some symbol reference + a constant addend, but really
4605 // shouldn't use both Darwin and ELF syntax.
4606 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4607 DarwinRefKind == MCSymbolRefExpr::VK_None;
4608}
4609
4610/// Force static initialization.
4611extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004612 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4613 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4614 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004615}
4616
4617#define GET_REGISTER_MATCHER
4618#define GET_SUBTARGET_FEATURE_NAME
4619#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004620#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004621#include "AArch64GenAsmMatcher.inc"
4622
4623// Define this matcher function after the auto-generated include so we
4624// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004625unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004626 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004627 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004628 // If the kind is a token for a literal immediate, check if our asm
4629 // operand matches. This is for InstAliases which have a fixed-value
4630 // immediate in the syntax.
4631 int64_t ExpectedVal;
4632 switch (Kind) {
4633 default:
4634 return Match_InvalidOperand;
4635 case MCK__35_0:
4636 ExpectedVal = 0;
4637 break;
4638 case MCK__35_1:
4639 ExpectedVal = 1;
4640 break;
4641 case MCK__35_12:
4642 ExpectedVal = 12;
4643 break;
4644 case MCK__35_16:
4645 ExpectedVal = 16;
4646 break;
4647 case MCK__35_2:
4648 ExpectedVal = 2;
4649 break;
4650 case MCK__35_24:
4651 ExpectedVal = 24;
4652 break;
4653 case MCK__35_3:
4654 ExpectedVal = 3;
4655 break;
4656 case MCK__35_32:
4657 ExpectedVal = 32;
4658 break;
4659 case MCK__35_4:
4660 ExpectedVal = 4;
4661 break;
4662 case MCK__35_48:
4663 ExpectedVal = 48;
4664 break;
4665 case MCK__35_6:
4666 ExpectedVal = 6;
4667 break;
4668 case MCK__35_64:
4669 ExpectedVal = 64;
4670 break;
4671 case MCK__35_8:
4672 ExpectedVal = 8;
4673 break;
4674 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004675 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004676 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004677 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004678 if (!CE)
4679 return Match_InvalidOperand;
4680 if (CE->getValue() == ExpectedVal)
4681 return Match_Success;
4682 return Match_InvalidOperand;
4683}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004684
Alex Bradbury58eba092016-11-01 16:32:05 +00004685OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004686AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4687
4688 SMLoc S = getLoc();
4689
4690 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4691 Error(S, "expected register");
4692 return MatchOperand_ParseFail;
4693 }
4694
4695 int FirstReg = tryParseRegister();
4696 if (FirstReg == -1) {
4697 return MatchOperand_ParseFail;
4698 }
4699 const MCRegisterClass &WRegClass =
4700 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4701 const MCRegisterClass &XRegClass =
4702 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4703
4704 bool isXReg = XRegClass.contains(FirstReg),
4705 isWReg = WRegClass.contains(FirstReg);
4706 if (!isXReg && !isWReg) {
4707 Error(S, "expected first even register of a "
4708 "consecutive same-size even/odd register pair");
4709 return MatchOperand_ParseFail;
4710 }
4711
4712 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4713 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4714
4715 if (FirstEncoding & 0x1) {
4716 Error(S, "expected first even register of a "
4717 "consecutive same-size even/odd register pair");
4718 return MatchOperand_ParseFail;
4719 }
4720
4721 SMLoc M = getLoc();
4722 if (getParser().getTok().isNot(AsmToken::Comma)) {
4723 Error(M, "expected comma");
4724 return MatchOperand_ParseFail;
4725 }
4726 // Eat the comma
4727 getParser().Lex();
4728
4729 SMLoc E = getLoc();
4730 int SecondReg = tryParseRegister();
4731 if (SecondReg ==-1) {
4732 return MatchOperand_ParseFail;
4733 }
4734
Eugene Zelenko049b0172017-01-06 00:30:53 +00004735 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004736 (isXReg && !XRegClass.contains(SecondReg)) ||
4737 (isWReg && !WRegClass.contains(SecondReg))) {
4738 Error(E,"expected second odd register of a "
4739 "consecutive same-size even/odd register pair");
4740 return MatchOperand_ParseFail;
4741 }
Joel Jones504bf332016-10-24 13:37:13 +00004742
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004743 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004744 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004745 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4746 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4747 } else {
4748 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4749 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4750 }
4751
Florian Hahnc4422242017-11-07 13:07:50 +00004752 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4753 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004754
4755 return MatchOperand_Success;
4756}
Florian Hahn91f11e52017-11-07 16:45:48 +00004757
4758template <bool ParseSuffix>
4759OperandMatchResultTy
4760AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004761 const SMLoc S = getLoc();
4762 // Check for a SVE vector register specifier first.
Sander de Smalen8e607342017-11-15 15:44:43 +00004763 int RegNum = -1;
Florian Hahn91f11e52017-11-07 16:45:48 +00004764 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004765
Sander de Smalen8e607342017-11-15 15:44:43 +00004766 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004767 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004768
4769 if (Res != MatchOperand_Success)
4770 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004771
4772 if (ParseSuffix && Kind.empty())
4773 return MatchOperand_NoMatch;
4774
Sander de Smalen73937b72018-04-11 07:36:10 +00004775 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
4776 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00004777 return MatchOperand_NoMatch;
4778
Sander de Smalen73937b72018-04-11 07:36:10 +00004779 unsigned ElementWidth = KindRes->second;
4780 Operands.push_back(AArch64Operand::CreateVectorReg(
4781 RegNum, RegKind::SVEDataVector, ElementWidth, S, S,
4782 getContext()));
Florian Hahn91f11e52017-11-07 16:45:48 +00004783
4784 return MatchOperand_Success;
4785}
Sander de Smalen245e0e62018-01-22 10:46:00 +00004786
4787OperandMatchResultTy
4788AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
4789 MCAsmParser &Parser = getParser();
4790
4791 SMLoc SS = getLoc();
4792 const AsmToken &TokE = Parser.getTok();
4793 bool IsHash = TokE.is(AsmToken::Hash);
4794
4795 if (!IsHash && TokE.isNot(AsmToken::Identifier))
4796 return MatchOperand_NoMatch;
4797
4798 int64_t Pattern;
4799 if (IsHash) {
4800 Parser.Lex(); // Eat hash
4801
4802 // Parse the immediate operand.
4803 const MCExpr *ImmVal;
4804 SS = getLoc();
4805 if (Parser.parseExpression(ImmVal))
4806 return MatchOperand_ParseFail;
4807
4808 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4809 if (!MCE)
4810 return MatchOperand_ParseFail;
4811
4812 Pattern = MCE->getValue();
4813 } else {
4814 // Parse the pattern
4815 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
4816 if (!Pat)
4817 return MatchOperand_NoMatch;
4818
4819 Parser.Lex();
4820 Pattern = Pat->Encoding;
4821 assert(Pattern >= 0 && Pattern < 32);
4822 }
4823
4824 Operands.push_back(
4825 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
4826 SS, getLoc(), getContext()));
4827
4828 return MatchOperand_Success;
4829}