blob: 17f038e2a654798c3df796efb95a0c7f13ff738a [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/AArch64AddressingModes.h"
11#include "MCTargetDesc/AArch64MCExpr.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000012#include "MCTargetDesc/AArch64MCTargetDesc.h"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000013#include "MCTargetDesc/AArch64TargetStreamer.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000014#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000015#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000016#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000017#include "llvm/ADT/ArrayRef.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000018#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "llvm/ADT/SmallVector.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000020#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000021#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000023#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000025#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000028#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000029#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000030#include "llvm/MC/MCParser/MCAsmLexer.h"
31#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000032#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000033#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000034#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000035#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSubtargetInfo.h"
38#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000039#include "llvm/MC/MCTargetOptions.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000043#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000044#include "llvm/Support/MathExtras.h"
45#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000046#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000047#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000049#include <cassert>
50#include <cctype>
51#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000052#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000053#include <string>
54#include <tuple>
55#include <utility>
56#include <vector>
57
Tim Northover3b0846e2014-05-24 12:50:23 +000058using namespace llvm;
59
60namespace {
61
Sander de Smalencd6be962017-12-20 11:02:42 +000062enum class RegKind {
63 Scalar,
64 NeonVector,
65 SVEDataVector,
66 SVEPredicateVector
67};
Florian Hahnc4422242017-11-07 13:07:50 +000068
Tim Northover3b0846e2014-05-24 12:50:23 +000069class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000070private:
71 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000072
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000073 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000074 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000075
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000076 AArch64TargetStreamer &getTargetStreamer() {
77 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
78 return static_cast<AArch64TargetStreamer &>(TS);
79 }
80
Rafael Espindola961d4692014-11-11 05:18:41 +000081 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000082
83 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +000084 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +000085 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
86 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +000087 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +000088 int tryParseRegister();
Tim Northover3b0846e2014-05-24 12:50:23 +000089 bool parseRegister(OperandVector &Operands);
90 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
Sander de Smalenc88f9a12018-04-11 14:10:37 +000091 bool parseNeonVectorList(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000092 bool parseOperand(OperandVector &Operands, bool isCondCode,
93 bool invertCondCode);
94
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +000095 bool showMatchError(SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000096
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000097 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000098 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +000099 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +0000100 bool parseDirectiveInst(SMLoc L);
101
Tim Northover3b0846e2014-05-24 12:50:23 +0000102 bool parseDirectiveTLSDescCall(SMLoc L);
103
104 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000105 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000106
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000107 bool parseDirectiveReq(StringRef Name, SMLoc L);
108 bool parseDirectiveUnreq(SMLoc L);
109
Tim Northover3b0846e2014-05-24 12:50:23 +0000110 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
111 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
112 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000113 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000114 bool MatchingInlineAsm) override;
115/// @name Auto-generated Match Functions
116/// {
117
118#define GET_ASSEMBLER_HEADER
119#include "AArch64GenAsmMatcher.inc"
120
121 /// }
122
Sander de Smalen73937b72018-04-11 07:36:10 +0000123 OperandMatchResultTy tryParseVectorRegister(int &Reg, StringRef &Kind,
124 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000125 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
126 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
127 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
128 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
129 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
130 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000131 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000132 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
133 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
134 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
135 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
136 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000137 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000138 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000139 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Florian Hahn91f11e52017-11-07 16:45:48 +0000140 template <bool ParseSuffix>
141 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000142 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000143 template <RegKind VectorKind>
144 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
145 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000146 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000147
148public:
149 enum AArch64MatchResultTy {
150 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
151#define GET_OPERAND_DIAGNOSTIC_TYPES
152#include "AArch64GenAsmMatcher.inc"
153 };
Joel Jones504bf332016-10-24 13:37:13 +0000154 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000155
Akira Hatanakab11ef082015-11-14 06:35:56 +0000156 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000157 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000158 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000159 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000160 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000161 MCStreamer &S = getParser().getStreamer();
162 if (S.getTargetStreamer() == nullptr)
163 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000164
165 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000166 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000167 }
168
169 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
170 SMLoc NameLoc, OperandVector &Operands) override;
171 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
172 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000173 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000174 unsigned Kind) override;
175
176 static bool classifySymbolRef(const MCExpr *Expr,
177 AArch64MCExpr::VariantKind &ELFRefKind,
178 MCSymbolRefExpr::VariantKind &DarwinRefKind,
179 int64_t &Addend);
180};
Tim Northover3b0846e2014-05-24 12:50:23 +0000181
182/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
183/// instruction.
184class AArch64Operand : public MCParsedAsmOperand {
185private:
186 enum KindTy {
187 k_Immediate,
188 k_ShiftedImm,
189 k_CondCode,
190 k_Register,
191 k_VectorList,
192 k_VectorIndex,
193 k_Token,
194 k_SysReg,
195 k_SysCR,
196 k_Prefetch,
197 k_ShiftExtend,
198 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000199 k_Barrier,
200 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000201 } Kind;
202
203 SMLoc StartLoc, EndLoc;
204
205 struct TokOp {
206 const char *Data;
207 unsigned Length;
208 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
209 };
210
211 struct RegOp {
212 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000213 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000214
215 int ElementWidth;
Tim Northover3b0846e2014-05-24 12:50:23 +0000216 };
217
218 struct VectorListOp {
219 unsigned RegNum;
220 unsigned Count;
221 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000222 unsigned ElementWidth;
223 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000224 };
225
226 struct VectorIndexOp {
227 unsigned Val;
228 };
229
230 struct ImmOp {
231 const MCExpr *Val;
232 };
233
234 struct ShiftedImmOp {
235 const MCExpr *Val;
236 unsigned ShiftAmount;
237 };
238
239 struct CondCodeOp {
240 AArch64CC::CondCode Code;
241 };
242
243 struct FPImmOp {
244 unsigned Val; // Encoded 8-bit representation.
245 };
246
247 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000248 const char *Data;
249 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000250 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000251 };
252
253 struct SysRegOp {
254 const char *Data;
255 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000256 uint32_t MRSReg;
257 uint32_t MSRReg;
258 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000259 };
260
261 struct SysCRImmOp {
262 unsigned Val;
263 };
264
265 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000266 const char *Data;
267 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000268 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000269 };
270
Oliver Stannarda34e4702015-12-01 10:48:51 +0000271 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000272 const char *Data;
273 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000274 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000275 };
276
Tim Northover3b0846e2014-05-24 12:50:23 +0000277 struct ShiftExtendOp {
278 AArch64_AM::ShiftExtendType Type;
279 unsigned Amount;
280 bool HasExplicitAmount;
281 };
282
283 struct ExtendOp {
284 unsigned Val;
285 };
286
287 union {
288 struct TokOp Tok;
289 struct RegOp Reg;
290 struct VectorListOp VectorList;
291 struct VectorIndexOp VectorIndex;
292 struct ImmOp Imm;
293 struct ShiftedImmOp ShiftedImm;
294 struct CondCodeOp CondCode;
295 struct FPImmOp FPImm;
296 struct BarrierOp Barrier;
297 struct SysRegOp SysReg;
298 struct SysCRImmOp SysCRImm;
299 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000300 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000301 struct ShiftExtendOp ShiftExtend;
302 };
303
304 // Keep the MCContext around as the MCExprs may need manipulated during
305 // the add<>Operands() calls.
306 MCContext &Ctx;
307
David Blaikie960ea3f2014-06-08 16:18:35 +0000308public:
David Blaikie9f380a32015-03-16 18:06:57 +0000309 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000310
Tim Northover3b0846e2014-05-24 12:50:23 +0000311 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
312 Kind = o.Kind;
313 StartLoc = o.StartLoc;
314 EndLoc = o.EndLoc;
315 switch (Kind) {
316 case k_Token:
317 Tok = o.Tok;
318 break;
319 case k_Immediate:
320 Imm = o.Imm;
321 break;
322 case k_ShiftedImm:
323 ShiftedImm = o.ShiftedImm;
324 break;
325 case k_CondCode:
326 CondCode = o.CondCode;
327 break;
328 case k_FPImm:
329 FPImm = o.FPImm;
330 break;
331 case k_Barrier:
332 Barrier = o.Barrier;
333 break;
334 case k_Register:
335 Reg = o.Reg;
336 break;
337 case k_VectorList:
338 VectorList = o.VectorList;
339 break;
340 case k_VectorIndex:
341 VectorIndex = o.VectorIndex;
342 break;
343 case k_SysReg:
344 SysReg = o.SysReg;
345 break;
346 case k_SysCR:
347 SysCRImm = o.SysCRImm;
348 break;
349 case k_Prefetch:
350 Prefetch = o.Prefetch;
351 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000352 case k_PSBHint:
353 PSBHint = o.PSBHint;
354 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000355 case k_ShiftExtend:
356 ShiftExtend = o.ShiftExtend;
357 break;
358 }
359 }
360
361 /// getStartLoc - Get the location of the first token of this operand.
362 SMLoc getStartLoc() const override { return StartLoc; }
363 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000364 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000365
366 StringRef getToken() const {
367 assert(Kind == k_Token && "Invalid access!");
368 return StringRef(Tok.Data, Tok.Length);
369 }
370
371 bool isTokenSuffix() const {
372 assert(Kind == k_Token && "Invalid access!");
373 return Tok.IsSuffix;
374 }
375
376 const MCExpr *getImm() const {
377 assert(Kind == k_Immediate && "Invalid access!");
378 return Imm.Val;
379 }
380
381 const MCExpr *getShiftedImmVal() const {
382 assert(Kind == k_ShiftedImm && "Invalid access!");
383 return ShiftedImm.Val;
384 }
385
386 unsigned getShiftedImmShift() const {
387 assert(Kind == k_ShiftedImm && "Invalid access!");
388 return ShiftedImm.ShiftAmount;
389 }
390
391 AArch64CC::CondCode getCondCode() const {
392 assert(Kind == k_CondCode && "Invalid access!");
393 return CondCode.Code;
394 }
395
396 unsigned getFPImm() const {
397 assert(Kind == k_FPImm && "Invalid access!");
398 return FPImm.Val;
399 }
400
401 unsigned getBarrier() const {
402 assert(Kind == k_Barrier && "Invalid access!");
403 return Barrier.Val;
404 }
405
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000406 StringRef getBarrierName() const {
407 assert(Kind == k_Barrier && "Invalid access!");
408 return StringRef(Barrier.Data, Barrier.Length);
409 }
410
Tim Northover3b0846e2014-05-24 12:50:23 +0000411 unsigned getReg() const override {
412 assert(Kind == k_Register && "Invalid access!");
413 return Reg.RegNum;
414 }
415
416 unsigned getVectorListStart() const {
417 assert(Kind == k_VectorList && "Invalid access!");
418 return VectorList.RegNum;
419 }
420
421 unsigned getVectorListCount() const {
422 assert(Kind == k_VectorList && "Invalid access!");
423 return VectorList.Count;
424 }
425
426 unsigned getVectorIndex() const {
427 assert(Kind == k_VectorIndex && "Invalid access!");
428 return VectorIndex.Val;
429 }
430
431 StringRef getSysReg() const {
432 assert(Kind == k_SysReg && "Invalid access!");
433 return StringRef(SysReg.Data, SysReg.Length);
434 }
435
Tim Northover3b0846e2014-05-24 12:50:23 +0000436 unsigned getSysCR() const {
437 assert(Kind == k_SysCR && "Invalid access!");
438 return SysCRImm.Val;
439 }
440
441 unsigned getPrefetch() const {
442 assert(Kind == k_Prefetch && "Invalid access!");
443 return Prefetch.Val;
444 }
445
Oliver Stannarda34e4702015-12-01 10:48:51 +0000446 unsigned getPSBHint() const {
447 assert(Kind == k_PSBHint && "Invalid access!");
448 return PSBHint.Val;
449 }
450
451 StringRef getPSBHintName() const {
452 assert(Kind == k_PSBHint && "Invalid access!");
453 return StringRef(PSBHint.Data, PSBHint.Length);
454 }
455
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000456 StringRef getPrefetchName() const {
457 assert(Kind == k_Prefetch && "Invalid access!");
458 return StringRef(Prefetch.Data, Prefetch.Length);
459 }
460
Tim Northover3b0846e2014-05-24 12:50:23 +0000461 AArch64_AM::ShiftExtendType getShiftExtendType() const {
462 assert(Kind == k_ShiftExtend && "Invalid access!");
463 return ShiftExtend.Type;
464 }
465
466 unsigned getShiftExtendAmount() const {
467 assert(Kind == k_ShiftExtend && "Invalid access!");
468 return ShiftExtend.Amount;
469 }
470
471 bool hasShiftExtendAmount() const {
472 assert(Kind == k_ShiftExtend && "Invalid access!");
473 return ShiftExtend.HasExplicitAmount;
474 }
475
476 bool isImm() const override { return Kind == k_Immediate; }
477 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000478
479 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
480
481 template <int Bits, int Scale> bool isSImmScaled() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000482 if (!isImm())
483 return false;
484 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
485 if (!MCE)
486 return false;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000487
488 int64_t Shift = Bits - 1;
489 int64_t MinVal = (int64_t(1) << Shift) * -Scale;
490 int64_t MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
491
Tim Northover3b0846e2014-05-24 12:50:23 +0000492 int64_t Val = MCE->getValue();
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000493 return Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0;
Tim Northover3b0846e2014-05-24 12:50:23 +0000494 }
495
Sander de Smalen245e0e62018-01-22 10:46:00 +0000496 bool isSVEPattern() const {
497 if (!isImm())
498 return false;
499 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
500 if (!MCE)
501 return false;
502 int64_t Val = MCE->getValue();
503 return Val >= 0 && Val < 32;
504 }
505
Tim Northover3b0846e2014-05-24 12:50:23 +0000506 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
507 AArch64MCExpr::VariantKind ELFRefKind;
508 MCSymbolRefExpr::VariantKind DarwinRefKind;
509 int64_t Addend;
510 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
511 Addend)) {
512 // If we don't understand the expression, assume the best and
513 // let the fixup and relocation code deal with it.
514 return true;
515 }
516
517 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
518 ELFRefKind == AArch64MCExpr::VK_LO12 ||
519 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
520 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
521 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
522 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
523 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
524 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000525 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
526 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
527 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000528 // Note that we don't range-check the addend. It's adjusted modulo page
529 // size when converted, so there is no "out of range" condition when using
530 // @pageoff.
531 return Addend >= 0 && (Addend % Scale) == 0;
532 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
533 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
534 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
535 return Addend == 0;
536 }
537
538 return false;
539 }
540
541 template <int Scale> bool isUImm12Offset() const {
542 if (!isImm())
543 return false;
544
545 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
546 if (!MCE)
547 return isSymbolicUImm12Offset(getImm(), Scale);
548
549 int64_t Val = MCE->getValue();
550 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
551 }
552
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000553 template <int N, int M>
554 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000555 if (!isImm())
556 return false;
557 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
558 if (!MCE)
559 return false;
560 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000561 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000562 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000563
Sander de Smalena1c259c2018-01-29 13:05:38 +0000564 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
565 // a logical immediate can always be represented when inverted.
566 template <typename T>
567 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000568 if (!isImm())
569 return false;
570 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
571 if (!MCE)
572 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000573
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000574 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000575 int64_t SVal = typename std::make_signed<T>::type(Val);
576 int64_t UVal = typename std::make_unsigned<T>::type(Val);
577 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000578 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000579
Sander de Smalena1c259c2018-01-29 13:05:38 +0000580 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000581 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000582
Tim Northover3b0846e2014-05-24 12:50:23 +0000583 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000584
Tim Northover3b0846e2014-05-24 12:50:23 +0000585 bool isAddSubImm() const {
586 if (!isShiftedImm() && !isImm())
587 return false;
588
589 const MCExpr *Expr;
590
591 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
592 if (isShiftedImm()) {
593 unsigned Shift = ShiftedImm.ShiftAmount;
594 Expr = ShiftedImm.Val;
595 if (Shift != 0 && Shift != 12)
596 return false;
597 } else {
598 Expr = getImm();
599 }
600
601 AArch64MCExpr::VariantKind ELFRefKind;
602 MCSymbolRefExpr::VariantKind DarwinRefKind;
603 int64_t Addend;
604 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
605 DarwinRefKind, Addend)) {
606 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
607 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
608 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
609 || ELFRefKind == AArch64MCExpr::VK_LO12
610 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
611 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
612 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
613 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
614 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
615 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000616 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
617 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
618 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000619 }
620
Diana Picusc93518d2016-10-11 09:17:47 +0000621 // If it's a constant, it should be a real immediate in range:
622 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
623 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
624
625 // If it's an expression, we hope for the best and let the fixup/relocation
626 // code deal with it.
627 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000628 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000629
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000630 bool isAddSubImmNeg() const {
631 if (!isShiftedImm() && !isImm())
632 return false;
633
634 const MCExpr *Expr;
635
636 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
637 if (isShiftedImm()) {
638 unsigned Shift = ShiftedImm.ShiftAmount;
639 Expr = ShiftedImm.Val;
640 if (Shift != 0 && Shift != 12)
641 return false;
642 } else
643 Expr = getImm();
644
645 // Otherwise it should be a real negative immediate in range:
646 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
647 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
648 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000649
Tim Northover3b0846e2014-05-24 12:50:23 +0000650 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000651
Tim Northover3b0846e2014-05-24 12:50:23 +0000652 bool isSIMDImmType10() const {
653 if (!isImm())
654 return false;
655 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
656 if (!MCE)
657 return false;
658 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
659 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000660
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000661 template<int N>
662 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000663 if (!isImm())
664 return false;
665 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
666 if (!MCE)
667 return true;
668 int64_t Val = MCE->getValue();
669 if (Val & 0x3)
670 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000671 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
672 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000673 }
674
675 bool
676 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
677 if (!isImm())
678 return false;
679
680 AArch64MCExpr::VariantKind ELFRefKind;
681 MCSymbolRefExpr::VariantKind DarwinRefKind;
682 int64_t Addend;
683 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
684 DarwinRefKind, Addend)) {
685 return false;
686 }
687 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
688 return false;
689
690 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
691 if (ELFRefKind == AllowedModifiers[i])
692 return Addend == 0;
693 }
694
695 return false;
696 }
697
698 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000699 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000700 }
701
702 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000703 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
704 AArch64MCExpr::VK_TPREL_G2,
705 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000706 }
707
708 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000709 return isMovWSymbol({
710 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000711 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
712 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000713 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000714 }
715
716 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000717 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
718 AArch64MCExpr::VK_TPREL_G0,
719 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000720 }
721
722 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000723 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000724 }
725
726 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000727 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000728 }
729
730 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000731 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
732 AArch64MCExpr::VK_TPREL_G1_NC,
733 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000734 }
735
736 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000737 return isMovWSymbol(
738 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
739 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000740 }
741
742 template<int RegWidth, int Shift>
743 bool isMOVZMovAlias() const {
744 if (!isImm()) return false;
745
746 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
747 if (!CE) return false;
748 uint64_t Value = CE->getValue();
749
Tim Northoverdaa1c012016-06-16 01:42:25 +0000750 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000751 }
752
753 template<int RegWidth, int Shift>
754 bool isMOVNMovAlias() const {
755 if (!isImm()) return false;
756
757 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
758 if (!CE) return false;
759 uint64_t Value = CE->getValue();
760
Tim Northoverdaa1c012016-06-16 01:42:25 +0000761 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000762 }
763
764 bool isFPImm() const { return Kind == k_FPImm; }
765 bool isBarrier() const { return Kind == k_Barrier; }
766 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000767
Tim Northover3b0846e2014-05-24 12:50:23 +0000768 bool isMRSSystemRegister() const {
769 if (!isSysReg()) return false;
770
Tim Northover7cd58932015-01-22 17:23:04 +0000771 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000772 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000773
Tim Northover3b0846e2014-05-24 12:50:23 +0000774 bool isMSRSystemRegister() const {
775 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000776 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000777 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000778
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000779 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000780 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000781 return (SysReg.PStateField == AArch64PState::PAN ||
782 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000783 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000784
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000785 bool isSystemPStateFieldWithImm0_15() const {
786 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000787 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000788 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000789
Florian Hahnc4422242017-11-07 13:07:50 +0000790 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000791 return Kind == k_Register;
792 }
793
794 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000795 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
796 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000797
Florian Hahnc4422242017-11-07 13:07:50 +0000798 bool isNeonVectorReg() const {
799 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
800 }
801
802 bool isNeonVectorRegLo() const {
803 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000804 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
805 Reg.RegNum);
806 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000807
Sander de Smalencd6be962017-12-20 11:02:42 +0000808 template <unsigned Class> bool isSVEVectorReg() const {
809 RegKind RK;
810 switch (Class) {
811 case AArch64::ZPRRegClassID:
812 RK = RegKind::SVEDataVector;
813 break;
814 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000815 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000816 RK = RegKind::SVEPredicateVector;
817 break;
818 default:
819 llvm_unreachable("Unsupport register class");
820 }
821
822 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000823 AArch64MCRegisterClasses[Class].contains(getReg());
824 }
825
Sander de Smalencd6be962017-12-20 11:02:42 +0000826 template <int ElementWidth, unsigned Class>
827 bool isSVEVectorRegOfWidth() const {
828 return isSVEVectorReg<Class>() &&
Sander de Smalen73937b72018-04-11 07:36:10 +0000829 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth);
Florian Hahn91f11e52017-11-07 16:45:48 +0000830 }
831
Tim Northover3b0846e2014-05-24 12:50:23 +0000832 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000833 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000834 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
835 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000836
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000837 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000838 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000839 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
840 Reg.RegNum);
841 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000842
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000843 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000844 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000845 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
846 Reg.RegNum);
847 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000848
849 bool isGPR64sp0() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000850 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000851 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
852 }
853
Sam Parker5f934642017-08-31 09:27:04 +0000854 template<int64_t Angle, int64_t Remainder>
855 bool isComplexRotation() const {
856 if (!isImm()) return false;
857
858 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
859 if (!CE) return false;
860 uint64_t Value = CE->getValue();
861
862 return (Value % Angle == Remainder && Value <= 270);
863 }
864
Tim Northover3b0846e2014-05-24 12:50:23 +0000865 /// Is this a vector list with the type implicit (presumably attached to the
866 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +0000867 template <RegKind VectorKind, unsigned NumRegs>
868 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000869 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +0000870 VectorList.NumElements == 0 &&
871 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000872 }
873
Sander de Smalen650234b2018-04-12 11:40:52 +0000874 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
875 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +0000876 bool isTypedVectorList() const {
877 if (Kind != k_VectorList)
878 return false;
879 if (VectorList.Count != NumRegs)
880 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +0000881 if (VectorList.RegisterKind != VectorKind)
882 return false;
883 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +0000884 return false;
885 return VectorList.NumElements == NumElements;
886 }
887
888 bool isVectorIndex1() const {
889 return Kind == k_VectorIndex && VectorIndex.Val == 1;
890 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000891
Tim Northover3b0846e2014-05-24 12:50:23 +0000892 bool isVectorIndexB() const {
893 return Kind == k_VectorIndex && VectorIndex.Val < 16;
894 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000895
Tim Northover3b0846e2014-05-24 12:50:23 +0000896 bool isVectorIndexH() const {
897 return Kind == k_VectorIndex && VectorIndex.Val < 8;
898 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000899
Tim Northover3b0846e2014-05-24 12:50:23 +0000900 bool isVectorIndexS() const {
901 return Kind == k_VectorIndex && VectorIndex.Val < 4;
902 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000903
Tim Northover3b0846e2014-05-24 12:50:23 +0000904 bool isVectorIndexD() const {
905 return Kind == k_VectorIndex && VectorIndex.Val < 2;
906 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000907
Tim Northover3b0846e2014-05-24 12:50:23 +0000908 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000909
Tim Northover3b0846e2014-05-24 12:50:23 +0000910 bool isTokenEqual(StringRef Str) const {
911 return Kind == k_Token && getToken() == Str;
912 }
913 bool isSysCR() const { return Kind == k_SysCR; }
914 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000915 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000916 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
917 bool isShifter() const {
918 if (!isShiftExtend())
919 return false;
920
921 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
922 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
923 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
924 ST == AArch64_AM::MSL);
925 }
926 bool isExtend() const {
927 if (!isShiftExtend())
928 return false;
929
930 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
931 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
932 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
933 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
934 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
935 ET == AArch64_AM::LSL) &&
936 getShiftExtendAmount() <= 4;
937 }
938
939 bool isExtend64() const {
940 if (!isExtend())
941 return false;
942 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
943 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
944 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
945 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000946
Tim Northover3b0846e2014-05-24 12:50:23 +0000947 bool isExtendLSL64() const {
948 if (!isExtend())
949 return false;
950 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
951 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
952 ET == AArch64_AM::LSL) &&
953 getShiftExtendAmount() <= 4;
954 }
955
956 template<int Width> bool isMemXExtend() const {
957 if (!isExtend())
958 return false;
959 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
960 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
961 (getShiftExtendAmount() == Log2_32(Width / 8) ||
962 getShiftExtendAmount() == 0);
963 }
964
965 template<int Width> bool isMemWExtend() const {
966 if (!isExtend())
967 return false;
968 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
969 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
970 (getShiftExtendAmount() == Log2_32(Width / 8) ||
971 getShiftExtendAmount() == 0);
972 }
973
974 template <unsigned width>
975 bool isArithmeticShifter() const {
976 if (!isShifter())
977 return false;
978
979 // An arithmetic shifter is LSL, LSR, or ASR.
980 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
981 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
982 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
983 }
984
985 template <unsigned width>
986 bool isLogicalShifter() const {
987 if (!isShifter())
988 return false;
989
990 // A logical shifter is LSL, LSR, ASR or ROR.
991 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
992 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
993 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
994 getShiftExtendAmount() < width;
995 }
996
997 bool isMovImm32Shifter() const {
998 if (!isShifter())
999 return false;
1000
1001 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1002 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1003 if (ST != AArch64_AM::LSL)
1004 return false;
1005 uint64_t Val = getShiftExtendAmount();
1006 return (Val == 0 || Val == 16);
1007 }
1008
1009 bool isMovImm64Shifter() const {
1010 if (!isShifter())
1011 return false;
1012
1013 // A MOVi shifter is LSL of 0 or 16.
1014 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1015 if (ST != AArch64_AM::LSL)
1016 return false;
1017 uint64_t Val = getShiftExtendAmount();
1018 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1019 }
1020
1021 bool isLogicalVecShifter() const {
1022 if (!isShifter())
1023 return false;
1024
1025 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1026 unsigned Shift = getShiftExtendAmount();
1027 return getShiftExtendType() == AArch64_AM::LSL &&
1028 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1029 }
1030
1031 bool isLogicalVecHalfWordShifter() const {
1032 if (!isLogicalVecShifter())
1033 return false;
1034
1035 // A logical vector shifter is a left shift by 0 or 8.
1036 unsigned Shift = getShiftExtendAmount();
1037 return getShiftExtendType() == AArch64_AM::LSL &&
1038 (Shift == 0 || Shift == 8);
1039 }
1040
1041 bool isMoveVecShifter() const {
1042 if (!isShiftExtend())
1043 return false;
1044
1045 // A logical vector shifter is a left shift by 8 or 16.
1046 unsigned Shift = getShiftExtendAmount();
1047 return getShiftExtendType() == AArch64_AM::MSL &&
1048 (Shift == 8 || Shift == 16);
1049 }
1050
1051 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1052 // to LDUR/STUR when the offset is not legal for the former but is for
1053 // the latter. As such, in addition to checking for being a legal unscaled
1054 // address, also check that it is not a legal scaled address. This avoids
1055 // ambiguity in the matcher.
1056 template<int Width>
1057 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001058 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001059 }
1060
1061 bool isAdrpLabel() const {
1062 // Validation was handled during parsing, so we just sanity check that
1063 // something didn't go haywire.
1064 if (!isImm())
1065 return false;
1066
1067 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1068 int64_t Val = CE->getValue();
1069 int64_t Min = - (4096 * (1LL << (21 - 1)));
1070 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1071 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1072 }
1073
1074 return true;
1075 }
1076
1077 bool isAdrLabel() const {
1078 // Validation was handled during parsing, so we just sanity check that
1079 // something didn't go haywire.
1080 if (!isImm())
1081 return false;
1082
1083 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1084 int64_t Val = CE->getValue();
1085 int64_t Min = - (1LL << (21 - 1));
1086 int64_t Max = ((1LL << (21 - 1)) - 1);
1087 return Val >= Min && Val <= Max;
1088 }
1089
1090 return true;
1091 }
1092
1093 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1094 // Add as immediates when possible. Null MCExpr = 0.
1095 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001096 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001097 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001098 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001099 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001100 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001101 }
1102
1103 void addRegOperands(MCInst &Inst, unsigned N) const {
1104 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001105 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001106 }
1107
1108 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1109 assert(N == 1 && "Invalid number of operands!");
1110 assert(
1111 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1112
1113 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1114 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1115 RI->getEncodingValue(getReg()));
1116
Jim Grosbache9119e42015-05-13 18:37:00 +00001117 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001118 }
1119
1120 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1121 assert(N == 1 && "Invalid number of operands!");
1122 assert(
1123 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001124 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001125 }
1126
1127 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1128 assert(N == 1 && "Invalid number of operands!");
1129 assert(
1130 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001131 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001132 }
1133
1134 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1135 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001136 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001137 }
1138
Sander de Smalen525e3222018-04-12 13:19:32 +00001139 enum VecListIndexType {
1140 VecListIdx_DReg = 0,
1141 VecListIdx_QReg = 1,
1142 };
1143
1144 template <VecListIndexType RegTy, unsigned NumRegs>
1145 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001146 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001147 static const unsigned FirstRegs[][5] = {
1148 /* DReg */ { AArch64::Q0,
1149 AArch64::D0, AArch64::D0_D1,
1150 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1151 /* QReg */ { AArch64::Q0,
1152 AArch64::Q0, AArch64::Q0_Q1,
1153 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 }
1154 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001155
Sander de Smalen525e3222018-04-12 13:19:32 +00001156 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1157 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1158 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001159 }
1160
1161 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1162 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001163 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001164 }
1165
1166 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1167 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001168 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001169 }
1170
1171 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1172 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001173 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001174 }
1175
1176 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1177 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001178 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001179 }
1180
1181 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1182 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001183 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001184 }
1185
1186 void addImmOperands(MCInst &Inst, unsigned N) const {
1187 assert(N == 1 && "Invalid number of operands!");
1188 // If this is a pageoff symrefexpr with an addend, adjust the addend
1189 // to be only the page-offset portion. Otherwise, just add the expr
1190 // as-is.
1191 addExpr(Inst, getImm());
1192 }
1193
1194 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1195 assert(N == 2 && "Invalid number of operands!");
1196 if (isShiftedImm()) {
1197 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001198 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001199 } else {
1200 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001201 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001202 }
1203 }
1204
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001205 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1206 assert(N == 2 && "Invalid number of operands!");
1207
1208 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1209 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1210 int64_t Val = -CE->getValue();
1211 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1212
1213 Inst.addOperand(MCOperand::createImm(Val));
1214 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1215 }
1216
Tim Northover3b0846e2014-05-24 12:50:23 +00001217 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1218 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001219 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001220 }
1221
1222 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1223 assert(N == 1 && "Invalid number of operands!");
1224 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1225 if (!MCE)
1226 addExpr(Inst, getImm());
1227 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001228 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001229 }
1230
1231 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1232 addImmOperands(Inst, N);
1233 }
1234
1235 template<int Scale>
1236 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1237 assert(N == 1 && "Invalid number of operands!");
1238 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1239
1240 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001241 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001242 return;
1243 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001244 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001245 }
1246
1247 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1248 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001249 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001250 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001251 }
1252
Sam Parker6d42de72017-08-11 13:14:00 +00001253 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1254 assert(N == 1 && "Invalid number of operands!");
1255 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1256 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1257 }
1258
Tim Northover3b0846e2014-05-24 12:50:23 +00001259 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1260 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001261 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001262 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001263 }
1264
1265 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1266 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001267 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001268 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001269 }
1270
1271 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1272 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001273 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001274 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001275 }
1276
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001277 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1278 assert(N == 1 && "Invalid number of operands!");
1279 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1280 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1281 }
1282
Tim Northover3b0846e2014-05-24 12:50:23 +00001283 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1284 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001285 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001286 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001287 }
1288
1289 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1290 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001291 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001292 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001293 }
1294
1295 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1296 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001297 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001298 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001299 }
1300
1301 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1302 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001303 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001304 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001305 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001306 }
1307
1308 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1309 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001310 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001311 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001312 }
1313
1314 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1315 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001316 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001317 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001318 }
1319
1320 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1321 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001322 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001323 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001324 }
1325
1326 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1327 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001328 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001329 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001330 }
1331
1332 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1333 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001334 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001335 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001336 }
1337
1338 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1339 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001340 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001341 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001342 }
1343
1344 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1345 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001346 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001347 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001348 }
1349
1350 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1351 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001352 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001353 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001354 }
1355
1356 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1357 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001358 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001359 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001360 }
1361
1362 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1363 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001364 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001365 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001366 }
1367
Sander de Smalena1c259c2018-01-29 13:05:38 +00001368 template <typename T>
1369 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001370 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001371 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001372 typename std::make_unsigned<T>::type Val = MCE->getValue();
1373 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001374 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001375 }
1376
Sander de Smalena1c259c2018-01-29 13:05:38 +00001377 template <typename T>
1378 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001379 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001380 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001381 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1382 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001383 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001384 }
1385
Tim Northover3b0846e2014-05-24 12:50:23 +00001386 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1387 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001388 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001389 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001390 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001391 }
1392
1393 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1394 // Branch operands don't encode the low bits, so shift them off
1395 // here. If it's a label, however, just put it on directly as there's
1396 // not enough information now to do anything.
1397 assert(N == 1 && "Invalid number of operands!");
1398 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1399 if (!MCE) {
1400 addExpr(Inst, getImm());
1401 return;
1402 }
1403 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001404 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001405 }
1406
1407 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1408 // Branch operands don't encode the low bits, so shift them off
1409 // here. If it's a label, however, just put it on directly as there's
1410 // not enough information now to do anything.
1411 assert(N == 1 && "Invalid number of operands!");
1412 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1413 if (!MCE) {
1414 addExpr(Inst, getImm());
1415 return;
1416 }
1417 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001418 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001419 }
1420
1421 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1422 // Branch operands don't encode the low bits, so shift them off
1423 // here. If it's a label, however, just put it on directly as there's
1424 // not enough information now to do anything.
1425 assert(N == 1 && "Invalid number of operands!");
1426 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1427 if (!MCE) {
1428 addExpr(Inst, getImm());
1429 return;
1430 }
1431 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001432 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001433 }
1434
1435 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1436 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001437 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001438 }
1439
1440 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1441 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001442 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001443 }
1444
1445 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1446 assert(N == 1 && "Invalid number of operands!");
1447
Jim Grosbache9119e42015-05-13 18:37:00 +00001448 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001449 }
1450
1451 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1452 assert(N == 1 && "Invalid number of operands!");
1453
Jim Grosbache9119e42015-05-13 18:37:00 +00001454 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001455 }
1456
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001457 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1458 assert(N == 1 && "Invalid number of operands!");
1459
1460 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1461 }
1462
1463 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001464 assert(N == 1 && "Invalid number of operands!");
1465
Jim Grosbache9119e42015-05-13 18:37:00 +00001466 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001467 }
1468
1469 void addSysCROperands(MCInst &Inst, unsigned N) const {
1470 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001471 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001472 }
1473
1474 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1475 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001476 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001477 }
1478
Oliver Stannarda34e4702015-12-01 10:48:51 +00001479 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1480 assert(N == 1 && "Invalid number of operands!");
1481 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1482 }
1483
Tim Northover3b0846e2014-05-24 12:50:23 +00001484 void addShifterOperands(MCInst &Inst, unsigned N) const {
1485 assert(N == 1 && "Invalid number of operands!");
1486 unsigned Imm =
1487 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001488 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001489 }
1490
1491 void addExtendOperands(MCInst &Inst, unsigned N) const {
1492 assert(N == 1 && "Invalid number of operands!");
1493 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1494 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1495 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001496 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001497 }
1498
1499 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1500 assert(N == 1 && "Invalid number of operands!");
1501 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1502 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1503 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001504 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001505 }
1506
1507 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1508 assert(N == 2 && "Invalid number of operands!");
1509 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1510 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001511 Inst.addOperand(MCOperand::createImm(IsSigned));
1512 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001513 }
1514
1515 // For 8-bit load/store instructions with a register offset, both the
1516 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1517 // they're disambiguated by whether the shift was explicit or implicit rather
1518 // than its size.
1519 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1520 assert(N == 2 && "Invalid number of operands!");
1521 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1522 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001523 Inst.addOperand(MCOperand::createImm(IsSigned));
1524 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001525 }
1526
1527 template<int Shift>
1528 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1529 assert(N == 1 && "Invalid number of operands!");
1530
1531 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1532 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001533 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001534 }
1535
1536 template<int Shift>
1537 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1538 assert(N == 1 && "Invalid number of operands!");
1539
1540 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1541 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001542 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001543 }
1544
Sam Parker5f934642017-08-31 09:27:04 +00001545 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1546 assert(N == 1 && "Invalid number of operands!");
1547 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1548 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1549 }
1550
1551 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1552 assert(N == 1 && "Invalid number of operands!");
1553 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1554 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1555 }
1556
Tim Northover3b0846e2014-05-24 12:50:23 +00001557 void print(raw_ostream &OS) const override;
1558
David Blaikie960ea3f2014-06-08 16:18:35 +00001559 static std::unique_ptr<AArch64Operand>
1560 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1561 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001562 Op->Tok.Data = Str.data();
1563 Op->Tok.Length = Str.size();
1564 Op->Tok.IsSuffix = IsSuffix;
1565 Op->StartLoc = S;
1566 Op->EndLoc = S;
1567 return Op;
1568 }
1569
David Blaikie960ea3f2014-06-08 16:18:35 +00001570 static std::unique_ptr<AArch64Operand>
Florian Hahnc4422242017-11-07 13:07:50 +00001571 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001572 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001573 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001574 Op->Reg.Kind = Kind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001575 Op->StartLoc = S;
1576 Op->EndLoc = E;
1577 return Op;
1578 }
1579
David Blaikie960ea3f2014-06-08 16:18:35 +00001580 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001581 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1582 SMLoc S, SMLoc E, MCContext &Ctx) {
1583 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1584 Kind == RegKind::SVEPredicateVector) &&
1585 "Invalid vector kind");
Florian Hahn91f11e52017-11-07 16:45:48 +00001586 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1587 Op->Reg.RegNum = RegNum;
1588 Op->Reg.ElementWidth = ElementWidth;
1589 Op->Reg.Kind = Kind;
1590 Op->StartLoc = S;
1591 Op->EndLoc = E;
1592 return Op;
1593 }
1594
1595 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001596 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001597 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1598 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001599 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001600 Op->VectorList.RegNum = RegNum;
1601 Op->VectorList.Count = Count;
1602 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001603 Op->VectorList.ElementWidth = ElementWidth;
1604 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001605 Op->StartLoc = S;
1606 Op->EndLoc = E;
1607 return Op;
1608 }
1609
David Blaikie960ea3f2014-06-08 16:18:35 +00001610 static std::unique_ptr<AArch64Operand>
1611 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1612 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001613 Op->VectorIndex.Val = Idx;
1614 Op->StartLoc = S;
1615 Op->EndLoc = E;
1616 return Op;
1617 }
1618
David Blaikie960ea3f2014-06-08 16:18:35 +00001619 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1620 SMLoc E, MCContext &Ctx) {
1621 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001622 Op->Imm.Val = Val;
1623 Op->StartLoc = S;
1624 Op->EndLoc = E;
1625 return Op;
1626 }
1627
David Blaikie960ea3f2014-06-08 16:18:35 +00001628 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1629 unsigned ShiftAmount,
1630 SMLoc S, SMLoc E,
1631 MCContext &Ctx) {
1632 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001633 Op->ShiftedImm .Val = Val;
1634 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1635 Op->StartLoc = S;
1636 Op->EndLoc = E;
1637 return Op;
1638 }
1639
David Blaikie960ea3f2014-06-08 16:18:35 +00001640 static std::unique_ptr<AArch64Operand>
1641 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1642 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001643 Op->CondCode.Code = Code;
1644 Op->StartLoc = S;
1645 Op->EndLoc = E;
1646 return Op;
1647 }
1648
David Blaikie960ea3f2014-06-08 16:18:35 +00001649 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1650 MCContext &Ctx) {
1651 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001652 Op->FPImm.Val = Val;
1653 Op->StartLoc = S;
1654 Op->EndLoc = S;
1655 return Op;
1656 }
1657
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001658 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1659 StringRef Str,
1660 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001661 MCContext &Ctx) {
1662 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001663 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001664 Op->Barrier.Data = Str.data();
1665 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001666 Op->StartLoc = S;
1667 Op->EndLoc = S;
1668 return Op;
1669 }
1670
Tim Northover7cd58932015-01-22 17:23:04 +00001671 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1672 uint32_t MRSReg,
1673 uint32_t MSRReg,
1674 uint32_t PStateField,
1675 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001676 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001677 Op->SysReg.Data = Str.data();
1678 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001679 Op->SysReg.MRSReg = MRSReg;
1680 Op->SysReg.MSRReg = MSRReg;
1681 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001682 Op->StartLoc = S;
1683 Op->EndLoc = S;
1684 return Op;
1685 }
1686
David Blaikie960ea3f2014-06-08 16:18:35 +00001687 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1688 SMLoc E, MCContext &Ctx) {
1689 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001690 Op->SysCRImm.Val = Val;
1691 Op->StartLoc = S;
1692 Op->EndLoc = E;
1693 return Op;
1694 }
1695
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001696 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1697 StringRef Str,
1698 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001699 MCContext &Ctx) {
1700 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001701 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001702 Op->Barrier.Data = Str.data();
1703 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001704 Op->StartLoc = S;
1705 Op->EndLoc = S;
1706 return Op;
1707 }
1708
Oliver Stannarda34e4702015-12-01 10:48:51 +00001709 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1710 StringRef Str,
1711 SMLoc S,
1712 MCContext &Ctx) {
1713 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1714 Op->PSBHint.Val = Val;
1715 Op->PSBHint.Data = Str.data();
1716 Op->PSBHint.Length = Str.size();
1717 Op->StartLoc = S;
1718 Op->EndLoc = S;
1719 return Op;
1720 }
1721
David Blaikie960ea3f2014-06-08 16:18:35 +00001722 static std::unique_ptr<AArch64Operand>
1723 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1724 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1725 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001726 Op->ShiftExtend.Type = ShOp;
1727 Op->ShiftExtend.Amount = Val;
1728 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1729 Op->StartLoc = S;
1730 Op->EndLoc = E;
1731 return Op;
1732 }
1733};
1734
1735} // end anonymous namespace.
1736
1737void AArch64Operand::print(raw_ostream &OS) const {
1738 switch (Kind) {
1739 case k_FPImm:
1740 OS << "<fpimm " << getFPImm() << "("
1741 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1742 break;
1743 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001744 StringRef Name = getBarrierName();
1745 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001746 OS << "<barrier " << Name << ">";
1747 else
1748 OS << "<barrier invalid #" << getBarrier() << ">";
1749 break;
1750 }
1751 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001752 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001753 break;
1754 case k_ShiftedImm: {
1755 unsigned Shift = getShiftedImmShift();
1756 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001757 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001758 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1759 break;
1760 }
1761 case k_CondCode:
1762 OS << "<condcode " << getCondCode() << ">";
1763 break;
1764 case k_Register:
1765 OS << "<register " << getReg() << ">";
1766 break;
1767 case k_VectorList: {
1768 OS << "<vectorlist ";
1769 unsigned Reg = getVectorListStart();
1770 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1771 OS << Reg + i << " ";
1772 OS << ">";
1773 break;
1774 }
1775 case k_VectorIndex:
1776 OS << "<vectorindex " << getVectorIndex() << ">";
1777 break;
1778 case k_SysReg:
1779 OS << "<sysreg: " << getSysReg() << '>';
1780 break;
1781 case k_Token:
1782 OS << "'" << getToken() << "'";
1783 break;
1784 case k_SysCR:
1785 OS << "c" << getSysCR();
1786 break;
1787 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001788 StringRef Name = getPrefetchName();
1789 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001790 OS << "<prfop " << Name << ">";
1791 else
1792 OS << "<prfop invalid #" << getPrefetch() << ">";
1793 break;
1794 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001795 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001796 OS << getPSBHintName();
1797 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001798 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001799 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1800 << getShiftExtendAmount();
1801 if (!hasShiftExtendAmount())
1802 OS << "<imp>";
1803 OS << '>';
1804 break;
1805 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001806}
1807
1808/// @name Auto-generated Match Functions
1809/// {
1810
1811static unsigned MatchRegisterName(StringRef Name);
1812
1813/// }
1814
Florian Hahnc4422242017-11-07 13:07:50 +00001815static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001816 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001817 .Case("v0", AArch64::Q0)
1818 .Case("v1", AArch64::Q1)
1819 .Case("v2", AArch64::Q2)
1820 .Case("v3", AArch64::Q3)
1821 .Case("v4", AArch64::Q4)
1822 .Case("v5", AArch64::Q5)
1823 .Case("v6", AArch64::Q6)
1824 .Case("v7", AArch64::Q7)
1825 .Case("v8", AArch64::Q8)
1826 .Case("v9", AArch64::Q9)
1827 .Case("v10", AArch64::Q10)
1828 .Case("v11", AArch64::Q11)
1829 .Case("v12", AArch64::Q12)
1830 .Case("v13", AArch64::Q13)
1831 .Case("v14", AArch64::Q14)
1832 .Case("v15", AArch64::Q15)
1833 .Case("v16", AArch64::Q16)
1834 .Case("v17", AArch64::Q17)
1835 .Case("v18", AArch64::Q18)
1836 .Case("v19", AArch64::Q19)
1837 .Case("v20", AArch64::Q20)
1838 .Case("v21", AArch64::Q21)
1839 .Case("v22", AArch64::Q22)
1840 .Case("v23", AArch64::Q23)
1841 .Case("v24", AArch64::Q24)
1842 .Case("v25", AArch64::Q25)
1843 .Case("v26", AArch64::Q26)
1844 .Case("v27", AArch64::Q27)
1845 .Case("v28", AArch64::Q28)
1846 .Case("v29", AArch64::Q29)
1847 .Case("v30", AArch64::Q30)
1848 .Case("v31", AArch64::Q31)
1849 .Default(0);
1850}
1851
Sander de Smalen73937b72018-04-11 07:36:10 +00001852/// Returns an optional pair of (#elements, element-width) if Suffix
1853/// is a valid vector kind. Where the number of elements in a vector
1854/// or the vector width is implicit or explicitly unknown (but still a
1855/// valid suffix kind), 0 is used.
1856static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1857 RegKind VectorKind) {
1858 std::pair<int, int> Res = {-1, -1};
1859
1860 switch (VectorKind) {
1861 case RegKind::NeonVector:
1862 Res =
1863 StringSwitch<std::pair<int, int>>(Suffix.lower())
1864 .Case("", {0, 0})
1865 .Case(".1d", {1, 64})
1866 .Case(".1q", {1, 128})
1867 // '.2h' needed for fp16 scalar pairwise reductions
1868 .Case(".2h", {2, 16})
1869 .Case(".2s", {2, 32})
1870 .Case(".2d", {2, 64})
1871 // '.4b' is another special case for the ARMv8.2a dot product
1872 // operand
1873 .Case(".4b", {4, 8})
1874 .Case(".4h", {4, 16})
1875 .Case(".4s", {4, 32})
1876 .Case(".8b", {8, 8})
1877 .Case(".8h", {8, 16})
1878 .Case(".16b", {16, 8})
1879 // Accept the width neutral ones, too, for verbose syntax. If those
1880 // aren't used in the right places, the token operand won't match so
1881 // all will work out.
1882 .Case(".b", {0, 8})
1883 .Case(".h", {0, 16})
1884 .Case(".s", {0, 32})
1885 .Case(".d", {0, 64})
1886 .Default({-1, -1});
1887 break;
1888 case RegKind::SVEPredicateVector:
1889 case RegKind::SVEDataVector:
1890 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1891 .Case("", {0, 0})
1892 .Case(".b", {0, 8})
1893 .Case(".h", {0, 16})
1894 .Case(".s", {0, 32})
1895 .Case(".d", {0, 64})
1896 .Case(".q", {0, 128})
1897 .Default({-1, -1});
1898 break;
1899 default:
1900 llvm_unreachable("Unsupported RegKind");
1901 }
1902
1903 if (Res == std::make_pair(-1, -1))
1904 return Optional<std::pair<int, int>>();
1905
1906 return Optional<std::pair<int, int>>(Res);
1907}
1908
1909static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1910 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001911}
1912
Florian Hahn91f11e52017-11-07 16:45:48 +00001913static unsigned matchSVEDataVectorRegName(StringRef Name) {
1914 return StringSwitch<unsigned>(Name.lower())
1915 .Case("z0", AArch64::Z0)
1916 .Case("z1", AArch64::Z1)
1917 .Case("z2", AArch64::Z2)
1918 .Case("z3", AArch64::Z3)
1919 .Case("z4", AArch64::Z4)
1920 .Case("z5", AArch64::Z5)
1921 .Case("z6", AArch64::Z6)
1922 .Case("z7", AArch64::Z7)
1923 .Case("z8", AArch64::Z8)
1924 .Case("z9", AArch64::Z9)
1925 .Case("z10", AArch64::Z10)
1926 .Case("z11", AArch64::Z11)
1927 .Case("z12", AArch64::Z12)
1928 .Case("z13", AArch64::Z13)
1929 .Case("z14", AArch64::Z14)
1930 .Case("z15", AArch64::Z15)
1931 .Case("z16", AArch64::Z16)
1932 .Case("z17", AArch64::Z17)
1933 .Case("z18", AArch64::Z18)
1934 .Case("z19", AArch64::Z19)
1935 .Case("z20", AArch64::Z20)
1936 .Case("z21", AArch64::Z21)
1937 .Case("z22", AArch64::Z22)
1938 .Case("z23", AArch64::Z23)
1939 .Case("z24", AArch64::Z24)
1940 .Case("z25", AArch64::Z25)
1941 .Case("z26", AArch64::Z26)
1942 .Case("z27", AArch64::Z27)
1943 .Case("z28", AArch64::Z28)
1944 .Case("z29", AArch64::Z29)
1945 .Case("z30", AArch64::Z30)
1946 .Case("z31", AArch64::Z31)
1947 .Default(0);
1948}
1949
Sander de Smalencd6be962017-12-20 11:02:42 +00001950static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1951 return StringSwitch<unsigned>(Name.lower())
1952 .Case("p0", AArch64::P0)
1953 .Case("p1", AArch64::P1)
1954 .Case("p2", AArch64::P2)
1955 .Case("p3", AArch64::P3)
1956 .Case("p4", AArch64::P4)
1957 .Case("p5", AArch64::P5)
1958 .Case("p6", AArch64::P6)
1959 .Case("p7", AArch64::P7)
1960 .Case("p8", AArch64::P8)
1961 .Case("p9", AArch64::P9)
1962 .Case("p10", AArch64::P10)
1963 .Case("p11", AArch64::P11)
1964 .Case("p12", AArch64::P12)
1965 .Case("p13", AArch64::P13)
1966 .Case("p14", AArch64::P14)
1967 .Case("p15", AArch64::P15)
1968 .Default(0);
1969}
1970
Tim Northover3b0846e2014-05-24 12:50:23 +00001971bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1972 SMLoc &EndLoc) {
1973 StartLoc = getLoc();
1974 RegNo = tryParseRegister();
1975 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1976 return (RegNo == (unsigned)-1);
1977}
1978
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001979// Matches a register name or register alias previously defined by '.req'
1980unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001981 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001982 unsigned RegNum = 0;
1983 if ((RegNum = matchSVEDataVectorRegName(Name)))
1984 return Kind == RegKind::SVEDataVector ? RegNum : 0;
1985
Sander de Smalencd6be962017-12-20 11:02:42 +00001986 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
1987 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
1988
Sander de Smalenc067c302017-12-20 09:45:45 +00001989 if ((RegNum = MatchNeonVectorRegName(Name)))
1990 return Kind == RegKind::NeonVector ? RegNum : 0;
1991
1992 // The parsed register must be of RegKind Scalar
1993 if ((RegNum = MatchRegisterName(Name)))
1994 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001995
Florian Hahnc4422242017-11-07 13:07:50 +00001996 if (!RegNum) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001997 // Check for aliases registered via .req. Canonicalize to lower case.
1998 // That's more consistent since register names are case insensitive, and
1999 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2000 auto Entry = RegisterReqs.find(Name.lower());
2001 if (Entry == RegisterReqs.end())
2002 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002003
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002004 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002005 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002006 RegNum = Entry->getValue().second;
2007 }
2008 return RegNum;
2009}
2010
Tim Northover3b0846e2014-05-24 12:50:23 +00002011/// tryParseRegister - Try to parse a register name. The token must be an
2012/// Identifier when called, and if it is a register name the token is eaten and
2013/// the register is added to the operand list.
2014int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002015 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002016 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002017 if (Tok.isNot(AsmToken::Identifier))
2018 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00002019
2020 std::string lowerCase = Tok.getString().lower();
Florian Hahnc4422242017-11-07 13:07:50 +00002021 unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
Sander de Smalenc067c302017-12-20 09:45:45 +00002022
Tim Northover3b0846e2014-05-24 12:50:23 +00002023 // Also handle a few aliases of registers.
2024 if (RegNum == 0)
2025 RegNum = StringSwitch<unsigned>(lowerCase)
2026 .Case("fp", AArch64::FP)
2027 .Case("lr", AArch64::LR)
2028 .Case("x31", AArch64::XZR)
2029 .Case("w31", AArch64::WZR)
2030 .Default(0);
2031
2032 if (RegNum == 0)
2033 return -1;
2034
2035 Parser.Lex(); // Eat identifier token.
2036 return RegNum;
2037}
2038
Tim Northover3b0846e2014-05-24 12:50:23 +00002039/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002040OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002041AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002042 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002043 SMLoc S = getLoc();
2044
2045 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2046 Error(S, "Expected cN operand where 0 <= N <= 15");
2047 return MatchOperand_ParseFail;
2048 }
2049
2050 StringRef Tok = Parser.getTok().getIdentifier();
2051 if (Tok[0] != 'c' && Tok[0] != 'C') {
2052 Error(S, "Expected cN operand where 0 <= N <= 15");
2053 return MatchOperand_ParseFail;
2054 }
2055
2056 uint32_t CRNum;
2057 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2058 if (BadNum || CRNum > 15) {
2059 Error(S, "Expected cN operand where 0 <= N <= 15");
2060 return MatchOperand_ParseFail;
2061 }
2062
2063 Parser.Lex(); // Eat identifier token.
2064 Operands.push_back(
2065 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2066 return MatchOperand_Success;
2067}
2068
2069/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002070OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002071AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002072 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002073 SMLoc S = getLoc();
2074 const AsmToken &Tok = Parser.getTok();
2075 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002076 // Eat optional hash.
2077 if (parseOptionalToken(AsmToken::Hash) ||
2078 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002079 const MCExpr *ImmVal;
2080 if (getParser().parseExpression(ImmVal))
2081 return MatchOperand_ParseFail;
2082
2083 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2084 if (!MCE) {
2085 TokError("immediate value expected for prefetch operand");
2086 return MatchOperand_ParseFail;
2087 }
2088 unsigned prfop = MCE->getValue();
2089 if (prfop > 31) {
2090 TokError("prefetch operand out of range, [0,31] expected");
2091 return MatchOperand_ParseFail;
2092 }
2093
Tim Northovere6ae6762016-07-05 21:23:04 +00002094 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2095 Operands.push_back(AArch64Operand::CreatePrefetch(
2096 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002097 return MatchOperand_Success;
2098 }
2099
2100 if (Tok.isNot(AsmToken::Identifier)) {
2101 TokError("pre-fetch hint expected");
2102 return MatchOperand_ParseFail;
2103 }
2104
Tim Northovere6ae6762016-07-05 21:23:04 +00002105 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2106 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002107 TokError("pre-fetch hint expected");
2108 return MatchOperand_ParseFail;
2109 }
2110
2111 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002112 Operands.push_back(AArch64Operand::CreatePrefetch(
2113 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002114 return MatchOperand_Success;
2115}
2116
Oliver Stannarda34e4702015-12-01 10:48:51 +00002117/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002118OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002119AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2120 MCAsmParser &Parser = getParser();
2121 SMLoc S = getLoc();
2122 const AsmToken &Tok = Parser.getTok();
2123 if (Tok.isNot(AsmToken::Identifier)) {
2124 TokError("invalid operand for instruction");
2125 return MatchOperand_ParseFail;
2126 }
2127
Tim Northovere6ae6762016-07-05 21:23:04 +00002128 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2129 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002130 TokError("invalid operand for instruction");
2131 return MatchOperand_ParseFail;
2132 }
2133
2134 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002135 Operands.push_back(AArch64Operand::CreatePSBHint(
2136 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002137 return MatchOperand_Success;
2138}
2139
Tim Northover3b0846e2014-05-24 12:50:23 +00002140/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2141/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002142OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002143AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002144 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002145 SMLoc S = getLoc();
2146 const MCExpr *Expr;
2147
2148 if (Parser.getTok().is(AsmToken::Hash)) {
2149 Parser.Lex(); // Eat hash token.
2150 }
2151
2152 if (parseSymbolicImmVal(Expr))
2153 return MatchOperand_ParseFail;
2154
2155 AArch64MCExpr::VariantKind ELFRefKind;
2156 MCSymbolRefExpr::VariantKind DarwinRefKind;
2157 int64_t Addend;
2158 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2159 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2160 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2161 // No modifier was specified at all; this is the syntax for an ELF basic
2162 // ADRP relocation (unfortunately).
2163 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002164 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002165 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2166 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2167 Addend != 0) {
2168 Error(S, "gotpage label reference not allowed an addend");
2169 return MatchOperand_ParseFail;
2170 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2171 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2172 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2173 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2174 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2175 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2176 // The operand must be an @page or @gotpage qualified symbolref.
2177 Error(S, "page or gotpage label reference expected");
2178 return MatchOperand_ParseFail;
2179 }
2180 }
2181
2182 // We have either a label reference possibly with addend or an immediate. The
2183 // addend is a raw value here. The linker will adjust it to only reference the
2184 // page.
2185 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2186 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2187
2188 return MatchOperand_Success;
2189}
2190
2191/// tryParseAdrLabel - Parse and validate a source label for the ADR
2192/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002193OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002194AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2195 SMLoc S = getLoc();
2196 const MCExpr *Expr;
2197
Nirav Davee833c6c2016-11-08 18:31:04 +00002198 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002199 if (getParser().parseExpression(Expr))
2200 return MatchOperand_ParseFail;
2201
2202 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2203 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2204
2205 return MatchOperand_Success;
2206}
2207
2208/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002209OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002210AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002211 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002212 SMLoc S = getLoc();
2213
Nirav Davee833c6c2016-11-08 18:31:04 +00002214 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002215
2216 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002217 bool isNegative = parseOptionalToken(AsmToken::Minus);
2218
Tim Northover3b0846e2014-05-24 12:50:23 +00002219 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002220 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002221 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002222 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002223 Val = Tok.getIntVal();
2224 if (Val > 255 || Val < 0) {
2225 TokError("encoded floating point value out of range");
2226 return MatchOperand_ParseFail;
2227 }
2228 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002229 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002230 if (isNegative)
2231 RealVal.changeSign();
2232
Tim Northover3b0846e2014-05-24 12:50:23 +00002233 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002234 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002235
John Brawn5ca5daa2017-04-20 10:13:54 +00002236 // Check for out of range values. As an exception we let Zero through,
2237 // but as tokens instead of an FPImm so that it can be matched by the
2238 // appropriate alias if one exists.
2239 if (RealVal.isPosZero()) {
2240 Parser.Lex(); // Eat the token.
2241 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2242 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2243 return MatchOperand_Success;
2244 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002245 TokError("expected compatible register or floating-point constant");
2246 return MatchOperand_ParseFail;
2247 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002248 }
2249 Parser.Lex(); // Eat the token.
2250 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2251 return MatchOperand_Success;
2252 }
2253
2254 if (!Hash)
2255 return MatchOperand_NoMatch;
2256
2257 TokError("invalid floating point immediate");
2258 return MatchOperand_ParseFail;
2259}
2260
2261/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002262OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002263AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002264 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002265 SMLoc S = getLoc();
2266
2267 if (Parser.getTok().is(AsmToken::Hash))
2268 Parser.Lex(); // Eat '#'
2269 else if (Parser.getTok().isNot(AsmToken::Integer))
2270 // Operand should start from # or should be integer, emit error otherwise.
2271 return MatchOperand_NoMatch;
2272
2273 const MCExpr *Imm;
2274 if (parseSymbolicImmVal(Imm))
2275 return MatchOperand_ParseFail;
2276 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2277 uint64_t ShiftAmount = 0;
2278 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2279 if (MCE) {
2280 int64_t Val = MCE->getValue();
2281 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002282 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002283 ShiftAmount = 12;
2284 }
2285 }
2286 SMLoc E = Parser.getTok().getLoc();
2287 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2288 getContext()));
2289 return MatchOperand_Success;
2290 }
2291
2292 // Eat ','
2293 Parser.Lex();
2294
2295 // The optional operand must be "lsl #N" where N is non-negative.
2296 if (!Parser.getTok().is(AsmToken::Identifier) ||
2297 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2298 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2299 return MatchOperand_ParseFail;
2300 }
2301
2302 // Eat 'lsl'
2303 Parser.Lex();
2304
Nirav Davee833c6c2016-11-08 18:31:04 +00002305 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002306
2307 if (Parser.getTok().isNot(AsmToken::Integer)) {
2308 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2309 return MatchOperand_ParseFail;
2310 }
2311
2312 int64_t ShiftAmount = Parser.getTok().getIntVal();
2313
2314 if (ShiftAmount < 0) {
2315 Error(Parser.getTok().getLoc(), "positive shift amount required");
2316 return MatchOperand_ParseFail;
2317 }
2318 Parser.Lex(); // Eat the number
2319
2320 SMLoc E = Parser.getTok().getLoc();
2321 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2322 S, E, getContext()));
2323 return MatchOperand_Success;
2324}
2325
2326/// parseCondCodeString - Parse a Condition Code string.
2327AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2328 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2329 .Case("eq", AArch64CC::EQ)
2330 .Case("ne", AArch64CC::NE)
2331 .Case("cs", AArch64CC::HS)
2332 .Case("hs", AArch64CC::HS)
2333 .Case("cc", AArch64CC::LO)
2334 .Case("lo", AArch64CC::LO)
2335 .Case("mi", AArch64CC::MI)
2336 .Case("pl", AArch64CC::PL)
2337 .Case("vs", AArch64CC::VS)
2338 .Case("vc", AArch64CC::VC)
2339 .Case("hi", AArch64CC::HI)
2340 .Case("ls", AArch64CC::LS)
2341 .Case("ge", AArch64CC::GE)
2342 .Case("lt", AArch64CC::LT)
2343 .Case("gt", AArch64CC::GT)
2344 .Case("le", AArch64CC::LE)
2345 .Case("al", AArch64CC::AL)
2346 .Case("nv", AArch64CC::NV)
2347 .Default(AArch64CC::Invalid);
2348 return CC;
2349}
2350
2351/// parseCondCode - Parse a Condition Code operand.
2352bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2353 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002354 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002355 SMLoc S = getLoc();
2356 const AsmToken &Tok = Parser.getTok();
2357 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2358
2359 StringRef Cond = Tok.getString();
2360 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2361 if (CC == AArch64CC::Invalid)
2362 return TokError("invalid condition code");
2363 Parser.Lex(); // Eat identifier token.
2364
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002365 if (invertCondCode) {
2366 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2367 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002368 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002369 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002370
2371 Operands.push_back(
2372 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2373 return false;
2374}
2375
2376/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2377/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002378OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002379AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002380 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002381 const AsmToken &Tok = Parser.getTok();
2382 std::string LowerID = Tok.getString().lower();
2383 AArch64_AM::ShiftExtendType ShOp =
2384 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2385 .Case("lsl", AArch64_AM::LSL)
2386 .Case("lsr", AArch64_AM::LSR)
2387 .Case("asr", AArch64_AM::ASR)
2388 .Case("ror", AArch64_AM::ROR)
2389 .Case("msl", AArch64_AM::MSL)
2390 .Case("uxtb", AArch64_AM::UXTB)
2391 .Case("uxth", AArch64_AM::UXTH)
2392 .Case("uxtw", AArch64_AM::UXTW)
2393 .Case("uxtx", AArch64_AM::UXTX)
2394 .Case("sxtb", AArch64_AM::SXTB)
2395 .Case("sxth", AArch64_AM::SXTH)
2396 .Case("sxtw", AArch64_AM::SXTW)
2397 .Case("sxtx", AArch64_AM::SXTX)
2398 .Default(AArch64_AM::InvalidShiftExtend);
2399
2400 if (ShOp == AArch64_AM::InvalidShiftExtend)
2401 return MatchOperand_NoMatch;
2402
2403 SMLoc S = Tok.getLoc();
2404 Parser.Lex();
2405
Nirav Davee833c6c2016-11-08 18:31:04 +00002406 bool Hash = parseOptionalToken(AsmToken::Hash);
2407
Tim Northover3b0846e2014-05-24 12:50:23 +00002408 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2409 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2410 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2411 ShOp == AArch64_AM::MSL) {
2412 // We expect a number here.
2413 TokError("expected #imm after shift specifier");
2414 return MatchOperand_ParseFail;
2415 }
2416
Chad Rosier2ff37b82016-12-27 16:58:09 +00002417 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002418 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2419 Operands.push_back(
2420 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2421 return MatchOperand_Success;
2422 }
2423
Chad Rosier2ff37b82016-12-27 16:58:09 +00002424 // Make sure we do actually have a number, identifier or a parenthesized
2425 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002426 SMLoc E = Parser.getTok().getLoc();
2427 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002428 !Parser.getTok().is(AsmToken::LParen) &&
2429 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002430 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002431 return MatchOperand_ParseFail;
2432 }
2433
2434 const MCExpr *ImmVal;
2435 if (getParser().parseExpression(ImmVal))
2436 return MatchOperand_ParseFail;
2437
2438 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2439 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002440 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002441 return MatchOperand_ParseFail;
2442 }
2443
Jim Grosbach57fd2622014-09-23 22:16:02 +00002444 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002445 Operands.push_back(AArch64Operand::CreateShiftExtend(
2446 ShOp, MCE->getValue(), true, S, E, getContext()));
2447 return MatchOperand_Success;
2448}
2449
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002450static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2451 if (FBS[AArch64::HasV8_1aOps])
2452 Str += "ARMv8.1a";
2453 else if (FBS[AArch64::HasV8_2aOps])
2454 Str += "ARMv8.2a";
2455 else
2456 Str += "(unknown)";
2457}
2458
2459void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2460 SMLoc S) {
2461 const uint16_t Op2 = Encoding & 7;
2462 const uint16_t Cm = (Encoding & 0x78) >> 3;
2463 const uint16_t Cn = (Encoding & 0x780) >> 7;
2464 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2465
2466 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2467
2468 Operands.push_back(
2469 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2470 Operands.push_back(
2471 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2472 Operands.push_back(
2473 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2474 Expr = MCConstantExpr::create(Op2, getContext());
2475 Operands.push_back(
2476 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2477}
2478
Tim Northover3b0846e2014-05-24 12:50:23 +00002479/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2480/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2481bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2482 OperandVector &Operands) {
2483 if (Name.find('.') != StringRef::npos)
2484 return TokError("invalid operand");
2485
2486 Mnemonic = Name;
2487 Operands.push_back(
2488 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2489
Rafael Espindola961d4692014-11-11 05:18:41 +00002490 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002491 const AsmToken &Tok = Parser.getTok();
2492 StringRef Op = Tok.getString();
2493 SMLoc S = Tok.getLoc();
2494
Tim Northover3b0846e2014-05-24 12:50:23 +00002495 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002496 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2497 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002498 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002499 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2500 std::string Str("IC " + std::string(IC->Name) + " requires ");
2501 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2502 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002503 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002504 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002505 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002506 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2507 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002508 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002509 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2510 std::string Str("DC " + std::string(DC->Name) + " requires ");
2511 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2512 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002513 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002514 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002515 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002516 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2517 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002518 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002519 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2520 std::string Str("AT " + std::string(AT->Name) + " requires ");
2521 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2522 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002523 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002524 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002525 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002526 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2527 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002528 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002529 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2530 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2531 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2532 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002533 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002534 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002535 }
2536
Tim Northover3b0846e2014-05-24 12:50:23 +00002537 Parser.Lex(); // Eat operand.
2538
2539 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2540 bool HasRegister = false;
2541
2542 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002543 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002544 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2545 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002546 HasRegister = true;
2547 }
2548
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002549 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002550 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002551 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002552 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002553
Nirav Davee833c6c2016-11-08 18:31:04 +00002554 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2555 return true;
2556
Tim Northover3b0846e2014-05-24 12:50:23 +00002557 return false;
2558}
2559
Alex Bradbury58eba092016-11-01 16:32:05 +00002560OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002561AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002562 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002563 const AsmToken &Tok = Parser.getTok();
2564
2565 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002566 if (parseOptionalToken(AsmToken::Hash) ||
2567 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002568 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002569 const MCExpr *ImmVal;
2570 SMLoc ExprLoc = getLoc();
2571 if (getParser().parseExpression(ImmVal))
2572 return MatchOperand_ParseFail;
2573 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2574 if (!MCE) {
2575 Error(ExprLoc, "immediate value expected for barrier operand");
2576 return MatchOperand_ParseFail;
2577 }
2578 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2579 Error(ExprLoc, "barrier operand out of range");
2580 return MatchOperand_ParseFail;
2581 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002582 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2583 Operands.push_back(AArch64Operand::CreateBarrier(
2584 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002585 return MatchOperand_Success;
2586 }
2587
2588 if (Tok.isNot(AsmToken::Identifier)) {
2589 TokError("invalid operand for instruction");
2590 return MatchOperand_ParseFail;
2591 }
2592
Tim Northover3b0846e2014-05-24 12:50:23 +00002593 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002594 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2595 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002596 TokError("'sy' or #imm operand expected");
2597 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002598 } else if (!DB) {
2599 TokError("invalid barrier option name");
2600 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002601 }
2602
Tim Northovere6ae6762016-07-05 21:23:04 +00002603 Operands.push_back(AArch64Operand::CreateBarrier(
2604 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002605 Parser.Lex(); // Consume the option
2606
2607 return MatchOperand_Success;
2608}
2609
Alex Bradbury58eba092016-11-01 16:32:05 +00002610OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002611AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002612 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002613 const AsmToken &Tok = Parser.getTok();
2614
2615 if (Tok.isNot(AsmToken::Identifier))
2616 return MatchOperand_NoMatch;
2617
Tim Northovere6ae6762016-07-05 21:23:04 +00002618 int MRSReg, MSRReg;
2619 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2620 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2621 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2622 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2623 } else
2624 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002625
Tim Northovere6ae6762016-07-05 21:23:04 +00002626 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2627 unsigned PStateImm = -1;
2628 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2629 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002630
Tim Northovere6ae6762016-07-05 21:23:04 +00002631 Operands.push_back(
2632 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2633 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002634 Parser.Lex(); // Eat identifier
2635
2636 return MatchOperand_Success;
2637}
2638
Florian Hahnc4422242017-11-07 13:07:50 +00002639/// tryParseNeonVectorRegister - Parse a vector register operand.
2640bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002641 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002642 if (Parser.getTok().isNot(AsmToken::Identifier))
2643 return true;
2644
2645 SMLoc S = getLoc();
2646 // Check for a vector register specifier first.
2647 StringRef Kind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002648 int Reg = -1;
2649 OperandMatchResultTy Res =
2650 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2651 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002652 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002653
2654 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2655 if (!KindRes)
2656 return true;
2657
2658 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002659 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002660 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2661 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002662
Tim Northover3b0846e2014-05-24 12:50:23 +00002663 // If there was an explicit qualifier, that goes on as a literal text
2664 // operand.
2665 if (!Kind.empty())
2666 Operands.push_back(
2667 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2668
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002669 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2670}
2671
2672OperandMatchResultTy
2673AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002674 SMLoc SIdx = getLoc();
2675 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002676 const MCExpr *ImmVal;
2677 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002678 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002679 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2680 if (!MCE) {
2681 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002682 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002683 }
2684
2685 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002686
Nirav Davee833c6c2016-11-08 18:31:04 +00002687 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002688 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002689
2690 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2691 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002692 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002693 }
2694
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002695 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002696}
2697
Sander de Smalen73937b72018-04-11 07:36:10 +00002698// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002699// optional kind specifier. If it is a register specifier, eat the token
2700// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002701OperandMatchResultTy
Sander de Smalen73937b72018-04-11 07:36:10 +00002702AArch64AsmParser::tryParseVectorRegister(int &Reg, StringRef &Kind,
2703 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002704 MCAsmParser &Parser = getParser();
2705 const AsmToken &Tok = Parser.getTok();
2706
Florian Hahn91f11e52017-11-07 16:45:48 +00002707 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002708 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002709
2710 StringRef Name = Tok.getString();
2711 // If there is a kind specifier, it's separated from the register name by
2712 // a '.'.
2713 size_t Start = 0, Next = Name.find('.');
2714 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002715 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002716
2717 if (RegNum) {
2718 if (Next != StringRef::npos) {
2719 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002720 if (!isValidVectorKind(Kind, MatchKind)) {
2721 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002722 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002723 }
2724 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002725 Parser.Lex(); // Eat the register token.
2726
2727 Reg = RegNum;
2728 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002729 }
2730
Sander de Smalen8e607342017-11-15 15:44:43 +00002731 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002732}
2733
Sander de Smalencd6be962017-12-20 11:02:42 +00002734/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2735OperandMatchResultTy
2736AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2737 // Check for a SVE predicate register specifier first.
2738 const SMLoc S = getLoc();
2739 StringRef Kind;
2740 int RegNum = -1;
Sander de Smalen73937b72018-04-11 07:36:10 +00002741 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002742 if (Res != MatchOperand_Success)
2743 return Res;
2744
Sander de Smalen73937b72018-04-11 07:36:10 +00002745 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2746 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002747 return MatchOperand_NoMatch;
2748
Sander de Smalen73937b72018-04-11 07:36:10 +00002749 unsigned ElementWidth = KindRes->second;
2750 Operands.push_back(AArch64Operand::CreateVectorReg(
2751 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2752 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002753
Sander de Smalen7868e742018-01-09 11:17:06 +00002754 // Not all predicates are followed by a '/m' or '/z'.
2755 MCAsmParser &Parser = getParser();
2756 if (Parser.getTok().isNot(AsmToken::Slash))
2757 return MatchOperand_Success;
2758
2759 // But when they do they shouldn't have an element type suffix.
2760 if (!Kind.empty()) {
2761 Error(S, "not expecting size suffix");
2762 return MatchOperand_ParseFail;
2763 }
2764
2765 // Add a literal slash as operand
2766 Operands.push_back(
2767 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2768
2769 Parser.Lex(); // Eat the slash.
2770
2771 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002772 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002773 if (Pred != "z" && Pred != "m") {
2774 Error(getLoc(), "expecting 'm' or 'z' predication");
2775 return MatchOperand_ParseFail;
2776 }
2777
2778 // Add zero/merge token.
2779 const char *ZM = Pred == "z" ? "z" : "m";
2780 Operands.push_back(
2781 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2782
2783 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002784 return MatchOperand_Success;
2785}
2786
Tim Northover3b0846e2014-05-24 12:50:23 +00002787/// parseRegister - Parse a non-vector register operand.
2788bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2789 SMLoc S = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00002790 // Try for a vector (neon) register.
2791 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002792 return false;
2793
2794 // Try for a scalar register.
2795 int64_t Reg = tryParseRegister();
2796 if (Reg == -1)
2797 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002798 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2799 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002800
Tim Northover3b0846e2014-05-24 12:50:23 +00002801 return false;
2802}
2803
2804bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002805 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002806 bool HasELFModifier = false;
2807 AArch64MCExpr::VariantKind RefKind;
2808
Nirav Davee833c6c2016-11-08 18:31:04 +00002809 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002810 HasELFModifier = true;
2811
Nirav Davee833c6c2016-11-08 18:31:04 +00002812 if (Parser.getTok().isNot(AsmToken::Identifier))
2813 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002814
2815 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2816 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2817 .Case("lo12", AArch64MCExpr::VK_LO12)
2818 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2819 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2820 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2821 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2822 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2823 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2824 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2825 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2826 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2827 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2828 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2829 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2830 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2831 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2832 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2833 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2834 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2835 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2836 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2837 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2838 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2839 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2840 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2841 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2842 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2843 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2844 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2845 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2846 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2847 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2848 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2849 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2850 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2851 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002852 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2853 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002854 .Default(AArch64MCExpr::VK_INVALID);
2855
Nirav Davee833c6c2016-11-08 18:31:04 +00002856 if (RefKind == AArch64MCExpr::VK_INVALID)
2857 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002858
2859 Parser.Lex(); // Eat identifier
2860
Nirav Davee833c6c2016-11-08 18:31:04 +00002861 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002862 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002863 }
2864
2865 if (getParser().parseExpression(ImmVal))
2866 return true;
2867
2868 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002869 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002870
2871 return false;
2872}
2873
Sander de Smalen650234b2018-04-12 11:40:52 +00002874template <RegKind VectorKind>
2875OperandMatchResultTy
2876AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
2877 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002878 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00002879 if (!Parser.getTok().is(AsmToken::LCurly))
2880 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002881
2882 // Wrapper around parse function
Sander de Smalen650234b2018-04-12 11:40:52 +00002883 auto ParseVector = [this, &Parser](int &Reg, StringRef &Kind, SMLoc Loc,
2884 bool NoMatchIsError) {
2885 auto RegTok = Parser.getTok();
2886 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
2887 if (ParseRes == MatchOperand_Success) {
Sander de Smalen73937b72018-04-11 07:36:10 +00002888 if (parseVectorKind(Kind, RegKind::NeonVector))
Sander de Smalen650234b2018-04-12 11:40:52 +00002889 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002890 llvm_unreachable("Expected a valid vector kind");
2891 }
2892
Sander de Smalen650234b2018-04-12 11:40:52 +00002893 if (RegTok.isNot(AsmToken::Identifier) ||
2894 ParseRes == MatchOperand_ParseFail ||
2895 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
2896 Error(Loc, "vector register expected");
2897 return MatchOperand_ParseFail;
2898 }
2899
2900 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002901 };
2902
Tim Northover3b0846e2014-05-24 12:50:23 +00002903 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00002904 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00002905 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00002906
Tim Northover3b0846e2014-05-24 12:50:23 +00002907 StringRef Kind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002908 int FirstReg = -1;
Sander de Smalen650234b2018-04-12 11:40:52 +00002909 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
2910
2911 // Put back the original left bracket if there was no match, so that
2912 // different types of list-operands can be matched (e.g. SVE, Neon).
2913 if (ParseRes == MatchOperand_NoMatch)
2914 Parser.getLexer().UnLex(LCurly);
2915
2916 if (ParseRes != MatchOperand_Success)
2917 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002918
Tim Northover3b0846e2014-05-24 12:50:23 +00002919 int64_t PrevReg = FirstReg;
2920 unsigned Count = 1;
2921
Nirav Davee833c6c2016-11-08 18:31:04 +00002922 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002923 SMLoc Loc = getLoc();
2924 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002925
2926 int Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002927 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2928 if (ParseRes != MatchOperand_Success)
2929 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002930
Tim Northover3b0846e2014-05-24 12:50:23 +00002931 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002932 if (Kind != NextKind) {
2933 Error(Loc, "mismatched register size suffix");
2934 return MatchOperand_ParseFail;
2935 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002936
2937 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2938
2939 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002940 Error(Loc, "invalid number of vectors");
2941 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002942 }
2943
2944 Count += Space;
2945 }
2946 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002947 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002948 SMLoc Loc = getLoc();
2949 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002950 int Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002951 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2952 if (ParseRes != MatchOperand_Success)
2953 return ParseRes;
2954
Tim Northover3b0846e2014-05-24 12:50:23 +00002955 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002956 if (Kind != NextKind) {
2957 Error(Loc, "mismatched register size suffix");
2958 return MatchOperand_ParseFail;
2959 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002960
2961 // Registers must be incremental (with wraparound at 31)
2962 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00002963 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
2964 Error(Loc, "registers must be sequential");
2965 return MatchOperand_ParseFail;
2966 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002967
2968 PrevReg = Reg;
2969 ++Count;
2970 }
2971 }
2972
Nirav Davee833c6c2016-11-08 18:31:04 +00002973 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00002974 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002975
Sander de Smalen650234b2018-04-12 11:40:52 +00002976 if (Count > 4) {
2977 Error(S, "invalid number of vectors");
2978 return MatchOperand_ParseFail;
2979 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002980
2981 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00002982 unsigned ElementWidth = 0;
2983 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002984 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00002985 std::tie(NumElements, ElementWidth) = *VK;
2986 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002987
2988 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00002989 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
2990 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002991
Sander de Smalen650234b2018-04-12 11:40:52 +00002992 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002993}
2994
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002995/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
2996bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002997 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
2998 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002999 return true;
3000
3001 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3002}
3003
Alex Bradbury58eba092016-11-01 16:32:05 +00003004OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003005AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003006 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003007 const AsmToken &Tok = Parser.getTok();
3008 if (!Tok.is(AsmToken::Identifier))
3009 return MatchOperand_NoMatch;
3010
Florian Hahnc4422242017-11-07 13:07:50 +00003011 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00003012
3013 MCContext &Ctx = getContext();
3014 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
3015 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
3016 return MatchOperand_NoMatch;
3017
3018 SMLoc S = getLoc();
3019 Parser.Lex(); // Eat register
3020
Nirav Davee833c6c2016-11-08 18:31:04 +00003021 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003022 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003023 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003024 return MatchOperand_Success;
3025 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003026
Nirav Davee833c6c2016-11-08 18:31:04 +00003027 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003028
3029 if (Parser.getTok().isNot(AsmToken::Integer)) {
3030 Error(getLoc(), "index must be absent or #0");
3031 return MatchOperand_ParseFail;
3032 }
3033
3034 const MCExpr *ImmVal;
3035 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3036 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3037 Error(getLoc(), "index must be absent or #0");
3038 return MatchOperand_ParseFail;
3039 }
3040
3041 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003042 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003043 return MatchOperand_Success;
3044}
3045
3046/// parseOperand - Parse a arm instruction operand. For now this parses the
3047/// operand regardless of the mnemonic.
3048bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3049 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003050 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003051
3052 OperandMatchResultTy ResTy =
3053 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3054
Tim Northover3b0846e2014-05-24 12:50:23 +00003055 // Check if the current operand has a custom associated parser, if so, try to
3056 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003057 if (ResTy == MatchOperand_Success)
3058 return false;
3059 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3060 // there was a match, but an error occurred, in which case, just return that
3061 // the operand parsing failed.
3062 if (ResTy == MatchOperand_ParseFail)
3063 return true;
3064
3065 // Nothing custom, so do general case parsing.
3066 SMLoc S, E;
3067 switch (getLexer().getKind()) {
3068 default: {
3069 SMLoc S = getLoc();
3070 const MCExpr *Expr;
3071 if (parseSymbolicImmVal(Expr))
3072 return Error(S, "invalid operand");
3073
3074 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3075 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3076 return false;
3077 }
3078 case AsmToken::LBrac: {
3079 SMLoc Loc = Parser.getTok().getLoc();
3080 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3081 getContext()));
3082 Parser.Lex(); // Eat '['
3083
3084 // There's no comma after a '[', so we can parse the next operand
3085 // immediately.
3086 return parseOperand(Operands, false, false);
3087 }
3088 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003089 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003090 case AsmToken::Identifier: {
3091 // If we're expecting a Condition Code operand, then just parse that.
3092 if (isCondCode)
3093 return parseCondCode(Operands, invertCondCode);
3094
3095 // If it's a register name, parse it.
3096 if (!parseRegister(Operands))
3097 return false;
3098
3099 // This could be an optional "shift" or "extend" operand.
3100 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3101 // We can only continue if no tokens were eaten.
3102 if (GotShift != MatchOperand_NoMatch)
3103 return GotShift;
3104
3105 // This was not a register so parse other operands that start with an
3106 // identifier (like labels) as expressions and create them as immediates.
3107 const MCExpr *IdVal;
3108 S = getLoc();
3109 if (getParser().parseExpression(IdVal))
3110 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003111 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3112 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3113 return false;
3114 }
3115 case AsmToken::Integer:
3116 case AsmToken::Real:
3117 case AsmToken::Hash: {
3118 // #42 -> immediate.
3119 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003120
3121 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003122
3123 // Parse a negative sign
3124 bool isNegative = false;
3125 if (Parser.getTok().is(AsmToken::Minus)) {
3126 isNegative = true;
3127 // We need to consume this token only when we have a Real, otherwise
3128 // we let parseSymbolicImmVal take care of it
3129 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3130 Parser.Lex();
3131 }
3132
3133 // The only Real that should come through here is a literal #0.0 for
3134 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3135 // so convert the value.
3136 const AsmToken &Tok = Parser.getTok();
3137 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003138 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003139 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3140 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3141 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3142 Mnemonic != "fcmlt")
3143 return TokError("unexpected floating point literal");
3144 else if (IntVal != 0 || isNegative)
3145 return TokError("expected floating-point constant #0.0");
3146 Parser.Lex(); // Eat the token.
3147
3148 Operands.push_back(
3149 AArch64Operand::CreateToken("#0", false, S, getContext()));
3150 Operands.push_back(
3151 AArch64Operand::CreateToken(".0", false, S, getContext()));
3152 return false;
3153 }
3154
3155 const MCExpr *ImmVal;
3156 if (parseSymbolicImmVal(ImmVal))
3157 return true;
3158
3159 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3160 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3161 return false;
3162 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003163 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003164 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003165 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003166 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003167 Parser.Lex(); // Eat '='
3168 const MCExpr *SubExprVal;
3169 if (getParser().parseExpression(SubExprVal))
3170 return true;
3171
David Peixottoae5ba762014-07-18 16:05:14 +00003172 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003173 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003174 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003175
3176 bool IsXReg =
3177 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3178 Operands[1]->getReg());
3179
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003180 MCContext& Ctx = getContext();
3181 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3182 // 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 +00003183 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003184 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3185 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3186 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3187 ShiftAmt += 16;
3188 Imm >>= 16;
3189 }
3190 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3191 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3192 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003193 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003194 if (ShiftAmt)
3195 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3196 ShiftAmt, true, S, E, Ctx));
3197 return false;
3198 }
David Peixottoae5ba762014-07-18 16:05:14 +00003199 APInt Simm = APInt(64, Imm << ShiftAmt);
3200 // check if the immediate is an unsigned or signed 32-bit int for W regs
3201 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3202 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003203 }
3204 // 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 +00003205 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003206 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003207 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3208 return false;
3209 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003210 }
3211}
3212
3213/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3214/// operands.
3215bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3216 StringRef Name, SMLoc NameLoc,
3217 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003218 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003219 Name = StringSwitch<StringRef>(Name.lower())
3220 .Case("beq", "b.eq")
3221 .Case("bne", "b.ne")
3222 .Case("bhs", "b.hs")
3223 .Case("bcs", "b.cs")
3224 .Case("blo", "b.lo")
3225 .Case("bcc", "b.cc")
3226 .Case("bmi", "b.mi")
3227 .Case("bpl", "b.pl")
3228 .Case("bvs", "b.vs")
3229 .Case("bvc", "b.vc")
3230 .Case("bhi", "b.hi")
3231 .Case("bls", "b.ls")
3232 .Case("bge", "b.ge")
3233 .Case("blt", "b.lt")
3234 .Case("bgt", "b.gt")
3235 .Case("ble", "b.le")
3236 .Case("bal", "b.al")
3237 .Case("bnv", "b.nv")
3238 .Default(Name);
3239
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003240 // First check for the AArch64-specific .req directive.
3241 if (Parser.getTok().is(AsmToken::Identifier) &&
3242 Parser.getTok().getIdentifier() == ".req") {
3243 parseDirectiveReq(Name, NameLoc);
3244 // We always return 'error' for this, as we're done with this
3245 // statement and don't need to match the 'instruction."
3246 return true;
3247 }
3248
Tim Northover3b0846e2014-05-24 12:50:23 +00003249 // Create the leading tokens for the mnemonic, split by '.' characters.
3250 size_t Start = 0, Next = Name.find('.');
3251 StringRef Head = Name.slice(Start, Next);
3252
3253 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003254 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3255 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003256
3257 Operands.push_back(
3258 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3259 Mnemonic = Head;
3260
3261 // Handle condition codes for a branch mnemonic
3262 if (Head == "b" && Next != StringRef::npos) {
3263 Start = Next;
3264 Next = Name.find('.', Start + 1);
3265 Head = Name.slice(Start + 1, Next);
3266
3267 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3268 (Head.data() - Name.data()));
3269 AArch64CC::CondCode CC = parseCondCodeString(Head);
3270 if (CC == AArch64CC::Invalid)
3271 return Error(SuffixLoc, "invalid condition code");
3272 Operands.push_back(
3273 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3274 Operands.push_back(
3275 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3276 }
3277
3278 // Add the remaining tokens in the mnemonic.
3279 while (Next != StringRef::npos) {
3280 Start = Next;
3281 Next = Name.find('.', Start + 1);
3282 Head = Name.slice(Start, Next);
3283 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3284 (Head.data() - Name.data()) + 1);
3285 Operands.push_back(
3286 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3287 }
3288
3289 // Conditional compare instructions have a Condition Code operand, which needs
3290 // to be parsed and an immediate operand created.
3291 bool condCodeFourthOperand =
3292 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3293 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3294 Head == "csinc" || Head == "csinv" || Head == "csneg");
3295
3296 // These instructions are aliases to some of the conditional select
3297 // instructions. However, the condition code is inverted in the aliased
3298 // instruction.
3299 //
3300 // FIXME: Is this the correct way to handle these? Or should the parser
3301 // generate the aliased instructions directly?
3302 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3303 bool condCodeThirdOperand =
3304 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3305
3306 // Read the remaining operands.
3307 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3308 // Read the first operand.
3309 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003310 return true;
3311 }
3312
3313 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003314 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003315 // Parse and remember the operand.
3316 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3317 (N == 3 && condCodeThirdOperand) ||
3318 (N == 2 && condCodeSecondOperand),
3319 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003320 return true;
3321 }
3322
3323 // After successfully parsing some operands there are two special cases to
3324 // consider (i.e. notional operands not separated by commas). Both are due
3325 // to memory specifiers:
3326 // + An RBrac will end an address for load/store/prefetch
3327 // + An '!' will indicate a pre-indexed operation.
3328 //
3329 // It's someone else's responsibility to make sure these tokens are sane
3330 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003331
Nirav Davee833c6c2016-11-08 18:31:04 +00003332 SMLoc RLoc = Parser.getTok().getLoc();
3333 if (parseOptionalToken(AsmToken::RBrac))
3334 Operands.push_back(
3335 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3336 SMLoc ELoc = Parser.getTok().getLoc();
3337 if (parseOptionalToken(AsmToken::Exclaim))
3338 Operands.push_back(
3339 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003340
3341 ++N;
3342 }
3343 }
3344
Nirav Davee833c6c2016-11-08 18:31:04 +00003345 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3346 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003347
Tim Northover3b0846e2014-05-24 12:50:23 +00003348 return false;
3349}
3350
3351// FIXME: This entire function is a giant hack to provide us with decent
3352// operand range validation/diagnostics until TableGen/MC can be extended
3353// to support autogeneration of this kind of validation.
3354bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3355 SmallVectorImpl<SMLoc> &Loc) {
3356 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3357 // Check for indexed addressing modes w/ the base register being the
3358 // same as a destination/source register or pair load where
3359 // the Rt == Rt2. All of those are undefined behaviour.
3360 switch (Inst.getOpcode()) {
3361 case AArch64::LDPSWpre:
3362 case AArch64::LDPWpost:
3363 case AArch64::LDPWpre:
3364 case AArch64::LDPXpost:
3365 case AArch64::LDPXpre: {
3366 unsigned Rt = Inst.getOperand(1).getReg();
3367 unsigned Rt2 = Inst.getOperand(2).getReg();
3368 unsigned Rn = Inst.getOperand(3).getReg();
3369 if (RI->isSubRegisterEq(Rn, Rt))
3370 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3371 "is also a destination");
3372 if (RI->isSubRegisterEq(Rn, Rt2))
3373 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3374 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003375 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003376 }
3377 case AArch64::LDPDi:
3378 case AArch64::LDPQi:
3379 case AArch64::LDPSi:
3380 case AArch64::LDPSWi:
3381 case AArch64::LDPWi:
3382 case AArch64::LDPXi: {
3383 unsigned Rt = Inst.getOperand(0).getReg();
3384 unsigned Rt2 = Inst.getOperand(1).getReg();
3385 if (Rt == Rt2)
3386 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3387 break;
3388 }
3389 case AArch64::LDPDpost:
3390 case AArch64::LDPDpre:
3391 case AArch64::LDPQpost:
3392 case AArch64::LDPQpre:
3393 case AArch64::LDPSpost:
3394 case AArch64::LDPSpre:
3395 case AArch64::LDPSWpost: {
3396 unsigned Rt = Inst.getOperand(1).getReg();
3397 unsigned Rt2 = Inst.getOperand(2).getReg();
3398 if (Rt == Rt2)
3399 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3400 break;
3401 }
3402 case AArch64::STPDpost:
3403 case AArch64::STPDpre:
3404 case AArch64::STPQpost:
3405 case AArch64::STPQpre:
3406 case AArch64::STPSpost:
3407 case AArch64::STPSpre:
3408 case AArch64::STPWpost:
3409 case AArch64::STPWpre:
3410 case AArch64::STPXpost:
3411 case AArch64::STPXpre: {
3412 unsigned Rt = Inst.getOperand(1).getReg();
3413 unsigned Rt2 = Inst.getOperand(2).getReg();
3414 unsigned Rn = Inst.getOperand(3).getReg();
3415 if (RI->isSubRegisterEq(Rn, Rt))
3416 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3417 "is also a source");
3418 if (RI->isSubRegisterEq(Rn, Rt2))
3419 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3420 "is also a source");
3421 break;
3422 }
3423 case AArch64::LDRBBpre:
3424 case AArch64::LDRBpre:
3425 case AArch64::LDRHHpre:
3426 case AArch64::LDRHpre:
3427 case AArch64::LDRSBWpre:
3428 case AArch64::LDRSBXpre:
3429 case AArch64::LDRSHWpre:
3430 case AArch64::LDRSHXpre:
3431 case AArch64::LDRSWpre:
3432 case AArch64::LDRWpre:
3433 case AArch64::LDRXpre:
3434 case AArch64::LDRBBpost:
3435 case AArch64::LDRBpost:
3436 case AArch64::LDRHHpost:
3437 case AArch64::LDRHpost:
3438 case AArch64::LDRSBWpost:
3439 case AArch64::LDRSBXpost:
3440 case AArch64::LDRSHWpost:
3441 case AArch64::LDRSHXpost:
3442 case AArch64::LDRSWpost:
3443 case AArch64::LDRWpost:
3444 case AArch64::LDRXpost: {
3445 unsigned Rt = Inst.getOperand(1).getReg();
3446 unsigned Rn = Inst.getOperand(2).getReg();
3447 if (RI->isSubRegisterEq(Rn, Rt))
3448 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3449 "is also a source");
3450 break;
3451 }
3452 case AArch64::STRBBpost:
3453 case AArch64::STRBpost:
3454 case AArch64::STRHHpost:
3455 case AArch64::STRHpost:
3456 case AArch64::STRWpost:
3457 case AArch64::STRXpost:
3458 case AArch64::STRBBpre:
3459 case AArch64::STRBpre:
3460 case AArch64::STRHHpre:
3461 case AArch64::STRHpre:
3462 case AArch64::STRWpre:
3463 case AArch64::STRXpre: {
3464 unsigned Rt = Inst.getOperand(1).getReg();
3465 unsigned Rn = Inst.getOperand(2).getReg();
3466 if (RI->isSubRegisterEq(Rn, Rt))
3467 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3468 "is also a source");
3469 break;
3470 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003471 case AArch64::STXRB:
3472 case AArch64::STXRH:
3473 case AArch64::STXRW:
3474 case AArch64::STXRX:
3475 case AArch64::STLXRB:
3476 case AArch64::STLXRH:
3477 case AArch64::STLXRW:
3478 case AArch64::STLXRX: {
3479 unsigned Rs = Inst.getOperand(0).getReg();
3480 unsigned Rt = Inst.getOperand(1).getReg();
3481 unsigned Rn = Inst.getOperand(2).getReg();
3482 if (RI->isSubRegisterEq(Rt, Rs) ||
3483 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3484 return Error(Loc[0],
3485 "unpredictable STXR instruction, status is also a source");
3486 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003487 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003488 case AArch64::STXPW:
3489 case AArch64::STXPX:
3490 case AArch64::STLXPW:
3491 case AArch64::STLXPX: {
3492 unsigned Rs = Inst.getOperand(0).getReg();
3493 unsigned Rt1 = Inst.getOperand(1).getReg();
3494 unsigned Rt2 = Inst.getOperand(2).getReg();
3495 unsigned Rn = Inst.getOperand(3).getReg();
3496 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3497 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3498 return Error(Loc[0],
3499 "unpredictable STXP instruction, status is also a source");
3500 break;
3501 }
3502 }
3503
Tim Northover3b0846e2014-05-24 12:50:23 +00003504
3505 // Now check immediate ranges. Separate from the above as there is overlap
3506 // in the instructions being checked and this keeps the nested conditionals
3507 // to a minimum.
3508 switch (Inst.getOpcode()) {
3509 case AArch64::ADDSWri:
3510 case AArch64::ADDSXri:
3511 case AArch64::ADDWri:
3512 case AArch64::ADDXri:
3513 case AArch64::SUBSWri:
3514 case AArch64::SUBSXri:
3515 case AArch64::SUBWri:
3516 case AArch64::SUBXri: {
3517 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3518 // some slight duplication here.
3519 if (Inst.getOperand(2).isExpr()) {
3520 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3521 AArch64MCExpr::VariantKind ELFRefKind;
3522 MCSymbolRefExpr::VariantKind DarwinRefKind;
3523 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003524 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3525
3526 // Only allow these with ADDXri.
3527 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3528 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3529 Inst.getOpcode() == AArch64::ADDXri)
3530 return false;
3531
3532 // Only allow these with ADDXri/ADDWri
3533 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3534 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3535 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3536 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3537 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3538 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3539 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003540 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3541 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3542 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003543 (Inst.getOpcode() == AArch64::ADDXri ||
3544 Inst.getOpcode() == AArch64::ADDWri))
3545 return false;
3546
3547 // Don't allow symbol refs in the immediate field otherwise
3548 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3549 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3550 // 'cmp w0, 'borked')
3551 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003552 }
Diana Picusc93518d2016-10-11 09:17:47 +00003553 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003554 }
3555 return false;
3556 }
3557 default:
3558 return false;
3559 }
3560}
3561
Craig Topper05515562017-10-26 06:46:41 +00003562static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3563 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003564
3565bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3566 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003567 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003568 case Match_InvalidTiedOperand:
3569 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003570 case Match_MissingFeature:
3571 return Error(Loc,
3572 "instruction requires a CPU feature not currently enabled");
3573 case Match_InvalidOperand:
3574 return Error(Loc, "invalid operand for instruction");
3575 case Match_InvalidSuffix:
3576 return Error(Loc, "invalid type suffix for instruction");
3577 case Match_InvalidCondCode:
3578 return Error(Loc, "expected AArch64 condition code");
3579 case Match_AddSubRegExtendSmall:
3580 return Error(Loc,
3581 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3582 case Match_AddSubRegExtendLarge:
3583 return Error(Loc,
3584 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3585 case Match_AddSubSecondSource:
3586 return Error(Loc,
3587 "expected compatible register, symbol or integer in range [0, 4095]");
3588 case Match_LogicalSecondSource:
3589 return Error(Loc, "expected compatible register or logical immediate");
3590 case Match_InvalidMovImm32Shift:
3591 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3592 case Match_InvalidMovImm64Shift:
3593 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3594 case Match_AddSubRegShift32:
3595 return Error(Loc,
3596 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3597 case Match_AddSubRegShift64:
3598 return Error(Loc,
3599 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3600 case Match_InvalidFPImm:
3601 return Error(Loc,
3602 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003603 case Match_InvalidMemoryIndexedSImm6:
3604 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003605 case Match_InvalidMemoryIndexedSImm5:
3606 return Error(Loc, "index must be an integer in range [-16, 15].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003607 case Match_InvalidMemoryIndexedSImm9:
3608 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003609 case Match_InvalidMemoryIndexedSImm10:
3610 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003611 case Match_InvalidMemoryIndexed4SImm7:
3612 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3613 case Match_InvalidMemoryIndexed8SImm7:
3614 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3615 case Match_InvalidMemoryIndexed16SImm7:
3616 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3617 case Match_InvalidMemoryWExtend8:
3618 return Error(Loc,
3619 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3620 case Match_InvalidMemoryWExtend16:
3621 return Error(Loc,
3622 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3623 case Match_InvalidMemoryWExtend32:
3624 return Error(Loc,
3625 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3626 case Match_InvalidMemoryWExtend64:
3627 return Error(Loc,
3628 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3629 case Match_InvalidMemoryWExtend128:
3630 return Error(Loc,
3631 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3632 case Match_InvalidMemoryXExtend8:
3633 return Error(Loc,
3634 "expected 'lsl' or 'sxtx' with optional shift of #0");
3635 case Match_InvalidMemoryXExtend16:
3636 return Error(Loc,
3637 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3638 case Match_InvalidMemoryXExtend32:
3639 return Error(Loc,
3640 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3641 case Match_InvalidMemoryXExtend64:
3642 return Error(Loc,
3643 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3644 case Match_InvalidMemoryXExtend128:
3645 return Error(Loc,
3646 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3647 case Match_InvalidMemoryIndexed1:
3648 return Error(Loc, "index must be an integer in range [0, 4095].");
3649 case Match_InvalidMemoryIndexed2:
3650 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3651 case Match_InvalidMemoryIndexed4:
3652 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3653 case Match_InvalidMemoryIndexed8:
3654 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3655 case Match_InvalidMemoryIndexed16:
3656 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003657 case Match_InvalidImm0_1:
3658 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003659 case Match_InvalidImm0_7:
3660 return Error(Loc, "immediate must be an integer in range [0, 7].");
3661 case Match_InvalidImm0_15:
3662 return Error(Loc, "immediate must be an integer in range [0, 15].");
3663 case Match_InvalidImm0_31:
3664 return Error(Loc, "immediate must be an integer in range [0, 31].");
3665 case Match_InvalidImm0_63:
3666 return Error(Loc, "immediate must be an integer in range [0, 63].");
3667 case Match_InvalidImm0_127:
3668 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003669 case Match_InvalidImm0_255:
3670 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003671 case Match_InvalidImm0_65535:
3672 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3673 case Match_InvalidImm1_8:
3674 return Error(Loc, "immediate must be an integer in range [1, 8].");
3675 case Match_InvalidImm1_16:
3676 return Error(Loc, "immediate must be an integer in range [1, 16].");
3677 case Match_InvalidImm1_32:
3678 return Error(Loc, "immediate must be an integer in range [1, 32].");
3679 case Match_InvalidImm1_64:
3680 return Error(Loc, "immediate must be an integer in range [1, 64].");
3681 case Match_InvalidIndex1:
3682 return Error(Loc, "expected lane specifier '[1]'");
3683 case Match_InvalidIndexB:
3684 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3685 case Match_InvalidIndexH:
3686 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3687 case Match_InvalidIndexS:
3688 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3689 case Match_InvalidIndexD:
3690 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3691 case Match_InvalidLabel:
3692 return Error(Loc, "expected label or encodable integer pc offset");
3693 case Match_MRS:
3694 return Error(Loc, "expected readable system register");
3695 case Match_MSR:
3696 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003697 case Match_InvalidComplexRotationEven:
3698 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3699 case Match_InvalidComplexRotationOdd:
3700 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003701 case Match_MnemonicFail: {
3702 std::string Suggestion = AArch64MnemonicSpellCheck(
3703 ((AArch64Operand &)*Operands[0]).getToken(),
3704 ComputeAvailableFeatures(STI->getFeatureBits()));
3705 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3706 }
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003707 case Match_InvalidSVEPattern:
3708 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003709 case Match_InvalidSVEPredicateAnyReg:
3710 case Match_InvalidSVEPredicateBReg:
3711 case Match_InvalidSVEPredicateHReg:
3712 case Match_InvalidSVEPredicateSReg:
3713 case Match_InvalidSVEPredicateDReg:
3714 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003715 case Match_InvalidSVEPredicate3bAnyReg:
3716 case Match_InvalidSVEPredicate3bBReg:
3717 case Match_InvalidSVEPredicate3bHReg:
3718 case Match_InvalidSVEPredicate3bSReg:
3719 case Match_InvalidSVEPredicate3bDReg:
3720 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003721 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003722 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003723 }
3724}
3725
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003726static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003727
3728bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3729 OperandVector &Operands,
3730 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003731 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003732 bool MatchingInlineAsm) {
3733 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003734 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3735 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003736
David Blaikie960ea3f2014-06-08 16:18:35 +00003737 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003738 unsigned NumOperands = Operands.size();
3739
3740 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003741 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3742 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003743 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003744 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003745 if (Op3CE) {
3746 uint64_t Op3Val = Op3CE->getValue();
3747 uint64_t NewOp3Val = 0;
3748 uint64_t NewOp4Val = 0;
3749 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003750 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003751 NewOp3Val = (32 - Op3Val) & 0x1f;
3752 NewOp4Val = 31 - Op3Val;
3753 } else {
3754 NewOp3Val = (64 - Op3Val) & 0x3f;
3755 NewOp4Val = 63 - Op3Val;
3756 }
3757
Jim Grosbach13760bd2015-05-30 01:25:56 +00003758 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3759 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003760
3761 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003762 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003763 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003764 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3765 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3766 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003767 }
3768 }
Tim Northover03b99f62015-04-30 18:28:58 +00003769 } else if (NumOperands == 4 && Tok == "bfc") {
3770 // FIXME: Horrible hack to handle BFC->BFM alias.
3771 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3772 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3773 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3774
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003775 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003776 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3777 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3778
3779 if (LSBCE && WidthCE) {
3780 uint64_t LSB = LSBCE->getValue();
3781 uint64_t Width = WidthCE->getValue();
3782
3783 uint64_t RegWidth = 0;
3784 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3785 Op1.getReg()))
3786 RegWidth = 64;
3787 else
3788 RegWidth = 32;
3789
3790 if (LSB >= RegWidth)
3791 return Error(LSBOp.getStartLoc(),
3792 "expected integer in range [0, 31]");
3793 if (Width < 1 || Width > RegWidth)
3794 return Error(WidthOp.getStartLoc(),
3795 "expected integer in range [1, 32]");
3796
3797 uint64_t ImmR = 0;
3798 if (RegWidth == 32)
3799 ImmR = (32 - LSB) & 0x1f;
3800 else
3801 ImmR = (64 - LSB) & 0x3f;
3802
3803 uint64_t ImmS = Width - 1;
3804
3805 if (ImmR != 0 && ImmS >= ImmR)
3806 return Error(WidthOp.getStartLoc(),
3807 "requested insert overflows register");
3808
Jim Grosbach13760bd2015-05-30 01:25:56 +00003809 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3810 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003811 Operands[0] = AArch64Operand::CreateToken(
3812 "bfm", false, Op.getStartLoc(), getContext());
3813 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003814 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3815 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003816 Operands[3] = AArch64Operand::CreateImm(
3817 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3818 Operands.emplace_back(
3819 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3820 WidthOp.getEndLoc(), getContext()));
3821 }
3822 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003823 } else if (NumOperands == 5) {
3824 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3825 // UBFIZ -> UBFM aliases.
3826 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003827 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3828 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3829 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003830
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003831 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003832 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3833 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003834
3835 if (Op3CE && Op4CE) {
3836 uint64_t Op3Val = Op3CE->getValue();
3837 uint64_t Op4Val = Op4CE->getValue();
3838
3839 uint64_t RegWidth = 0;
3840 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003841 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003842 RegWidth = 64;
3843 else
3844 RegWidth = 32;
3845
3846 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003847 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003848 "expected integer in range [0, 31]");
3849 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003850 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003851 "expected integer in range [1, 32]");
3852
3853 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003854 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003855 NewOp3Val = (32 - Op3Val) & 0x1f;
3856 else
3857 NewOp3Val = (64 - Op3Val) & 0x3f;
3858
3859 uint64_t NewOp4Val = Op4Val - 1;
3860
3861 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003862 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003863 "requested insert overflows register");
3864
3865 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003866 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003867 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003868 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003869 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003870 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003871 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003872 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003873 if (Tok == "bfi")
3874 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003875 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003876 else if (Tok == "sbfiz")
3877 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003878 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003879 else if (Tok == "ubfiz")
3880 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003881 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003882 else
3883 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003884 }
3885 }
3886
3887 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3888 // UBFX -> UBFM aliases.
3889 } else if (NumOperands == 5 &&
3890 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003891 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3892 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3893 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003894
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003895 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003896 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3897 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003898
3899 if (Op3CE && Op4CE) {
3900 uint64_t Op3Val = Op3CE->getValue();
3901 uint64_t Op4Val = Op4CE->getValue();
3902
3903 uint64_t RegWidth = 0;
3904 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003905 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003906 RegWidth = 64;
3907 else
3908 RegWidth = 32;
3909
3910 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003911 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003912 "expected integer in range [0, 31]");
3913 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003914 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003915 "expected integer in range [1, 32]");
3916
3917 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3918
3919 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003920 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003921 "requested extract overflows register");
3922
3923 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003924 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003925 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003926 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003927 if (Tok == "bfxil")
3928 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003929 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003930 else if (Tok == "sbfx")
3931 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003932 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003933 else if (Tok == "ubfx")
3934 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003935 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003936 else
3937 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003938 }
3939 }
3940 }
3941 }
Tim Northover9097a072017-12-18 10:36:00 +00003942
3943 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
3944 // instruction for FP registers correctly in some rare circumstances. Convert
3945 // it to a safe instruction and warn (because silently changing someone's
3946 // assembly is rude).
3947 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
3948 NumOperands == 4 && Tok == "movi") {
3949 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3950 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3951 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3952 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
3953 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
3954 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
3955 if (Suffix.lower() == ".2d" &&
3956 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
3957 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
3958 " correctly on this CPU, converting to equivalent movi.16b");
3959 // Switch the suffix to .16b.
3960 unsigned Idx = Op1.isToken() ? 1 : 2;
3961 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
3962 getContext());
3963 }
3964 }
3965 }
3966
Tim Northover3b0846e2014-05-24 12:50:23 +00003967 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3968 // InstAlias can't quite handle this since the reg classes aren't
3969 // subclasses.
3970 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3971 // The source register can be Wn here, but the matcher expects a
3972 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003973 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003974 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003975 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003976 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3977 Op.getStartLoc(), Op.getEndLoc(),
3978 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003979 }
3980 }
3981 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3982 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003983 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003984 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003985 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003986 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003987 // The source register can be Wn here, but the matcher expects a
3988 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003989 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003990 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003991 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003992 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3993 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003994 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003995 }
3996 }
3997 }
3998 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3999 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004000 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004001 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004002 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004003 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004004 // The source register can be Wn here, but the matcher expects a
4005 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004006 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004007 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004008 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004009 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4010 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004011 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004012 }
4013 }
4014 }
4015
Tim Northover3b0846e2014-05-24 12:50:23 +00004016 MCInst Inst;
4017 // First try to match against the secondary set of tables containing the
4018 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4019 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004020 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004021
4022 // If that fails, try against the alternate table containing long-form NEON:
4023 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004024 if (MatchResult != Match_Success) {
4025 // But first, save the short-form match result: we can use it in case the
4026 // long-form match also fails.
4027 auto ShortFormNEONErrorInfo = ErrorInfo;
4028 auto ShortFormNEONMatchResult = MatchResult;
4029
Tim Northover3b0846e2014-05-24 12:50:23 +00004030 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004031 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004032
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004033 // Now, both matches failed, and the long-form match failed on the mnemonic
4034 // suffix token operand. The short-form match failure is probably more
4035 // relevant: use it instead.
4036 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004037 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004038 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4039 MatchResult = ShortFormNEONMatchResult;
4040 ErrorInfo = ShortFormNEONErrorInfo;
4041 }
4042 }
4043
Tim Northover3b0846e2014-05-24 12:50:23 +00004044 switch (MatchResult) {
4045 case Match_Success: {
4046 // Perform range checking and other semantic validations
4047 SmallVector<SMLoc, 8> OperandLocs;
4048 NumOperands = Operands.size();
4049 for (unsigned i = 1; i < NumOperands; ++i)
4050 OperandLocs.push_back(Operands[i]->getStartLoc());
4051 if (validateInstruction(Inst, OperandLocs))
4052 return true;
4053
4054 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004055 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004056 return false;
4057 }
4058 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004059 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004060 // Special case the error message for the very common case where only
4061 // a single subtarget feature is missing (neon, e.g.).
4062 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004063 uint64_t Mask = 1;
4064 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4065 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004066 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004067 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004068 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004069 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004070 }
4071 return Error(IDLoc, Msg);
4072 }
4073 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004074 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004075 case Match_InvalidOperand: {
4076 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004077
Tim Northover26bb14e2014-08-18 11:49:42 +00004078 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004079 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004080 return Error(IDLoc, "too few operands for instruction",
4081 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004082
David Blaikie960ea3f2014-06-08 16:18:35 +00004083 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004084 if (ErrorLoc == SMLoc())
4085 ErrorLoc = IDLoc;
4086 }
4087 // If the match failed on a suffix token operand, tweak the diagnostic
4088 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004089 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4090 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004091 MatchResult = Match_InvalidSuffix;
4092
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004093 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004094 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004095 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004096 case Match_InvalidMemoryIndexed1:
4097 case Match_InvalidMemoryIndexed2:
4098 case Match_InvalidMemoryIndexed4:
4099 case Match_InvalidMemoryIndexed8:
4100 case Match_InvalidMemoryIndexed16:
4101 case Match_InvalidCondCode:
4102 case Match_AddSubRegExtendSmall:
4103 case Match_AddSubRegExtendLarge:
4104 case Match_AddSubSecondSource:
4105 case Match_LogicalSecondSource:
4106 case Match_AddSubRegShift32:
4107 case Match_AddSubRegShift64:
4108 case Match_InvalidMovImm32Shift:
4109 case Match_InvalidMovImm64Shift:
4110 case Match_InvalidFPImm:
4111 case Match_InvalidMemoryWExtend8:
4112 case Match_InvalidMemoryWExtend16:
4113 case Match_InvalidMemoryWExtend32:
4114 case Match_InvalidMemoryWExtend64:
4115 case Match_InvalidMemoryWExtend128:
4116 case Match_InvalidMemoryXExtend8:
4117 case Match_InvalidMemoryXExtend16:
4118 case Match_InvalidMemoryXExtend32:
4119 case Match_InvalidMemoryXExtend64:
4120 case Match_InvalidMemoryXExtend128:
Sander de Smalen909cf952018-01-19 15:22:00 +00004121 case Match_InvalidMemoryIndexedSImm6:
Tim Northover3b0846e2014-05-24 12:50:23 +00004122 case Match_InvalidMemoryIndexed4SImm7:
4123 case Match_InvalidMemoryIndexed8SImm7:
4124 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen30fda452018-04-10 07:01:53 +00004125 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004126 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004127 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004128 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004129 case Match_InvalidImm0_7:
4130 case Match_InvalidImm0_15:
4131 case Match_InvalidImm0_31:
4132 case Match_InvalidImm0_63:
4133 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004134 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004135 case Match_InvalidImm0_65535:
4136 case Match_InvalidImm1_8:
4137 case Match_InvalidImm1_16:
4138 case Match_InvalidImm1_32:
4139 case Match_InvalidImm1_64:
4140 case Match_InvalidIndex1:
4141 case Match_InvalidIndexB:
4142 case Match_InvalidIndexH:
4143 case Match_InvalidIndexS:
4144 case Match_InvalidIndexD:
4145 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004146 case Match_InvalidComplexRotationEven:
4147 case Match_InvalidComplexRotationOdd:
Sander de Smalencd6be962017-12-20 11:02:42 +00004148 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004149 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004150 case Match_InvalidSVEPredicateBReg:
4151 case Match_InvalidSVEPredicateHReg:
4152 case Match_InvalidSVEPredicateSReg:
4153 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004154 case Match_InvalidSVEPredicate3bAnyReg:
4155 case Match_InvalidSVEPredicate3bBReg:
4156 case Match_InvalidSVEPredicate3bHReg:
4157 case Match_InvalidSVEPredicate3bSReg:
4158 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004159 case Match_MSR:
4160 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004161 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004162 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004163 // Any time we get here, there's nothing fancy to do. Just get the
4164 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004165 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004166 if (ErrorLoc == SMLoc())
4167 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004168 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004169 }
4170 }
4171
4172 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004173}
4174
4175/// ParseDirective parses the arm specific directives
4176bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004177 const MCObjectFileInfo::Environment Format =
4178 getContext().getObjectFileInfo()->getObjectFileType();
4179 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4180 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004181
Tim Northover3b0846e2014-05-24 12:50:23 +00004182 StringRef IDVal = DirectiveID.getIdentifier();
4183 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004184 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004185 parseDirectiveArch(Loc);
4186 else if (IDVal == ".cpu")
4187 parseDirectiveCPU(Loc);
4188 else if (IDVal == ".hword")
4189 parseDirectiveWord(2, Loc);
4190 else if (IDVal == ".word")
4191 parseDirectiveWord(4, Loc);
4192 else if (IDVal == ".xword")
4193 parseDirectiveWord(8, Loc);
4194 else if (IDVal == ".tlsdesccall")
4195 parseDirectiveTLSDescCall(Loc);
4196 else if (IDVal == ".ltorg" || IDVal == ".pool")
4197 parseDirectiveLtorg(Loc);
4198 else if (IDVal == ".unreq")
4199 parseDirectiveUnreq(Loc);
4200 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004201 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004202 parseDirectiveInst(Loc);
4203 else
4204 return true;
4205 } else if (IDVal == MCLOHDirectiveName())
4206 parseDirectiveLOH(IDVal, Loc);
4207 else
4208 return true;
4209 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004210}
4211
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004212static const struct {
4213 const char *Name;
4214 const FeatureBitset Features;
4215} ExtensionMap[] = {
4216 { "crc", {AArch64::FeatureCRC} },
4217 { "crypto", {AArch64::FeatureCrypto} },
4218 { "fp", {AArch64::FeatureFPARMv8} },
4219 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004220 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004221 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004222
4223 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004224 { "pan", {} },
4225 { "lor", {} },
4226 { "rdma", {} },
4227 { "profile", {} },
4228};
4229
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004230/// parseDirectiveArch
4231/// ::= .arch token
4232bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4233 SMLoc ArchLoc = getLoc();
4234
4235 StringRef Arch, ExtensionString;
4236 std::tie(Arch, ExtensionString) =
4237 getParser().parseStringToEndOfStatement().trim().split('+');
4238
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004239 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4240 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004241 return Error(ArchLoc, "unknown arch name");
4242
4243 if (parseToken(AsmToken::EndOfStatement))
4244 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004245
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004246 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004247 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004248 AArch64::getArchFeatures(ID, AArch64Features);
4249 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4250 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004251
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004252 MCSubtargetInfo &STI = copySTI();
4253 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4254 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4255
4256 SmallVector<StringRef, 4> RequestedExtensions;
4257 if (!ExtensionString.empty())
4258 ExtensionString.split(RequestedExtensions, '+');
4259
4260 FeatureBitset Features = STI.getFeatureBits();
4261 for (auto Name : RequestedExtensions) {
4262 bool EnableFeature = true;
4263
4264 if (Name.startswith_lower("no")) {
4265 EnableFeature = false;
4266 Name = Name.substr(2);
4267 }
4268
4269 for (const auto &Extension : ExtensionMap) {
4270 if (Extension.Name != Name)
4271 continue;
4272
4273 if (Extension.Features.none())
4274 report_fatal_error("unsupported architectural extension: " + Name);
4275
4276 FeatureBitset ToggleFeatures = EnableFeature
4277 ? (~Features & Extension.Features)
4278 : ( Features & Extension.Features);
4279 uint64_t Features =
4280 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4281 setAvailableFeatures(Features);
4282 break;
4283 }
4284 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004285 return false;
4286}
4287
Tim Northover8b96c7e2017-05-15 19:42:15 +00004288static SMLoc incrementLoc(SMLoc L, int Offset) {
4289 return SMLoc::getFromPointer(L.getPointer() + Offset);
4290}
4291
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004292/// parseDirectiveCPU
4293/// ::= .cpu id
4294bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004295 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004296
4297 StringRef CPU, ExtensionString;
4298 std::tie(CPU, ExtensionString) =
4299 getParser().parseStringToEndOfStatement().trim().split('+');
4300
Nirav Davee833c6c2016-11-08 18:31:04 +00004301 if (parseToken(AsmToken::EndOfStatement))
4302 return true;
4303
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004304 SmallVector<StringRef, 4> RequestedExtensions;
4305 if (!ExtensionString.empty())
4306 ExtensionString.split(RequestedExtensions, '+');
4307
4308 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4309 // once that is tablegen'ed
4310 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004311 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004312 return false;
4313 }
4314
4315 MCSubtargetInfo &STI = copySTI();
4316 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004317 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004318
4319 FeatureBitset Features = STI.getFeatureBits();
4320 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004321 // Advance source location past '+'.
4322 CurLoc = incrementLoc(CurLoc, 1);
4323
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004324 bool EnableFeature = true;
4325
4326 if (Name.startswith_lower("no")) {
4327 EnableFeature = false;
4328 Name = Name.substr(2);
4329 }
4330
Tim Northover8b96c7e2017-05-15 19:42:15 +00004331 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004332 for (const auto &Extension : ExtensionMap) {
4333 if (Extension.Name != Name)
4334 continue;
4335
4336 if (Extension.Features.none())
4337 report_fatal_error("unsupported architectural extension: " + Name);
4338
4339 FeatureBitset ToggleFeatures = EnableFeature
4340 ? (~Features & Extension.Features)
4341 : ( Features & Extension.Features);
4342 uint64_t Features =
4343 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4344 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004345 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004346
4347 break;
4348 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004349
4350 if (!FoundExtension)
4351 Error(CurLoc, "unsupported architectural extension");
4352
4353 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004354 }
4355 return false;
4356}
4357
Tim Northover3b0846e2014-05-24 12:50:23 +00004358/// parseDirectiveWord
4359/// ::= .word [ expression (, expression)* ]
4360bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004361 auto parseOp = [&]() -> bool {
4362 const MCExpr *Value;
4363 if (getParser().parseExpression(Value))
4364 return true;
4365 getParser().getStreamer().EmitValue(Value, Size, L);
4366 return false;
4367 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004368
Nirav Davee833c6c2016-11-08 18:31:04 +00004369 if (parseMany(parseOp))
4370 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004371 return false;
4372}
4373
Chad Rosierdcd2a302014-10-22 20:35:57 +00004374/// parseDirectiveInst
4375/// ::= .inst opcode [, ...]
4376bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004377 if (getLexer().is(AsmToken::EndOfStatement))
4378 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004379
Nirav Davee833c6c2016-11-08 18:31:04 +00004380 auto parseOp = [&]() -> bool {
4381 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004382 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004383 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4384 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004385 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004386 if (check(!Value, L, "expected constant expression"))
4387 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004388 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004389 return false;
4390 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004391
Nirav Davee833c6c2016-11-08 18:31:04 +00004392 if (parseMany(parseOp))
4393 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004394 return false;
4395}
4396
Tim Northover3b0846e2014-05-24 12:50:23 +00004397// parseDirectiveTLSDescCall:
4398// ::= .tlsdesccall symbol
4399bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4400 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004401 if (check(getParser().parseIdentifier(Name), L,
4402 "expected symbol after directive") ||
4403 parseToken(AsmToken::EndOfStatement))
4404 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004405
Jim Grosbach6f482002015-05-18 18:43:14 +00004406 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004407 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4408 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004409
4410 MCInst Inst;
4411 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004412 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004413
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004414 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004415 return false;
4416}
4417
4418/// ::= .loh <lohName | lohId> label1, ..., labelN
4419/// The number of arguments depends on the loh identifier.
4420bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004421 MCLOHType Kind;
4422 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4423 if (getParser().getTok().isNot(AsmToken::Integer))
4424 return TokError("expected an identifier or a number in directive");
4425 // We successfully get a numeric value for the identifier.
4426 // Check if it is valid.
4427 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004428 if (Id <= -1U && !isValidMCLOHType(Id))
4429 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004430 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004431 } else {
4432 StringRef Name = getTok().getIdentifier();
4433 // We successfully parse an identifier.
4434 // Check if it is a recognized one.
4435 int Id = MCLOHNameToId(Name);
4436
4437 if (Id == -1)
4438 return TokError("invalid identifier in directive");
4439 Kind = (MCLOHType)Id;
4440 }
4441 // Consume the identifier.
4442 Lex();
4443 // Get the number of arguments of this LOH.
4444 int NbArgs = MCLOHIdToNbArgs(Kind);
4445
4446 assert(NbArgs != -1 && "Invalid number of arguments");
4447
4448 SmallVector<MCSymbol *, 3> Args;
4449 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4450 StringRef Name;
4451 if (getParser().parseIdentifier(Name))
4452 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004453 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004454
4455 if (Idx + 1 == NbArgs)
4456 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004457 if (parseToken(AsmToken::Comma,
4458 "unexpected token in '" + Twine(IDVal) + "' directive"))
4459 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004460 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004461 if (parseToken(AsmToken::EndOfStatement,
4462 "unexpected token in '" + Twine(IDVal) + "' directive"))
4463 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004464
4465 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4466 return false;
4467}
4468
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004469/// parseDirectiveLtorg
4470/// ::= .ltorg | .pool
4471bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004472 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4473 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004474 getTargetStreamer().emitCurrentConstantPool();
4475 return false;
4476}
4477
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004478/// parseDirectiveReq
4479/// ::= name .req registername
4480bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004481 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004482 Parser.Lex(); // Eat the '.req' token.
4483 SMLoc SRegLoc = getLoc();
Sander de Smalen8e607342017-11-15 15:44:43 +00004484 int RegNum = tryParseRegister();
Florian Hahnc4422242017-11-07 13:07:50 +00004485 RegKind RegisterKind = RegKind::Scalar;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004486
Sander de Smalen8e607342017-11-15 15:44:43 +00004487 if (RegNum == -1) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004488 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004489 RegisterKind = RegKind::NeonVector;
Sander de Smalen73937b72018-04-11 07:36:10 +00004490 OperandMatchResultTy Res =
4491 tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
4492
4493 if (Res == MatchOperand_ParseFail)
4494 return true;
4495
4496 if (Res == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004497 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004498 }
4499
Sander de Smalen8e607342017-11-15 15:44:43 +00004500 if (RegNum == -1) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004501 StringRef Kind;
4502 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen8e607342017-11-15 15:44:43 +00004503 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004504 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004505
4506 if (Res == MatchOperand_ParseFail)
4507 return true;
4508
4509 if (Res == MatchOperand_Success && !Kind.empty())
4510 return Error(SRegLoc,
4511 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004512 }
4513
Sander de Smalencd6be962017-12-20 11:02:42 +00004514 if (RegNum == -1) {
4515 StringRef Kind;
4516 RegisterKind = RegKind::SVEPredicateVector;
4517 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004518 tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004519
4520 if (Res == MatchOperand_ParseFail)
4521 return true;
4522
4523 if (Res == MatchOperand_Success && !Kind.empty())
4524 return Error(SRegLoc,
4525 "sve predicate register without type specifier expected");
4526 }
4527
Sander de Smalen8e607342017-11-15 15:44:43 +00004528 if (RegNum == -1)
Nirav Dave2364748a2016-09-16 18:30:20 +00004529 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004530
4531 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004532 if (parseToken(AsmToken::EndOfStatement,
4533 "unexpected input in .req directive"))
4534 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004535
Sander de Smalen8e607342017-11-15 15:44:43 +00004536 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004537 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004538 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4539
Nirav Dave2364748a2016-09-16 18:30:20 +00004540 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004541}
4542
4543/// parseDirectiveUneq
4544/// ::= .unreq registername
4545bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004546 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004547 if (getTok().isNot(AsmToken::Identifier))
4548 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004549 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4550 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004551 if (parseToken(AsmToken::EndOfStatement))
4552 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004553 return false;
4554}
4555
Tim Northover3b0846e2014-05-24 12:50:23 +00004556bool
4557AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4558 AArch64MCExpr::VariantKind &ELFRefKind,
4559 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4560 int64_t &Addend) {
4561 ELFRefKind = AArch64MCExpr::VK_INVALID;
4562 DarwinRefKind = MCSymbolRefExpr::VK_None;
4563 Addend = 0;
4564
4565 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4566 ELFRefKind = AE->getKind();
4567 Expr = AE->getSubExpr();
4568 }
4569
4570 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4571 if (SE) {
4572 // It's a simple symbol reference with no addend.
4573 DarwinRefKind = SE->getKind();
4574 return true;
4575 }
4576
4577 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4578 if (!BE)
4579 return false;
4580
4581 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4582 if (!SE)
4583 return false;
4584 DarwinRefKind = SE->getKind();
4585
4586 if (BE->getOpcode() != MCBinaryExpr::Add &&
4587 BE->getOpcode() != MCBinaryExpr::Sub)
4588 return false;
4589
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004590 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004591 // on here than we can deal with.
4592 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4593 if (!AddendExpr)
4594 return false;
4595
4596 Addend = AddendExpr->getValue();
4597 if (BE->getOpcode() == MCBinaryExpr::Sub)
4598 Addend = -Addend;
4599
4600 // It's some symbol reference + a constant addend, but really
4601 // shouldn't use both Darwin and ELF syntax.
4602 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4603 DarwinRefKind == MCSymbolRefExpr::VK_None;
4604}
4605
4606/// Force static initialization.
4607extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004608 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4609 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4610 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004611}
4612
4613#define GET_REGISTER_MATCHER
4614#define GET_SUBTARGET_FEATURE_NAME
4615#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004616#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004617#include "AArch64GenAsmMatcher.inc"
4618
4619// Define this matcher function after the auto-generated include so we
4620// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004621unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004622 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004623 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004624 // If the kind is a token for a literal immediate, check if our asm
4625 // operand matches. This is for InstAliases which have a fixed-value
4626 // immediate in the syntax.
4627 int64_t ExpectedVal;
4628 switch (Kind) {
4629 default:
4630 return Match_InvalidOperand;
4631 case MCK__35_0:
4632 ExpectedVal = 0;
4633 break;
4634 case MCK__35_1:
4635 ExpectedVal = 1;
4636 break;
4637 case MCK__35_12:
4638 ExpectedVal = 12;
4639 break;
4640 case MCK__35_16:
4641 ExpectedVal = 16;
4642 break;
4643 case MCK__35_2:
4644 ExpectedVal = 2;
4645 break;
4646 case MCK__35_24:
4647 ExpectedVal = 24;
4648 break;
4649 case MCK__35_3:
4650 ExpectedVal = 3;
4651 break;
4652 case MCK__35_32:
4653 ExpectedVal = 32;
4654 break;
4655 case MCK__35_4:
4656 ExpectedVal = 4;
4657 break;
4658 case MCK__35_48:
4659 ExpectedVal = 48;
4660 break;
4661 case MCK__35_6:
4662 ExpectedVal = 6;
4663 break;
4664 case MCK__35_64:
4665 ExpectedVal = 64;
4666 break;
4667 case MCK__35_8:
4668 ExpectedVal = 8;
4669 break;
4670 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004671 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004672 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004673 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004674 if (!CE)
4675 return Match_InvalidOperand;
4676 if (CE->getValue() == ExpectedVal)
4677 return Match_Success;
4678 return Match_InvalidOperand;
4679}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004680
Alex Bradbury58eba092016-11-01 16:32:05 +00004681OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004682AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4683
4684 SMLoc S = getLoc();
4685
4686 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4687 Error(S, "expected register");
4688 return MatchOperand_ParseFail;
4689 }
4690
4691 int FirstReg = tryParseRegister();
4692 if (FirstReg == -1) {
4693 return MatchOperand_ParseFail;
4694 }
4695 const MCRegisterClass &WRegClass =
4696 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4697 const MCRegisterClass &XRegClass =
4698 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4699
4700 bool isXReg = XRegClass.contains(FirstReg),
4701 isWReg = WRegClass.contains(FirstReg);
4702 if (!isXReg && !isWReg) {
4703 Error(S, "expected first even register of a "
4704 "consecutive same-size even/odd register pair");
4705 return MatchOperand_ParseFail;
4706 }
4707
4708 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4709 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4710
4711 if (FirstEncoding & 0x1) {
4712 Error(S, "expected first even register of a "
4713 "consecutive same-size even/odd register pair");
4714 return MatchOperand_ParseFail;
4715 }
4716
4717 SMLoc M = getLoc();
4718 if (getParser().getTok().isNot(AsmToken::Comma)) {
4719 Error(M, "expected comma");
4720 return MatchOperand_ParseFail;
4721 }
4722 // Eat the comma
4723 getParser().Lex();
4724
4725 SMLoc E = getLoc();
4726 int SecondReg = tryParseRegister();
4727 if (SecondReg ==-1) {
4728 return MatchOperand_ParseFail;
4729 }
4730
Eugene Zelenko049b0172017-01-06 00:30:53 +00004731 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004732 (isXReg && !XRegClass.contains(SecondReg)) ||
4733 (isWReg && !WRegClass.contains(SecondReg))) {
4734 Error(E,"expected second odd register of a "
4735 "consecutive same-size even/odd register pair");
4736 return MatchOperand_ParseFail;
4737 }
Joel Jones504bf332016-10-24 13:37:13 +00004738
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004739 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004740 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004741 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4742 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4743 } else {
4744 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4745 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4746 }
4747
Florian Hahnc4422242017-11-07 13:07:50 +00004748 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4749 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004750
4751 return MatchOperand_Success;
4752}
Florian Hahn91f11e52017-11-07 16:45:48 +00004753
4754template <bool ParseSuffix>
4755OperandMatchResultTy
4756AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004757 const SMLoc S = getLoc();
4758 // Check for a SVE vector register specifier first.
Sander de Smalen8e607342017-11-15 15:44:43 +00004759 int RegNum = -1;
Florian Hahn91f11e52017-11-07 16:45:48 +00004760 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004761
Sander de Smalen8e607342017-11-15 15:44:43 +00004762 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004763 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004764
4765 if (Res != MatchOperand_Success)
4766 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004767
4768 if (ParseSuffix && Kind.empty())
4769 return MatchOperand_NoMatch;
4770
Sander de Smalen73937b72018-04-11 07:36:10 +00004771 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
4772 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00004773 return MatchOperand_NoMatch;
4774
Sander de Smalen73937b72018-04-11 07:36:10 +00004775 unsigned ElementWidth = KindRes->second;
4776 Operands.push_back(AArch64Operand::CreateVectorReg(
4777 RegNum, RegKind::SVEDataVector, ElementWidth, S, S,
4778 getContext()));
Florian Hahn91f11e52017-11-07 16:45:48 +00004779
4780 return MatchOperand_Success;
4781}
Sander de Smalen245e0e62018-01-22 10:46:00 +00004782
4783OperandMatchResultTy
4784AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
4785 MCAsmParser &Parser = getParser();
4786
4787 SMLoc SS = getLoc();
4788 const AsmToken &TokE = Parser.getTok();
4789 bool IsHash = TokE.is(AsmToken::Hash);
4790
4791 if (!IsHash && TokE.isNot(AsmToken::Identifier))
4792 return MatchOperand_NoMatch;
4793
4794 int64_t Pattern;
4795 if (IsHash) {
4796 Parser.Lex(); // Eat hash
4797
4798 // Parse the immediate operand.
4799 const MCExpr *ImmVal;
4800 SS = getLoc();
4801 if (Parser.parseExpression(ImmVal))
4802 return MatchOperand_ParseFail;
4803
4804 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4805 if (!MCE)
4806 return MatchOperand_ParseFail;
4807
4808 Pattern = MCE->getValue();
4809 } else {
4810 // Parse the pattern
4811 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
4812 if (!Pat)
4813 return MatchOperand_NoMatch;
4814
4815 Parser.Lex();
4816 Pattern = Pat->Encoding;
4817 assert(Pattern >= 0 && Pattern < 32);
4818 }
4819
4820 Operands.push_back(
4821 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
4822 SS, getLoc(), getContext()));
4823
4824 return MatchOperand_Success;
4825}