blob: 2abe2a0fda590b8418d4e0e5d1d08b8c5981219f [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();
89 int tryMatchVectorRegister(StringRef &Kind, bool expected);
90 bool parseRegister(OperandVector &Operands);
91 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
92 bool parseVectorList(OperandVector &Operands);
93 bool parseOperand(OperandVector &Operands, bool isCondCode,
94 bool invertCondCode);
95
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +000096 bool showMatchError(SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000097
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000098 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000099 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000100 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +0000101 bool parseDirectiveInst(SMLoc L);
102
Tim Northover3b0846e2014-05-24 12:50:23 +0000103 bool parseDirectiveTLSDescCall(SMLoc L);
104
105 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000106 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000107
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000108 bool parseDirectiveReq(StringRef Name, SMLoc L);
109 bool parseDirectiveUnreq(SMLoc L);
110
Tim Northover3b0846e2014-05-24 12:50:23 +0000111 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
112 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
113 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000114 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000115 bool MatchingInlineAsm) override;
116/// @name Auto-generated Match Functions
117/// {
118
119#define GET_ASSEMBLER_HEADER
120#include "AArch64GenAsmMatcher.inc"
121
122 /// }
123
Sander de Smalen8e607342017-11-15 15:44:43 +0000124 OperandMatchResultTy tryParseSVERegister(int &Reg, StringRef &Kind,
125 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000126 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
127 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
128 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
129 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
130 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
131 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000132 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000133 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
134 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
135 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
136 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
137 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000138 bool tryParseNeonVectorRegister(OperandVector &Operands);
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 Smalen7ab96f52018-01-22 15:29:19 +0000143 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000144
145public:
146 enum AArch64MatchResultTy {
147 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
148#define GET_OPERAND_DIAGNOSTIC_TYPES
149#include "AArch64GenAsmMatcher.inc"
150 };
Joel Jones504bf332016-10-24 13:37:13 +0000151 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000152
Akira Hatanakab11ef082015-11-14 06:35:56 +0000153 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000154 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000155 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000156 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000157 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000158 MCStreamer &S = getParser().getStreamer();
159 if (S.getTargetStreamer() == nullptr)
160 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000161
162 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000163 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000164 }
165
166 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
167 SMLoc NameLoc, OperandVector &Operands) override;
168 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
169 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000170 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000171 unsigned Kind) override;
172
173 static bool classifySymbolRef(const MCExpr *Expr,
174 AArch64MCExpr::VariantKind &ELFRefKind,
175 MCSymbolRefExpr::VariantKind &DarwinRefKind,
176 int64_t &Addend);
177};
Tim Northover3b0846e2014-05-24 12:50:23 +0000178
179/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
180/// instruction.
181class AArch64Operand : public MCParsedAsmOperand {
182private:
183 enum KindTy {
184 k_Immediate,
185 k_ShiftedImm,
186 k_CondCode,
187 k_Register,
188 k_VectorList,
189 k_VectorIndex,
190 k_Token,
191 k_SysReg,
192 k_SysCR,
193 k_Prefetch,
194 k_ShiftExtend,
195 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000196 k_Barrier,
197 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000198 } Kind;
199
200 SMLoc StartLoc, EndLoc;
201
202 struct TokOp {
203 const char *Data;
204 unsigned Length;
205 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
206 };
207
208 struct RegOp {
209 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000210 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000211
212 int ElementWidth;
Tim Northover3b0846e2014-05-24 12:50:23 +0000213 };
214
215 struct VectorListOp {
216 unsigned RegNum;
217 unsigned Count;
218 unsigned NumElements;
219 unsigned ElementKind;
220 };
221
222 struct VectorIndexOp {
223 unsigned Val;
224 };
225
226 struct ImmOp {
227 const MCExpr *Val;
228 };
229
230 struct ShiftedImmOp {
231 const MCExpr *Val;
232 unsigned ShiftAmount;
233 };
234
235 struct CondCodeOp {
236 AArch64CC::CondCode Code;
237 };
238
239 struct FPImmOp {
240 unsigned Val; // Encoded 8-bit representation.
241 };
242
243 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000244 const char *Data;
245 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000246 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000247 };
248
249 struct SysRegOp {
250 const char *Data;
251 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000252 uint32_t MRSReg;
253 uint32_t MSRReg;
254 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000255 };
256
257 struct SysCRImmOp {
258 unsigned Val;
259 };
260
261 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000262 const char *Data;
263 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000264 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000265 };
266
Oliver Stannarda34e4702015-12-01 10:48:51 +0000267 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000268 const char *Data;
269 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000270 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000271 };
272
Tim Northover3b0846e2014-05-24 12:50:23 +0000273 struct ShiftExtendOp {
274 AArch64_AM::ShiftExtendType Type;
275 unsigned Amount;
276 bool HasExplicitAmount;
277 };
278
279 struct ExtendOp {
280 unsigned Val;
281 };
282
283 union {
284 struct TokOp Tok;
285 struct RegOp Reg;
286 struct VectorListOp VectorList;
287 struct VectorIndexOp VectorIndex;
288 struct ImmOp Imm;
289 struct ShiftedImmOp ShiftedImm;
290 struct CondCodeOp CondCode;
291 struct FPImmOp FPImm;
292 struct BarrierOp Barrier;
293 struct SysRegOp SysReg;
294 struct SysCRImmOp SysCRImm;
295 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000296 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000297 struct ShiftExtendOp ShiftExtend;
298 };
299
300 // Keep the MCContext around as the MCExprs may need manipulated during
301 // the add<>Operands() calls.
302 MCContext &Ctx;
303
David Blaikie960ea3f2014-06-08 16:18:35 +0000304public:
David Blaikie9f380a32015-03-16 18:06:57 +0000305 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000306
Tim Northover3b0846e2014-05-24 12:50:23 +0000307 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
308 Kind = o.Kind;
309 StartLoc = o.StartLoc;
310 EndLoc = o.EndLoc;
311 switch (Kind) {
312 case k_Token:
313 Tok = o.Tok;
314 break;
315 case k_Immediate:
316 Imm = o.Imm;
317 break;
318 case k_ShiftedImm:
319 ShiftedImm = o.ShiftedImm;
320 break;
321 case k_CondCode:
322 CondCode = o.CondCode;
323 break;
324 case k_FPImm:
325 FPImm = o.FPImm;
326 break;
327 case k_Barrier:
328 Barrier = o.Barrier;
329 break;
330 case k_Register:
331 Reg = o.Reg;
332 break;
333 case k_VectorList:
334 VectorList = o.VectorList;
335 break;
336 case k_VectorIndex:
337 VectorIndex = o.VectorIndex;
338 break;
339 case k_SysReg:
340 SysReg = o.SysReg;
341 break;
342 case k_SysCR:
343 SysCRImm = o.SysCRImm;
344 break;
345 case k_Prefetch:
346 Prefetch = o.Prefetch;
347 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000348 case k_PSBHint:
349 PSBHint = o.PSBHint;
350 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000351 case k_ShiftExtend:
352 ShiftExtend = o.ShiftExtend;
353 break;
354 }
355 }
356
357 /// getStartLoc - Get the location of the first token of this operand.
358 SMLoc getStartLoc() const override { return StartLoc; }
359 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000360 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000361
362 StringRef getToken() const {
363 assert(Kind == k_Token && "Invalid access!");
364 return StringRef(Tok.Data, Tok.Length);
365 }
366
367 bool isTokenSuffix() const {
368 assert(Kind == k_Token && "Invalid access!");
369 return Tok.IsSuffix;
370 }
371
372 const MCExpr *getImm() const {
373 assert(Kind == k_Immediate && "Invalid access!");
374 return Imm.Val;
375 }
376
377 const MCExpr *getShiftedImmVal() const {
378 assert(Kind == k_ShiftedImm && "Invalid access!");
379 return ShiftedImm.Val;
380 }
381
382 unsigned getShiftedImmShift() const {
383 assert(Kind == k_ShiftedImm && "Invalid access!");
384 return ShiftedImm.ShiftAmount;
385 }
386
387 AArch64CC::CondCode getCondCode() const {
388 assert(Kind == k_CondCode && "Invalid access!");
389 return CondCode.Code;
390 }
391
392 unsigned getFPImm() const {
393 assert(Kind == k_FPImm && "Invalid access!");
394 return FPImm.Val;
395 }
396
397 unsigned getBarrier() const {
398 assert(Kind == k_Barrier && "Invalid access!");
399 return Barrier.Val;
400 }
401
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000402 StringRef getBarrierName() const {
403 assert(Kind == k_Barrier && "Invalid access!");
404 return StringRef(Barrier.Data, Barrier.Length);
405 }
406
Tim Northover3b0846e2014-05-24 12:50:23 +0000407 unsigned getReg() const override {
408 assert(Kind == k_Register && "Invalid access!");
409 return Reg.RegNum;
410 }
411
412 unsigned getVectorListStart() const {
413 assert(Kind == k_VectorList && "Invalid access!");
414 return VectorList.RegNum;
415 }
416
417 unsigned getVectorListCount() const {
418 assert(Kind == k_VectorList && "Invalid access!");
419 return VectorList.Count;
420 }
421
422 unsigned getVectorIndex() const {
423 assert(Kind == k_VectorIndex && "Invalid access!");
424 return VectorIndex.Val;
425 }
426
427 StringRef getSysReg() const {
428 assert(Kind == k_SysReg && "Invalid access!");
429 return StringRef(SysReg.Data, SysReg.Length);
430 }
431
Tim Northover3b0846e2014-05-24 12:50:23 +0000432 unsigned getSysCR() const {
433 assert(Kind == k_SysCR && "Invalid access!");
434 return SysCRImm.Val;
435 }
436
437 unsigned getPrefetch() const {
438 assert(Kind == k_Prefetch && "Invalid access!");
439 return Prefetch.Val;
440 }
441
Oliver Stannarda34e4702015-12-01 10:48:51 +0000442 unsigned getPSBHint() const {
443 assert(Kind == k_PSBHint && "Invalid access!");
444 return PSBHint.Val;
445 }
446
447 StringRef getPSBHintName() const {
448 assert(Kind == k_PSBHint && "Invalid access!");
449 return StringRef(PSBHint.Data, PSBHint.Length);
450 }
451
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000452 StringRef getPrefetchName() const {
453 assert(Kind == k_Prefetch && "Invalid access!");
454 return StringRef(Prefetch.Data, Prefetch.Length);
455 }
456
Tim Northover3b0846e2014-05-24 12:50:23 +0000457 AArch64_AM::ShiftExtendType getShiftExtendType() const {
458 assert(Kind == k_ShiftExtend && "Invalid access!");
459 return ShiftExtend.Type;
460 }
461
462 unsigned getShiftExtendAmount() const {
463 assert(Kind == k_ShiftExtend && "Invalid access!");
464 return ShiftExtend.Amount;
465 }
466
467 bool hasShiftExtendAmount() const {
468 assert(Kind == k_ShiftExtend && "Invalid access!");
469 return ShiftExtend.HasExplicitAmount;
470 }
471
472 bool isImm() const override { return Kind == k_Immediate; }
473 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000474
475 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
476
477 template <int Bits, int Scale> bool isSImmScaled() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000478 if (!isImm())
479 return false;
480 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
481 if (!MCE)
482 return false;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000483
484 int64_t Shift = Bits - 1;
485 int64_t MinVal = (int64_t(1) << Shift) * -Scale;
486 int64_t MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
487
Tim Northover3b0846e2014-05-24 12:50:23 +0000488 int64_t Val = MCE->getValue();
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000489 return Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0;
Tim Northover3b0846e2014-05-24 12:50:23 +0000490 }
491
Sander de Smalen245e0e62018-01-22 10:46:00 +0000492 bool isSVEPattern() const {
493 if (!isImm())
494 return false;
495 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
496 if (!MCE)
497 return false;
498 int64_t Val = MCE->getValue();
499 return Val >= 0 && Val < 32;
500 }
501
Tim Northover3b0846e2014-05-24 12:50:23 +0000502 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
503 AArch64MCExpr::VariantKind ELFRefKind;
504 MCSymbolRefExpr::VariantKind DarwinRefKind;
505 int64_t Addend;
506 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
507 Addend)) {
508 // If we don't understand the expression, assume the best and
509 // let the fixup and relocation code deal with it.
510 return true;
511 }
512
513 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
514 ELFRefKind == AArch64MCExpr::VK_LO12 ||
515 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
516 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
517 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
518 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
519 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
520 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000521 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
522 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
523 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000524 // Note that we don't range-check the addend. It's adjusted modulo page
525 // size when converted, so there is no "out of range" condition when using
526 // @pageoff.
527 return Addend >= 0 && (Addend % Scale) == 0;
528 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
529 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
530 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
531 return Addend == 0;
532 }
533
534 return false;
535 }
536
537 template <int Scale> bool isUImm12Offset() const {
538 if (!isImm())
539 return false;
540
541 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
542 if (!MCE)
543 return isSymbolicUImm12Offset(getImm(), Scale);
544
545 int64_t Val = MCE->getValue();
546 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
547 }
548
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000549 template <int N, int M>
550 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000551 if (!isImm())
552 return false;
553 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
554 if (!MCE)
555 return false;
556 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000557 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000558 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000559
Sander de Smalena1c259c2018-01-29 13:05:38 +0000560 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
561 // a logical immediate can always be represented when inverted.
562 template <typename T>
563 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000564 if (!isImm())
565 return false;
566 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
567 if (!MCE)
568 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000569
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000570 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000571 int64_t SVal = typename std::make_signed<T>::type(Val);
572 int64_t UVal = typename std::make_unsigned<T>::type(Val);
573 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000574 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000575
Sander de Smalena1c259c2018-01-29 13:05:38 +0000576 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000577 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000578
Tim Northover3b0846e2014-05-24 12:50:23 +0000579 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000580
Tim Northover3b0846e2014-05-24 12:50:23 +0000581 bool isAddSubImm() const {
582 if (!isShiftedImm() && !isImm())
583 return false;
584
585 const MCExpr *Expr;
586
587 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
588 if (isShiftedImm()) {
589 unsigned Shift = ShiftedImm.ShiftAmount;
590 Expr = ShiftedImm.Val;
591 if (Shift != 0 && Shift != 12)
592 return false;
593 } else {
594 Expr = getImm();
595 }
596
597 AArch64MCExpr::VariantKind ELFRefKind;
598 MCSymbolRefExpr::VariantKind DarwinRefKind;
599 int64_t Addend;
600 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
601 DarwinRefKind, Addend)) {
602 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
603 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
604 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
605 || ELFRefKind == AArch64MCExpr::VK_LO12
606 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
607 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
608 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
609 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
610 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
611 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000612 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
613 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
614 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000615 }
616
Diana Picusc93518d2016-10-11 09:17:47 +0000617 // If it's a constant, it should be a real immediate in range:
618 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
619 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
620
621 // If it's an expression, we hope for the best and let the fixup/relocation
622 // code deal with it.
623 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000624 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000625
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000626 bool isAddSubImmNeg() const {
627 if (!isShiftedImm() && !isImm())
628 return false;
629
630 const MCExpr *Expr;
631
632 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
633 if (isShiftedImm()) {
634 unsigned Shift = ShiftedImm.ShiftAmount;
635 Expr = ShiftedImm.Val;
636 if (Shift != 0 && Shift != 12)
637 return false;
638 } else
639 Expr = getImm();
640
641 // Otherwise it should be a real negative immediate in range:
642 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
643 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
644 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000645
Tim Northover3b0846e2014-05-24 12:50:23 +0000646 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000647
Tim Northover3b0846e2014-05-24 12:50:23 +0000648 bool isSIMDImmType10() const {
649 if (!isImm())
650 return false;
651 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
652 if (!MCE)
653 return false;
654 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
655 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000656
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000657 template<int N>
658 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000659 if (!isImm())
660 return false;
661 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
662 if (!MCE)
663 return true;
664 int64_t Val = MCE->getValue();
665 if (Val & 0x3)
666 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000667 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
668 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000669 }
670
671 bool
672 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
673 if (!isImm())
674 return false;
675
676 AArch64MCExpr::VariantKind ELFRefKind;
677 MCSymbolRefExpr::VariantKind DarwinRefKind;
678 int64_t Addend;
679 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
680 DarwinRefKind, Addend)) {
681 return false;
682 }
683 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
684 return false;
685
686 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
687 if (ELFRefKind == AllowedModifiers[i])
688 return Addend == 0;
689 }
690
691 return false;
692 }
693
694 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000695 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000696 }
697
698 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000699 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
700 AArch64MCExpr::VK_TPREL_G2,
701 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000702 }
703
704 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000705 return isMovWSymbol({
706 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000707 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
708 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000709 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000710 }
711
712 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000713 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
714 AArch64MCExpr::VK_TPREL_G0,
715 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000716 }
717
718 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000719 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000720 }
721
722 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000723 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000724 }
725
726 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000727 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
728 AArch64MCExpr::VK_TPREL_G1_NC,
729 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000730 }
731
732 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000733 return isMovWSymbol(
734 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
735 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000736 }
737
738 template<int RegWidth, int Shift>
739 bool isMOVZMovAlias() const {
740 if (!isImm()) return false;
741
742 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
743 if (!CE) return false;
744 uint64_t Value = CE->getValue();
745
Tim Northoverdaa1c012016-06-16 01:42:25 +0000746 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000747 }
748
749 template<int RegWidth, int Shift>
750 bool isMOVNMovAlias() const {
751 if (!isImm()) return false;
752
753 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
754 if (!CE) return false;
755 uint64_t Value = CE->getValue();
756
Tim Northoverdaa1c012016-06-16 01:42:25 +0000757 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000758 }
759
760 bool isFPImm() const { return Kind == k_FPImm; }
761 bool isBarrier() const { return Kind == k_Barrier; }
762 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000763
Tim Northover3b0846e2014-05-24 12:50:23 +0000764 bool isMRSSystemRegister() const {
765 if (!isSysReg()) return false;
766
Tim Northover7cd58932015-01-22 17:23:04 +0000767 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000768 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000769
Tim Northover3b0846e2014-05-24 12:50:23 +0000770 bool isMSRSystemRegister() const {
771 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000772 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000773 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000774
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000775 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000776 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000777 return (SysReg.PStateField == AArch64PState::PAN ||
778 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000779 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000780
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000781 bool isSystemPStateFieldWithImm0_15() const {
782 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000783 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000784 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000785
Florian Hahnc4422242017-11-07 13:07:50 +0000786 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000787 return Kind == k_Register;
788 }
789
790 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000791 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
792 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000793
Florian Hahnc4422242017-11-07 13:07:50 +0000794 bool isNeonVectorReg() const {
795 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
796 }
797
798 bool isNeonVectorRegLo() const {
799 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000800 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
801 Reg.RegNum);
802 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000803
Sander de Smalencd6be962017-12-20 11:02:42 +0000804 template <unsigned Class> bool isSVEVectorReg() const {
805 RegKind RK;
806 switch (Class) {
807 case AArch64::ZPRRegClassID:
808 RK = RegKind::SVEDataVector;
809 break;
810 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000811 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000812 RK = RegKind::SVEPredicateVector;
813 break;
814 default:
815 llvm_unreachable("Unsupport register class");
816 }
817
818 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000819 AArch64MCRegisterClasses[Class].contains(getReg());
820 }
821
Sander de Smalencd6be962017-12-20 11:02:42 +0000822 template <int ElementWidth, unsigned Class>
823 bool isSVEVectorRegOfWidth() const {
824 return isSVEVectorReg<Class>() &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000825 (ElementWidth == -1 || Reg.ElementWidth == ElementWidth);
826 }
827
Tim Northover3b0846e2014-05-24 12:50:23 +0000828 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000829 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000830 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
831 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000832
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000833 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000834 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000835 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
836 Reg.RegNum);
837 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000838
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000839 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000840 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000841 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
842 Reg.RegNum);
843 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000844
845 bool isGPR64sp0() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000846 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000847 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
848 }
849
Sam Parker5f934642017-08-31 09:27:04 +0000850 template<int64_t Angle, int64_t Remainder>
851 bool isComplexRotation() const {
852 if (!isImm()) return false;
853
854 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
855 if (!CE) return false;
856 uint64_t Value = CE->getValue();
857
858 return (Value % Angle == Remainder && Value <= 270);
859 }
860
Tim Northover3b0846e2014-05-24 12:50:23 +0000861 /// Is this a vector list with the type implicit (presumably attached to the
862 /// instruction itself)?
863 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
864 return Kind == k_VectorList && VectorList.Count == NumRegs &&
865 !VectorList.ElementKind;
866 }
867
868 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
869 bool isTypedVectorList() const {
870 if (Kind != k_VectorList)
871 return false;
872 if (VectorList.Count != NumRegs)
873 return false;
874 if (VectorList.ElementKind != ElementKind)
875 return false;
876 return VectorList.NumElements == NumElements;
877 }
878
879 bool isVectorIndex1() const {
880 return Kind == k_VectorIndex && VectorIndex.Val == 1;
881 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000882
Tim Northover3b0846e2014-05-24 12:50:23 +0000883 bool isVectorIndexB() const {
884 return Kind == k_VectorIndex && VectorIndex.Val < 16;
885 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000886
Tim Northover3b0846e2014-05-24 12:50:23 +0000887 bool isVectorIndexH() const {
888 return Kind == k_VectorIndex && VectorIndex.Val < 8;
889 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000890
Tim Northover3b0846e2014-05-24 12:50:23 +0000891 bool isVectorIndexS() const {
892 return Kind == k_VectorIndex && VectorIndex.Val < 4;
893 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000894
Tim Northover3b0846e2014-05-24 12:50:23 +0000895 bool isVectorIndexD() const {
896 return Kind == k_VectorIndex && VectorIndex.Val < 2;
897 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000898
Tim Northover3b0846e2014-05-24 12:50:23 +0000899 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000900
Tim Northover3b0846e2014-05-24 12:50:23 +0000901 bool isTokenEqual(StringRef Str) const {
902 return Kind == k_Token && getToken() == Str;
903 }
904 bool isSysCR() const { return Kind == k_SysCR; }
905 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000906 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000907 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
908 bool isShifter() const {
909 if (!isShiftExtend())
910 return false;
911
912 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
913 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
914 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
915 ST == AArch64_AM::MSL);
916 }
917 bool isExtend() const {
918 if (!isShiftExtend())
919 return false;
920
921 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
922 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
923 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
924 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
925 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
926 ET == AArch64_AM::LSL) &&
927 getShiftExtendAmount() <= 4;
928 }
929
930 bool isExtend64() const {
931 if (!isExtend())
932 return false;
933 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
934 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
935 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
936 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000937
Tim Northover3b0846e2014-05-24 12:50:23 +0000938 bool isExtendLSL64() const {
939 if (!isExtend())
940 return false;
941 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
942 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
943 ET == AArch64_AM::LSL) &&
944 getShiftExtendAmount() <= 4;
945 }
946
947 template<int Width> bool isMemXExtend() const {
948 if (!isExtend())
949 return false;
950 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
951 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
952 (getShiftExtendAmount() == Log2_32(Width / 8) ||
953 getShiftExtendAmount() == 0);
954 }
955
956 template<int Width> bool isMemWExtend() const {
957 if (!isExtend())
958 return false;
959 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
960 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
961 (getShiftExtendAmount() == Log2_32(Width / 8) ||
962 getShiftExtendAmount() == 0);
963 }
964
965 template <unsigned width>
966 bool isArithmeticShifter() const {
967 if (!isShifter())
968 return false;
969
970 // An arithmetic shifter is LSL, LSR, or ASR.
971 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
972 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
973 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
974 }
975
976 template <unsigned width>
977 bool isLogicalShifter() const {
978 if (!isShifter())
979 return false;
980
981 // A logical shifter is LSL, LSR, ASR or ROR.
982 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
983 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
984 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
985 getShiftExtendAmount() < width;
986 }
987
988 bool isMovImm32Shifter() const {
989 if (!isShifter())
990 return false;
991
992 // A MOVi shifter is LSL of 0, 16, 32, or 48.
993 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
994 if (ST != AArch64_AM::LSL)
995 return false;
996 uint64_t Val = getShiftExtendAmount();
997 return (Val == 0 || Val == 16);
998 }
999
1000 bool isMovImm64Shifter() const {
1001 if (!isShifter())
1002 return false;
1003
1004 // A MOVi shifter is LSL of 0 or 16.
1005 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1006 if (ST != AArch64_AM::LSL)
1007 return false;
1008 uint64_t Val = getShiftExtendAmount();
1009 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1010 }
1011
1012 bool isLogicalVecShifter() const {
1013 if (!isShifter())
1014 return false;
1015
1016 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1017 unsigned Shift = getShiftExtendAmount();
1018 return getShiftExtendType() == AArch64_AM::LSL &&
1019 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1020 }
1021
1022 bool isLogicalVecHalfWordShifter() const {
1023 if (!isLogicalVecShifter())
1024 return false;
1025
1026 // A logical vector shifter is a left shift by 0 or 8.
1027 unsigned Shift = getShiftExtendAmount();
1028 return getShiftExtendType() == AArch64_AM::LSL &&
1029 (Shift == 0 || Shift == 8);
1030 }
1031
1032 bool isMoveVecShifter() const {
1033 if (!isShiftExtend())
1034 return false;
1035
1036 // A logical vector shifter is a left shift by 8 or 16.
1037 unsigned Shift = getShiftExtendAmount();
1038 return getShiftExtendType() == AArch64_AM::MSL &&
1039 (Shift == 8 || Shift == 16);
1040 }
1041
1042 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1043 // to LDUR/STUR when the offset is not legal for the former but is for
1044 // the latter. As such, in addition to checking for being a legal unscaled
1045 // address, also check that it is not a legal scaled address. This avoids
1046 // ambiguity in the matcher.
1047 template<int Width>
1048 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001049 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001050 }
1051
1052 bool isAdrpLabel() const {
1053 // Validation was handled during parsing, so we just sanity check that
1054 // something didn't go haywire.
1055 if (!isImm())
1056 return false;
1057
1058 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1059 int64_t Val = CE->getValue();
1060 int64_t Min = - (4096 * (1LL << (21 - 1)));
1061 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1062 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1063 }
1064
1065 return true;
1066 }
1067
1068 bool isAdrLabel() const {
1069 // Validation was handled during parsing, so we just sanity check that
1070 // something didn't go haywire.
1071 if (!isImm())
1072 return false;
1073
1074 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1075 int64_t Val = CE->getValue();
1076 int64_t Min = - (1LL << (21 - 1));
1077 int64_t Max = ((1LL << (21 - 1)) - 1);
1078 return Val >= Min && Val <= Max;
1079 }
1080
1081 return true;
1082 }
1083
1084 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1085 // Add as immediates when possible. Null MCExpr = 0.
1086 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001087 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001088 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001089 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001090 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001091 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001092 }
1093
1094 void addRegOperands(MCInst &Inst, unsigned N) const {
1095 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001096 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001097 }
1098
1099 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1100 assert(N == 1 && "Invalid number of operands!");
1101 assert(
1102 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1103
1104 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1105 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1106 RI->getEncodingValue(getReg()));
1107
Jim Grosbache9119e42015-05-13 18:37:00 +00001108 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001109 }
1110
1111 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1112 assert(N == 1 && "Invalid number of operands!");
1113 assert(
1114 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001115 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001116 }
1117
1118 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1119 assert(N == 1 && "Invalid number of operands!");
1120 assert(
1121 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001122 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001123 }
1124
1125 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1126 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001127 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001128 }
1129
1130 template <unsigned NumRegs>
1131 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1132 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001133 static const unsigned FirstRegs[] = { AArch64::D0,
1134 AArch64::D0_D1,
1135 AArch64::D0_D1_D2,
1136 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001137 unsigned FirstReg = FirstRegs[NumRegs - 1];
1138
1139 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001140 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001141 }
1142
1143 template <unsigned NumRegs>
1144 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1145 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001146 static const unsigned FirstRegs[] = { AArch64::Q0,
1147 AArch64::Q0_Q1,
1148 AArch64::Q0_Q1_Q2,
1149 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001150 unsigned FirstReg = FirstRegs[NumRegs - 1];
1151
1152 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001153 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001154 }
1155
1156 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1157 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001158 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001159 }
1160
1161 void addVectorIndexBOperands(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 addVectorIndexHOperands(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 addVectorIndexSOperands(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 addVectorIndexDOperands(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 addImmOperands(MCInst &Inst, unsigned N) const {
1182 assert(N == 1 && "Invalid number of operands!");
1183 // If this is a pageoff symrefexpr with an addend, adjust the addend
1184 // to be only the page-offset portion. Otherwise, just add the expr
1185 // as-is.
1186 addExpr(Inst, getImm());
1187 }
1188
1189 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1190 assert(N == 2 && "Invalid number of operands!");
1191 if (isShiftedImm()) {
1192 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001193 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001194 } else {
1195 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001196 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001197 }
1198 }
1199
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001200 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1201 assert(N == 2 && "Invalid number of operands!");
1202
1203 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1204 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1205 int64_t Val = -CE->getValue();
1206 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1207
1208 Inst.addOperand(MCOperand::createImm(Val));
1209 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1210 }
1211
Tim Northover3b0846e2014-05-24 12:50:23 +00001212 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1213 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001214 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001215 }
1216
1217 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1218 assert(N == 1 && "Invalid number of operands!");
1219 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1220 if (!MCE)
1221 addExpr(Inst, getImm());
1222 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001223 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001224 }
1225
1226 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1227 addImmOperands(Inst, N);
1228 }
1229
1230 template<int Scale>
1231 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1232 assert(N == 1 && "Invalid number of operands!");
1233 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1234
1235 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001236 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001237 return;
1238 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001239 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001240 }
1241
1242 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1243 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001244 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001245 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001246 }
1247
Sam Parker6d42de72017-08-11 13:14:00 +00001248 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1249 assert(N == 1 && "Invalid number of operands!");
1250 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1251 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1252 }
1253
Tim Northover3b0846e2014-05-24 12:50:23 +00001254 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1255 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001256 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001257 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001258 }
1259
1260 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1261 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001262 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001263 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001264 }
1265
1266 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1267 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001268 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001269 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001270 }
1271
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001272 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1273 assert(N == 1 && "Invalid number of operands!");
1274 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1275 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1276 }
1277
Tim Northover3b0846e2014-05-24 12:50:23 +00001278 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1279 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001280 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001281 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001282 }
1283
1284 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1285 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001286 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001287 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001288 }
1289
1290 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1291 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001292 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001293 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001294 }
1295
1296 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1297 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001298 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001299 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001300 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001301 }
1302
1303 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1304 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001305 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001306 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001307 }
1308
1309 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1310 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001311 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001312 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001313 }
1314
1315 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1316 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001317 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001318 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001319 }
1320
1321 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1322 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001323 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001324 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001325 }
1326
1327 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1328 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001329 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001330 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001331 }
1332
1333 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1334 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001335 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001336 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001337 }
1338
1339 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1340 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001341 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001342 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001343 }
1344
1345 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1346 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001347 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001348 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001349 }
1350
1351 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1352 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001353 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001354 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001355 }
1356
1357 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1358 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001359 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001360 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001361 }
1362
Sander de Smalena1c259c2018-01-29 13:05:38 +00001363 template <typename T>
1364 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001365 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001366 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001367 typename std::make_unsigned<T>::type Val = MCE->getValue();
1368 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001369 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001370 }
1371
Sander de Smalena1c259c2018-01-29 13:05:38 +00001372 template <typename T>
1373 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001374 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001375 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001376 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1377 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001378 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001379 }
1380
Tim Northover3b0846e2014-05-24 12:50:23 +00001381 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1382 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001383 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001384 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001385 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001386 }
1387
1388 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1389 // Branch operands don't encode the low bits, so shift them off
1390 // here. If it's a label, however, just put it on directly as there's
1391 // not enough information now to do anything.
1392 assert(N == 1 && "Invalid number of operands!");
1393 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1394 if (!MCE) {
1395 addExpr(Inst, getImm());
1396 return;
1397 }
1398 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001399 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001400 }
1401
1402 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1403 // Branch operands don't encode the low bits, so shift them off
1404 // here. If it's a label, however, just put it on directly as there's
1405 // not enough information now to do anything.
1406 assert(N == 1 && "Invalid number of operands!");
1407 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1408 if (!MCE) {
1409 addExpr(Inst, getImm());
1410 return;
1411 }
1412 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001413 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001414 }
1415
1416 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1417 // Branch operands don't encode the low bits, so shift them off
1418 // here. If it's a label, however, just put it on directly as there's
1419 // not enough information now to do anything.
1420 assert(N == 1 && "Invalid number of operands!");
1421 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1422 if (!MCE) {
1423 addExpr(Inst, getImm());
1424 return;
1425 }
1426 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001427 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001428 }
1429
1430 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1431 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001432 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001433 }
1434
1435 void addBarrierOperands(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(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001438 }
1439
1440 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1441 assert(N == 1 && "Invalid number of operands!");
1442
Jim Grosbache9119e42015-05-13 18:37:00 +00001443 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001444 }
1445
1446 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1447 assert(N == 1 && "Invalid number of operands!");
1448
Jim Grosbache9119e42015-05-13 18:37:00 +00001449 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001450 }
1451
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001452 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1453 assert(N == 1 && "Invalid number of operands!");
1454
1455 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1456 }
1457
1458 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001459 assert(N == 1 && "Invalid number of operands!");
1460
Jim Grosbache9119e42015-05-13 18:37:00 +00001461 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001462 }
1463
1464 void addSysCROperands(MCInst &Inst, unsigned N) const {
1465 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001466 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001467 }
1468
1469 void addPrefetchOperands(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(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001472 }
1473
Oliver Stannarda34e4702015-12-01 10:48:51 +00001474 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1475 assert(N == 1 && "Invalid number of operands!");
1476 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1477 }
1478
Tim Northover3b0846e2014-05-24 12:50:23 +00001479 void addShifterOperands(MCInst &Inst, unsigned N) const {
1480 assert(N == 1 && "Invalid number of operands!");
1481 unsigned Imm =
1482 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001483 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001484 }
1485
1486 void addExtendOperands(MCInst &Inst, unsigned N) const {
1487 assert(N == 1 && "Invalid number of operands!");
1488 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1489 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1490 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001491 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001492 }
1493
1494 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1495 assert(N == 1 && "Invalid number of operands!");
1496 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1497 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1498 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001499 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001500 }
1501
1502 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1503 assert(N == 2 && "Invalid number of operands!");
1504 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1505 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001506 Inst.addOperand(MCOperand::createImm(IsSigned));
1507 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001508 }
1509
1510 // For 8-bit load/store instructions with a register offset, both the
1511 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1512 // they're disambiguated by whether the shift was explicit or implicit rather
1513 // than its size.
1514 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1515 assert(N == 2 && "Invalid number of operands!");
1516 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1517 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001518 Inst.addOperand(MCOperand::createImm(IsSigned));
1519 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001520 }
1521
1522 template<int Shift>
1523 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1524 assert(N == 1 && "Invalid number of operands!");
1525
1526 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1527 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001528 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001529 }
1530
1531 template<int Shift>
1532 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1533 assert(N == 1 && "Invalid number of operands!");
1534
1535 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1536 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001537 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001538 }
1539
Sam Parker5f934642017-08-31 09:27:04 +00001540 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1541 assert(N == 1 && "Invalid number of operands!");
1542 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1543 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1544 }
1545
1546 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1547 assert(N == 1 && "Invalid number of operands!");
1548 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1549 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1550 }
1551
Tim Northover3b0846e2014-05-24 12:50:23 +00001552 void print(raw_ostream &OS) const override;
1553
David Blaikie960ea3f2014-06-08 16:18:35 +00001554 static std::unique_ptr<AArch64Operand>
1555 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1556 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001557 Op->Tok.Data = Str.data();
1558 Op->Tok.Length = Str.size();
1559 Op->Tok.IsSuffix = IsSuffix;
1560 Op->StartLoc = S;
1561 Op->EndLoc = S;
1562 return Op;
1563 }
1564
David Blaikie960ea3f2014-06-08 16:18:35 +00001565 static std::unique_ptr<AArch64Operand>
Florian Hahnc4422242017-11-07 13:07:50 +00001566 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001567 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001568 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001569 Op->Reg.Kind = Kind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001570 Op->StartLoc = S;
1571 Op->EndLoc = E;
1572 return Op;
1573 }
1574
David Blaikie960ea3f2014-06-08 16:18:35 +00001575 static std::unique_ptr<AArch64Operand>
Florian Hahn91f11e52017-11-07 16:45:48 +00001576 CreateReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1577 SMLoc S, SMLoc E, MCContext &Ctx) {
1578 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1579 Op->Reg.RegNum = RegNum;
1580 Op->Reg.ElementWidth = ElementWidth;
1581 Op->Reg.Kind = Kind;
1582 Op->StartLoc = S;
1583 Op->EndLoc = E;
1584 return Op;
1585 }
1586
1587 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001588 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1589 char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1590 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001591 Op->VectorList.RegNum = RegNum;
1592 Op->VectorList.Count = Count;
1593 Op->VectorList.NumElements = NumElements;
1594 Op->VectorList.ElementKind = ElementKind;
1595 Op->StartLoc = S;
1596 Op->EndLoc = E;
1597 return Op;
1598 }
1599
David Blaikie960ea3f2014-06-08 16:18:35 +00001600 static std::unique_ptr<AArch64Operand>
1601 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1602 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001603 Op->VectorIndex.Val = Idx;
1604 Op->StartLoc = S;
1605 Op->EndLoc = E;
1606 return Op;
1607 }
1608
David Blaikie960ea3f2014-06-08 16:18:35 +00001609 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1610 SMLoc E, MCContext &Ctx) {
1611 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001612 Op->Imm.Val = Val;
1613 Op->StartLoc = S;
1614 Op->EndLoc = E;
1615 return Op;
1616 }
1617
David Blaikie960ea3f2014-06-08 16:18:35 +00001618 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1619 unsigned ShiftAmount,
1620 SMLoc S, SMLoc E,
1621 MCContext &Ctx) {
1622 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001623 Op->ShiftedImm .Val = Val;
1624 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1625 Op->StartLoc = S;
1626 Op->EndLoc = E;
1627 return Op;
1628 }
1629
David Blaikie960ea3f2014-06-08 16:18:35 +00001630 static std::unique_ptr<AArch64Operand>
1631 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1632 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001633 Op->CondCode.Code = Code;
1634 Op->StartLoc = S;
1635 Op->EndLoc = E;
1636 return Op;
1637 }
1638
David Blaikie960ea3f2014-06-08 16:18:35 +00001639 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1640 MCContext &Ctx) {
1641 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001642 Op->FPImm.Val = Val;
1643 Op->StartLoc = S;
1644 Op->EndLoc = S;
1645 return Op;
1646 }
1647
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001648 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1649 StringRef Str,
1650 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001651 MCContext &Ctx) {
1652 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001653 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001654 Op->Barrier.Data = Str.data();
1655 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001656 Op->StartLoc = S;
1657 Op->EndLoc = S;
1658 return Op;
1659 }
1660
Tim Northover7cd58932015-01-22 17:23:04 +00001661 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1662 uint32_t MRSReg,
1663 uint32_t MSRReg,
1664 uint32_t PStateField,
1665 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001666 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001667 Op->SysReg.Data = Str.data();
1668 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001669 Op->SysReg.MRSReg = MRSReg;
1670 Op->SysReg.MSRReg = MSRReg;
1671 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001672 Op->StartLoc = S;
1673 Op->EndLoc = S;
1674 return Op;
1675 }
1676
David Blaikie960ea3f2014-06-08 16:18:35 +00001677 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1678 SMLoc E, MCContext &Ctx) {
1679 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001680 Op->SysCRImm.Val = Val;
1681 Op->StartLoc = S;
1682 Op->EndLoc = E;
1683 return Op;
1684 }
1685
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001686 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1687 StringRef Str,
1688 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001689 MCContext &Ctx) {
1690 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001691 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001692 Op->Barrier.Data = Str.data();
1693 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001694 Op->StartLoc = S;
1695 Op->EndLoc = S;
1696 return Op;
1697 }
1698
Oliver Stannarda34e4702015-12-01 10:48:51 +00001699 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1700 StringRef Str,
1701 SMLoc S,
1702 MCContext &Ctx) {
1703 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1704 Op->PSBHint.Val = Val;
1705 Op->PSBHint.Data = Str.data();
1706 Op->PSBHint.Length = Str.size();
1707 Op->StartLoc = S;
1708 Op->EndLoc = S;
1709 return Op;
1710 }
1711
David Blaikie960ea3f2014-06-08 16:18:35 +00001712 static std::unique_ptr<AArch64Operand>
1713 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1714 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1715 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001716 Op->ShiftExtend.Type = ShOp;
1717 Op->ShiftExtend.Amount = Val;
1718 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1719 Op->StartLoc = S;
1720 Op->EndLoc = E;
1721 return Op;
1722 }
1723};
1724
1725} // end anonymous namespace.
1726
1727void AArch64Operand::print(raw_ostream &OS) const {
1728 switch (Kind) {
1729 case k_FPImm:
1730 OS << "<fpimm " << getFPImm() << "("
1731 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1732 break;
1733 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001734 StringRef Name = getBarrierName();
1735 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001736 OS << "<barrier " << Name << ">";
1737 else
1738 OS << "<barrier invalid #" << getBarrier() << ">";
1739 break;
1740 }
1741 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001742 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001743 break;
1744 case k_ShiftedImm: {
1745 unsigned Shift = getShiftedImmShift();
1746 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001747 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001748 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1749 break;
1750 }
1751 case k_CondCode:
1752 OS << "<condcode " << getCondCode() << ">";
1753 break;
1754 case k_Register:
1755 OS << "<register " << getReg() << ">";
1756 break;
1757 case k_VectorList: {
1758 OS << "<vectorlist ";
1759 unsigned Reg = getVectorListStart();
1760 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1761 OS << Reg + i << " ";
1762 OS << ">";
1763 break;
1764 }
1765 case k_VectorIndex:
1766 OS << "<vectorindex " << getVectorIndex() << ">";
1767 break;
1768 case k_SysReg:
1769 OS << "<sysreg: " << getSysReg() << '>';
1770 break;
1771 case k_Token:
1772 OS << "'" << getToken() << "'";
1773 break;
1774 case k_SysCR:
1775 OS << "c" << getSysCR();
1776 break;
1777 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001778 StringRef Name = getPrefetchName();
1779 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001780 OS << "<prfop " << Name << ">";
1781 else
1782 OS << "<prfop invalid #" << getPrefetch() << ">";
1783 break;
1784 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001785 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001786 OS << getPSBHintName();
1787 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001788 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001789 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1790 << getShiftExtendAmount();
1791 if (!hasShiftExtendAmount())
1792 OS << "<imp>";
1793 OS << '>';
1794 break;
1795 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001796}
1797
1798/// @name Auto-generated Match Functions
1799/// {
1800
1801static unsigned MatchRegisterName(StringRef Name);
1802
1803/// }
1804
Florian Hahnc4422242017-11-07 13:07:50 +00001805static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001806 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001807 .Case("v0", AArch64::Q0)
1808 .Case("v1", AArch64::Q1)
1809 .Case("v2", AArch64::Q2)
1810 .Case("v3", AArch64::Q3)
1811 .Case("v4", AArch64::Q4)
1812 .Case("v5", AArch64::Q5)
1813 .Case("v6", AArch64::Q6)
1814 .Case("v7", AArch64::Q7)
1815 .Case("v8", AArch64::Q8)
1816 .Case("v9", AArch64::Q9)
1817 .Case("v10", AArch64::Q10)
1818 .Case("v11", AArch64::Q11)
1819 .Case("v12", AArch64::Q12)
1820 .Case("v13", AArch64::Q13)
1821 .Case("v14", AArch64::Q14)
1822 .Case("v15", AArch64::Q15)
1823 .Case("v16", AArch64::Q16)
1824 .Case("v17", AArch64::Q17)
1825 .Case("v18", AArch64::Q18)
1826 .Case("v19", AArch64::Q19)
1827 .Case("v20", AArch64::Q20)
1828 .Case("v21", AArch64::Q21)
1829 .Case("v22", AArch64::Q22)
1830 .Case("v23", AArch64::Q23)
1831 .Case("v24", AArch64::Q24)
1832 .Case("v25", AArch64::Q25)
1833 .Case("v26", AArch64::Q26)
1834 .Case("v27", AArch64::Q27)
1835 .Case("v28", AArch64::Q28)
1836 .Case("v29", AArch64::Q29)
1837 .Case("v30", AArch64::Q30)
1838 .Case("v31", AArch64::Q31)
1839 .Default(0);
1840}
1841
1842static bool isValidVectorKind(StringRef Name) {
1843 return StringSwitch<bool>(Name.lower())
1844 .Case(".8b", true)
1845 .Case(".16b", true)
1846 .Case(".4h", true)
1847 .Case(".8h", true)
1848 .Case(".2s", true)
1849 .Case(".4s", true)
1850 .Case(".1d", true)
1851 .Case(".2d", true)
1852 .Case(".1q", true)
1853 // Accept the width neutral ones, too, for verbose syntax. If those
1854 // aren't used in the right places, the token operand won't match so
1855 // all will work out.
1856 .Case(".b", true)
1857 .Case(".h", true)
1858 .Case(".s", true)
1859 .Case(".d", true)
Oliver Stannarde4c3d212015-12-08 12:16:10 +00001860 // Needed for fp16 scalar pairwise reductions
1861 .Case(".2h", true)
Sjoerd Meijer79876332017-08-09 14:59:54 +00001862 // another special case for the ARMv8.2a dot product operand
1863 .Case(".4b", true)
Tim Northover3b0846e2014-05-24 12:50:23 +00001864 .Default(false);
1865}
1866
Florian Hahn91f11e52017-11-07 16:45:48 +00001867static unsigned matchSVEDataVectorRegName(StringRef Name) {
1868 return StringSwitch<unsigned>(Name.lower())
1869 .Case("z0", AArch64::Z0)
1870 .Case("z1", AArch64::Z1)
1871 .Case("z2", AArch64::Z2)
1872 .Case("z3", AArch64::Z3)
1873 .Case("z4", AArch64::Z4)
1874 .Case("z5", AArch64::Z5)
1875 .Case("z6", AArch64::Z6)
1876 .Case("z7", AArch64::Z7)
1877 .Case("z8", AArch64::Z8)
1878 .Case("z9", AArch64::Z9)
1879 .Case("z10", AArch64::Z10)
1880 .Case("z11", AArch64::Z11)
1881 .Case("z12", AArch64::Z12)
1882 .Case("z13", AArch64::Z13)
1883 .Case("z14", AArch64::Z14)
1884 .Case("z15", AArch64::Z15)
1885 .Case("z16", AArch64::Z16)
1886 .Case("z17", AArch64::Z17)
1887 .Case("z18", AArch64::Z18)
1888 .Case("z19", AArch64::Z19)
1889 .Case("z20", AArch64::Z20)
1890 .Case("z21", AArch64::Z21)
1891 .Case("z22", AArch64::Z22)
1892 .Case("z23", AArch64::Z23)
1893 .Case("z24", AArch64::Z24)
1894 .Case("z25", AArch64::Z25)
1895 .Case("z26", AArch64::Z26)
1896 .Case("z27", AArch64::Z27)
1897 .Case("z28", AArch64::Z28)
1898 .Case("z29", AArch64::Z29)
1899 .Case("z30", AArch64::Z30)
1900 .Case("z31", AArch64::Z31)
1901 .Default(0);
1902}
1903
Sander de Smalencd6be962017-12-20 11:02:42 +00001904static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1905 return StringSwitch<unsigned>(Name.lower())
1906 .Case("p0", AArch64::P0)
1907 .Case("p1", AArch64::P1)
1908 .Case("p2", AArch64::P2)
1909 .Case("p3", AArch64::P3)
1910 .Case("p4", AArch64::P4)
1911 .Case("p5", AArch64::P5)
1912 .Case("p6", AArch64::P6)
1913 .Case("p7", AArch64::P7)
1914 .Case("p8", AArch64::P8)
1915 .Case("p9", AArch64::P9)
1916 .Case("p10", AArch64::P10)
1917 .Case("p11", AArch64::P11)
1918 .Case("p12", AArch64::P12)
1919 .Case("p13", AArch64::P13)
1920 .Case("p14", AArch64::P14)
1921 .Case("p15", AArch64::P15)
1922 .Default(0);
1923}
1924
Florian Hahn91f11e52017-11-07 16:45:48 +00001925static bool isValidSVEKind(StringRef Name) {
1926 return StringSwitch<bool>(Name.lower())
1927 .Case(".b", true)
1928 .Case(".h", true)
1929 .Case(".s", true)
1930 .Case(".d", true)
1931 .Case(".q", true)
1932 .Default(false);
1933}
1934
Tim Northover3b0846e2014-05-24 12:50:23 +00001935static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1936 char &ElementKind) {
1937 assert(isValidVectorKind(Name));
1938
1939 ElementKind = Name.lower()[Name.size() - 1];
1940 NumElements = 0;
1941
1942 if (Name.size() == 2)
1943 return;
1944
1945 // Parse the lane count
1946 Name = Name.drop_front();
1947 while (isdigit(Name.front())) {
1948 NumElements = 10 * NumElements + (Name.front() - '0');
1949 Name = Name.drop_front();
1950 }
1951}
1952
1953bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1954 SMLoc &EndLoc) {
1955 StartLoc = getLoc();
1956 RegNo = tryParseRegister();
1957 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1958 return (RegNo == (unsigned)-1);
1959}
1960
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001961// Matches a register name or register alias previously defined by '.req'
1962unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001963 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001964 unsigned RegNum = 0;
1965 if ((RegNum = matchSVEDataVectorRegName(Name)))
1966 return Kind == RegKind::SVEDataVector ? RegNum : 0;
1967
Sander de Smalencd6be962017-12-20 11:02:42 +00001968 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
1969 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
1970
Sander de Smalenc067c302017-12-20 09:45:45 +00001971 if ((RegNum = MatchNeonVectorRegName(Name)))
1972 return Kind == RegKind::NeonVector ? RegNum : 0;
1973
1974 // The parsed register must be of RegKind Scalar
1975 if ((RegNum = MatchRegisterName(Name)))
1976 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001977
Florian Hahnc4422242017-11-07 13:07:50 +00001978 if (!RegNum) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001979 // Check for aliases registered via .req. Canonicalize to lower case.
1980 // That's more consistent since register names are case insensitive, and
1981 // it's how the original entry was passed in from MC/MCParser/AsmParser.
1982 auto Entry = RegisterReqs.find(Name.lower());
1983 if (Entry == RegisterReqs.end())
1984 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00001985
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001986 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00001987 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001988 RegNum = Entry->getValue().second;
1989 }
1990 return RegNum;
1991}
1992
Tim Northover3b0846e2014-05-24 12:50:23 +00001993/// tryParseRegister - Try to parse a register name. The token must be an
1994/// Identifier when called, and if it is a register name the token is eaten and
1995/// the register is added to the operand list.
1996int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00001997 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001998 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00001999 if (Tok.isNot(AsmToken::Identifier))
2000 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00002001
2002 std::string lowerCase = Tok.getString().lower();
Florian Hahnc4422242017-11-07 13:07:50 +00002003 unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
Sander de Smalenc067c302017-12-20 09:45:45 +00002004
Tim Northover3b0846e2014-05-24 12:50:23 +00002005 // Also handle a few aliases of registers.
2006 if (RegNum == 0)
2007 RegNum = StringSwitch<unsigned>(lowerCase)
2008 .Case("fp", AArch64::FP)
2009 .Case("lr", AArch64::LR)
2010 .Case("x31", AArch64::XZR)
2011 .Case("w31", AArch64::WZR)
2012 .Default(0);
2013
2014 if (RegNum == 0)
2015 return -1;
2016
2017 Parser.Lex(); // Eat identifier token.
2018 return RegNum;
2019}
2020
2021/// tryMatchVectorRegister - Try to parse a vector register name with optional
2022/// kind specifier. If it is a register specifier, eat the token and return it.
2023int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002024 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002025 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2026 TokError("vector register expected");
2027 return -1;
2028 }
2029
2030 StringRef Name = Parser.getTok().getString();
2031 // If there is a kind specifier, it's separated from the register name by
2032 // a '.'.
2033 size_t Start = 0, Next = Name.find('.');
2034 StringRef Head = Name.slice(Start, Next);
Florian Hahnc4422242017-11-07 13:07:50 +00002035 unsigned RegNum = matchRegisterNameAlias(Head, RegKind::NeonVector);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002036
Tim Northover3b0846e2014-05-24 12:50:23 +00002037 if (RegNum) {
2038 if (Next != StringRef::npos) {
2039 Kind = Name.slice(Next, StringRef::npos);
2040 if (!isValidVectorKind(Kind)) {
2041 TokError("invalid vector kind qualifier");
2042 return -1;
2043 }
2044 }
2045 Parser.Lex(); // Eat the register token.
2046 return RegNum;
2047 }
2048
2049 if (expected)
2050 TokError("vector register expected");
2051 return -1;
2052}
2053
2054/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002055OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002056AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002057 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002058 SMLoc S = getLoc();
2059
2060 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2061 Error(S, "Expected cN operand where 0 <= N <= 15");
2062 return MatchOperand_ParseFail;
2063 }
2064
2065 StringRef Tok = Parser.getTok().getIdentifier();
2066 if (Tok[0] != 'c' && Tok[0] != 'C') {
2067 Error(S, "Expected cN operand where 0 <= N <= 15");
2068 return MatchOperand_ParseFail;
2069 }
2070
2071 uint32_t CRNum;
2072 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2073 if (BadNum || CRNum > 15) {
2074 Error(S, "Expected cN operand where 0 <= N <= 15");
2075 return MatchOperand_ParseFail;
2076 }
2077
2078 Parser.Lex(); // Eat identifier token.
2079 Operands.push_back(
2080 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2081 return MatchOperand_Success;
2082}
2083
2084/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002085OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002086AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002087 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002088 SMLoc S = getLoc();
2089 const AsmToken &Tok = Parser.getTok();
2090 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002091 // Eat optional hash.
2092 if (parseOptionalToken(AsmToken::Hash) ||
2093 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002094 const MCExpr *ImmVal;
2095 if (getParser().parseExpression(ImmVal))
2096 return MatchOperand_ParseFail;
2097
2098 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2099 if (!MCE) {
2100 TokError("immediate value expected for prefetch operand");
2101 return MatchOperand_ParseFail;
2102 }
2103 unsigned prfop = MCE->getValue();
2104 if (prfop > 31) {
2105 TokError("prefetch operand out of range, [0,31] expected");
2106 return MatchOperand_ParseFail;
2107 }
2108
Tim Northovere6ae6762016-07-05 21:23:04 +00002109 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2110 Operands.push_back(AArch64Operand::CreatePrefetch(
2111 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002112 return MatchOperand_Success;
2113 }
2114
2115 if (Tok.isNot(AsmToken::Identifier)) {
2116 TokError("pre-fetch hint expected");
2117 return MatchOperand_ParseFail;
2118 }
2119
Tim Northovere6ae6762016-07-05 21:23:04 +00002120 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2121 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002122 TokError("pre-fetch hint expected");
2123 return MatchOperand_ParseFail;
2124 }
2125
2126 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002127 Operands.push_back(AArch64Operand::CreatePrefetch(
2128 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002129 return MatchOperand_Success;
2130}
2131
Oliver Stannarda34e4702015-12-01 10:48:51 +00002132/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002133OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002134AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2135 MCAsmParser &Parser = getParser();
2136 SMLoc S = getLoc();
2137 const AsmToken &Tok = Parser.getTok();
2138 if (Tok.isNot(AsmToken::Identifier)) {
2139 TokError("invalid operand for instruction");
2140 return MatchOperand_ParseFail;
2141 }
2142
Tim Northovere6ae6762016-07-05 21:23:04 +00002143 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2144 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002145 TokError("invalid operand for instruction");
2146 return MatchOperand_ParseFail;
2147 }
2148
2149 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002150 Operands.push_back(AArch64Operand::CreatePSBHint(
2151 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002152 return MatchOperand_Success;
2153}
2154
Tim Northover3b0846e2014-05-24 12:50:23 +00002155/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2156/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002157OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002158AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002159 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002160 SMLoc S = getLoc();
2161 const MCExpr *Expr;
2162
2163 if (Parser.getTok().is(AsmToken::Hash)) {
2164 Parser.Lex(); // Eat hash token.
2165 }
2166
2167 if (parseSymbolicImmVal(Expr))
2168 return MatchOperand_ParseFail;
2169
2170 AArch64MCExpr::VariantKind ELFRefKind;
2171 MCSymbolRefExpr::VariantKind DarwinRefKind;
2172 int64_t Addend;
2173 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2174 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2175 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2176 // No modifier was specified at all; this is the syntax for an ELF basic
2177 // ADRP relocation (unfortunately).
2178 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002179 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002180 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2181 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2182 Addend != 0) {
2183 Error(S, "gotpage label reference not allowed an addend");
2184 return MatchOperand_ParseFail;
2185 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2186 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2187 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2188 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2189 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2190 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2191 // The operand must be an @page or @gotpage qualified symbolref.
2192 Error(S, "page or gotpage label reference expected");
2193 return MatchOperand_ParseFail;
2194 }
2195 }
2196
2197 // We have either a label reference possibly with addend or an immediate. The
2198 // addend is a raw value here. The linker will adjust it to only reference the
2199 // page.
2200 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2201 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2202
2203 return MatchOperand_Success;
2204}
2205
2206/// tryParseAdrLabel - Parse and validate a source label for the ADR
2207/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002208OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002209AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2210 SMLoc S = getLoc();
2211 const MCExpr *Expr;
2212
Nirav Davee833c6c2016-11-08 18:31:04 +00002213 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002214 if (getParser().parseExpression(Expr))
2215 return MatchOperand_ParseFail;
2216
2217 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2218 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2219
2220 return MatchOperand_Success;
2221}
2222
2223/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002224OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002225AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002226 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002227 SMLoc S = getLoc();
2228
Nirav Davee833c6c2016-11-08 18:31:04 +00002229 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002230
2231 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002232 bool isNegative = parseOptionalToken(AsmToken::Minus);
2233
Tim Northover3b0846e2014-05-24 12:50:23 +00002234 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002235 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002236 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002237 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002238 Val = Tok.getIntVal();
2239 if (Val > 255 || Val < 0) {
2240 TokError("encoded floating point value out of range");
2241 return MatchOperand_ParseFail;
2242 }
2243 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002244 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002245 if (isNegative)
2246 RealVal.changeSign();
2247
Tim Northover3b0846e2014-05-24 12:50:23 +00002248 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002249 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002250
John Brawn5ca5daa2017-04-20 10:13:54 +00002251 // Check for out of range values. As an exception we let Zero through,
2252 // but as tokens instead of an FPImm so that it can be matched by the
2253 // appropriate alias if one exists.
2254 if (RealVal.isPosZero()) {
2255 Parser.Lex(); // Eat the token.
2256 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2257 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2258 return MatchOperand_Success;
2259 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002260 TokError("expected compatible register or floating-point constant");
2261 return MatchOperand_ParseFail;
2262 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002263 }
2264 Parser.Lex(); // Eat the token.
2265 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2266 return MatchOperand_Success;
2267 }
2268
2269 if (!Hash)
2270 return MatchOperand_NoMatch;
2271
2272 TokError("invalid floating point immediate");
2273 return MatchOperand_ParseFail;
2274}
2275
2276/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002277OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002278AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002279 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002280 SMLoc S = getLoc();
2281
2282 if (Parser.getTok().is(AsmToken::Hash))
2283 Parser.Lex(); // Eat '#'
2284 else if (Parser.getTok().isNot(AsmToken::Integer))
2285 // Operand should start from # or should be integer, emit error otherwise.
2286 return MatchOperand_NoMatch;
2287
2288 const MCExpr *Imm;
2289 if (parseSymbolicImmVal(Imm))
2290 return MatchOperand_ParseFail;
2291 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2292 uint64_t ShiftAmount = 0;
2293 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2294 if (MCE) {
2295 int64_t Val = MCE->getValue();
2296 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002297 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002298 ShiftAmount = 12;
2299 }
2300 }
2301 SMLoc E = Parser.getTok().getLoc();
2302 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2303 getContext()));
2304 return MatchOperand_Success;
2305 }
2306
2307 // Eat ','
2308 Parser.Lex();
2309
2310 // The optional operand must be "lsl #N" where N is non-negative.
2311 if (!Parser.getTok().is(AsmToken::Identifier) ||
2312 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2313 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2314 return MatchOperand_ParseFail;
2315 }
2316
2317 // Eat 'lsl'
2318 Parser.Lex();
2319
Nirav Davee833c6c2016-11-08 18:31:04 +00002320 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002321
2322 if (Parser.getTok().isNot(AsmToken::Integer)) {
2323 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2324 return MatchOperand_ParseFail;
2325 }
2326
2327 int64_t ShiftAmount = Parser.getTok().getIntVal();
2328
2329 if (ShiftAmount < 0) {
2330 Error(Parser.getTok().getLoc(), "positive shift amount required");
2331 return MatchOperand_ParseFail;
2332 }
2333 Parser.Lex(); // Eat the number
2334
2335 SMLoc E = Parser.getTok().getLoc();
2336 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2337 S, E, getContext()));
2338 return MatchOperand_Success;
2339}
2340
2341/// parseCondCodeString - Parse a Condition Code string.
2342AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2343 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2344 .Case("eq", AArch64CC::EQ)
2345 .Case("ne", AArch64CC::NE)
2346 .Case("cs", AArch64CC::HS)
2347 .Case("hs", AArch64CC::HS)
2348 .Case("cc", AArch64CC::LO)
2349 .Case("lo", AArch64CC::LO)
2350 .Case("mi", AArch64CC::MI)
2351 .Case("pl", AArch64CC::PL)
2352 .Case("vs", AArch64CC::VS)
2353 .Case("vc", AArch64CC::VC)
2354 .Case("hi", AArch64CC::HI)
2355 .Case("ls", AArch64CC::LS)
2356 .Case("ge", AArch64CC::GE)
2357 .Case("lt", AArch64CC::LT)
2358 .Case("gt", AArch64CC::GT)
2359 .Case("le", AArch64CC::LE)
2360 .Case("al", AArch64CC::AL)
2361 .Case("nv", AArch64CC::NV)
2362 .Default(AArch64CC::Invalid);
2363 return CC;
2364}
2365
2366/// parseCondCode - Parse a Condition Code operand.
2367bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2368 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002369 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002370 SMLoc S = getLoc();
2371 const AsmToken &Tok = Parser.getTok();
2372 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2373
2374 StringRef Cond = Tok.getString();
2375 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2376 if (CC == AArch64CC::Invalid)
2377 return TokError("invalid condition code");
2378 Parser.Lex(); // Eat identifier token.
2379
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002380 if (invertCondCode) {
2381 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2382 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002383 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002384 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002385
2386 Operands.push_back(
2387 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2388 return false;
2389}
2390
2391/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2392/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002393OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002394AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002395 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002396 const AsmToken &Tok = Parser.getTok();
2397 std::string LowerID = Tok.getString().lower();
2398 AArch64_AM::ShiftExtendType ShOp =
2399 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2400 .Case("lsl", AArch64_AM::LSL)
2401 .Case("lsr", AArch64_AM::LSR)
2402 .Case("asr", AArch64_AM::ASR)
2403 .Case("ror", AArch64_AM::ROR)
2404 .Case("msl", AArch64_AM::MSL)
2405 .Case("uxtb", AArch64_AM::UXTB)
2406 .Case("uxth", AArch64_AM::UXTH)
2407 .Case("uxtw", AArch64_AM::UXTW)
2408 .Case("uxtx", AArch64_AM::UXTX)
2409 .Case("sxtb", AArch64_AM::SXTB)
2410 .Case("sxth", AArch64_AM::SXTH)
2411 .Case("sxtw", AArch64_AM::SXTW)
2412 .Case("sxtx", AArch64_AM::SXTX)
2413 .Default(AArch64_AM::InvalidShiftExtend);
2414
2415 if (ShOp == AArch64_AM::InvalidShiftExtend)
2416 return MatchOperand_NoMatch;
2417
2418 SMLoc S = Tok.getLoc();
2419 Parser.Lex();
2420
Nirav Davee833c6c2016-11-08 18:31:04 +00002421 bool Hash = parseOptionalToken(AsmToken::Hash);
2422
Tim Northover3b0846e2014-05-24 12:50:23 +00002423 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2424 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2425 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2426 ShOp == AArch64_AM::MSL) {
2427 // We expect a number here.
2428 TokError("expected #imm after shift specifier");
2429 return MatchOperand_ParseFail;
2430 }
2431
Chad Rosier2ff37b82016-12-27 16:58:09 +00002432 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002433 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2434 Operands.push_back(
2435 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2436 return MatchOperand_Success;
2437 }
2438
Chad Rosier2ff37b82016-12-27 16:58:09 +00002439 // Make sure we do actually have a number, identifier or a parenthesized
2440 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002441 SMLoc E = Parser.getTok().getLoc();
2442 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002443 !Parser.getTok().is(AsmToken::LParen) &&
2444 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002445 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002446 return MatchOperand_ParseFail;
2447 }
2448
2449 const MCExpr *ImmVal;
2450 if (getParser().parseExpression(ImmVal))
2451 return MatchOperand_ParseFail;
2452
2453 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2454 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002455 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002456 return MatchOperand_ParseFail;
2457 }
2458
Jim Grosbach57fd2622014-09-23 22:16:02 +00002459 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002460 Operands.push_back(AArch64Operand::CreateShiftExtend(
2461 ShOp, MCE->getValue(), true, S, E, getContext()));
2462 return MatchOperand_Success;
2463}
2464
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002465static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2466 if (FBS[AArch64::HasV8_1aOps])
2467 Str += "ARMv8.1a";
2468 else if (FBS[AArch64::HasV8_2aOps])
2469 Str += "ARMv8.2a";
2470 else
2471 Str += "(unknown)";
2472}
2473
2474void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2475 SMLoc S) {
2476 const uint16_t Op2 = Encoding & 7;
2477 const uint16_t Cm = (Encoding & 0x78) >> 3;
2478 const uint16_t Cn = (Encoding & 0x780) >> 7;
2479 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2480
2481 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2482
2483 Operands.push_back(
2484 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2485 Operands.push_back(
2486 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2487 Operands.push_back(
2488 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2489 Expr = MCConstantExpr::create(Op2, getContext());
2490 Operands.push_back(
2491 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2492}
2493
Tim Northover3b0846e2014-05-24 12:50:23 +00002494/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2495/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2496bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2497 OperandVector &Operands) {
2498 if (Name.find('.') != StringRef::npos)
2499 return TokError("invalid operand");
2500
2501 Mnemonic = Name;
2502 Operands.push_back(
2503 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2504
Rafael Espindola961d4692014-11-11 05:18:41 +00002505 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002506 const AsmToken &Tok = Parser.getTok();
2507 StringRef Op = Tok.getString();
2508 SMLoc S = Tok.getLoc();
2509
Tim Northover3b0846e2014-05-24 12:50:23 +00002510 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002511 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2512 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002513 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002514 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2515 std::string Str("IC " + std::string(IC->Name) + " requires ");
2516 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2517 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002518 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002519 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002520 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002521 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2522 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002523 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002524 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2525 std::string Str("DC " + std::string(DC->Name) + " requires ");
2526 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2527 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002528 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002529 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002530 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002531 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2532 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002533 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002534 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2535 std::string Str("AT " + std::string(AT->Name) + " requires ");
2536 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2537 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002538 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002539 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002540 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002541 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2542 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002543 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002544 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2545 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2546 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2547 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002548 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002549 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002550 }
2551
Tim Northover3b0846e2014-05-24 12:50:23 +00002552 Parser.Lex(); // Eat operand.
2553
2554 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2555 bool HasRegister = false;
2556
2557 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002558 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002559 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2560 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002561 HasRegister = true;
2562 }
2563
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002564 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002565 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002566 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002567 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002568
Nirav Davee833c6c2016-11-08 18:31:04 +00002569 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2570 return true;
2571
Tim Northover3b0846e2014-05-24 12:50:23 +00002572 return false;
2573}
2574
Alex Bradbury58eba092016-11-01 16:32:05 +00002575OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002576AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002577 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002578 const AsmToken &Tok = Parser.getTok();
2579
2580 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002581 if (parseOptionalToken(AsmToken::Hash) ||
2582 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002583 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002584 const MCExpr *ImmVal;
2585 SMLoc ExprLoc = getLoc();
2586 if (getParser().parseExpression(ImmVal))
2587 return MatchOperand_ParseFail;
2588 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2589 if (!MCE) {
2590 Error(ExprLoc, "immediate value expected for barrier operand");
2591 return MatchOperand_ParseFail;
2592 }
2593 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2594 Error(ExprLoc, "barrier operand out of range");
2595 return MatchOperand_ParseFail;
2596 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002597 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2598 Operands.push_back(AArch64Operand::CreateBarrier(
2599 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002600 return MatchOperand_Success;
2601 }
2602
2603 if (Tok.isNot(AsmToken::Identifier)) {
2604 TokError("invalid operand for instruction");
2605 return MatchOperand_ParseFail;
2606 }
2607
Tim Northover3b0846e2014-05-24 12:50:23 +00002608 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002609 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2610 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002611 TokError("'sy' or #imm operand expected");
2612 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002613 } else if (!DB) {
2614 TokError("invalid barrier option name");
2615 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002616 }
2617
Tim Northovere6ae6762016-07-05 21:23:04 +00002618 Operands.push_back(AArch64Operand::CreateBarrier(
2619 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002620 Parser.Lex(); // Consume the option
2621
2622 return MatchOperand_Success;
2623}
2624
Alex Bradbury58eba092016-11-01 16:32:05 +00002625OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002626AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002627 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002628 const AsmToken &Tok = Parser.getTok();
2629
2630 if (Tok.isNot(AsmToken::Identifier))
2631 return MatchOperand_NoMatch;
2632
Tim Northovere6ae6762016-07-05 21:23:04 +00002633 int MRSReg, MSRReg;
2634 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2635 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2636 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2637 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2638 } else
2639 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002640
Tim Northovere6ae6762016-07-05 21:23:04 +00002641 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2642 unsigned PStateImm = -1;
2643 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2644 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002645
Tim Northovere6ae6762016-07-05 21:23:04 +00002646 Operands.push_back(
2647 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2648 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002649 Parser.Lex(); // Eat identifier
2650
2651 return MatchOperand_Success;
2652}
2653
Florian Hahnc4422242017-11-07 13:07:50 +00002654/// tryParseNeonVectorRegister - Parse a vector register operand.
2655bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002656 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002657 if (Parser.getTok().isNot(AsmToken::Identifier))
2658 return true;
2659
2660 SMLoc S = getLoc();
2661 // Check for a vector register specifier first.
2662 StringRef Kind;
2663 int64_t Reg = tryMatchVectorRegister(Kind, false);
2664 if (Reg == -1)
2665 return true;
2666 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00002667 AArch64Operand::CreateReg(Reg, RegKind::NeonVector, S, getLoc(),
2668 getContext()));
2669
Tim Northover3b0846e2014-05-24 12:50:23 +00002670 // If there was an explicit qualifier, that goes on as a literal text
2671 // operand.
2672 if (!Kind.empty())
2673 Operands.push_back(
2674 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2675
2676 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002677 SMLoc SIdx = getLoc();
2678 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002679 const MCExpr *ImmVal;
2680 if (getParser().parseExpression(ImmVal))
2681 return false;
2682 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2683 if (!MCE) {
2684 TokError("immediate value expected for vector index");
2685 return false;
2686 }
2687
2688 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002689
Nirav Davee833c6c2016-11-08 18:31:04 +00002690 if (parseToken(AsmToken::RBrac, "']' expected"))
2691 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002692
2693 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2694 E, getContext()));
2695 }
2696
2697 return false;
2698}
2699
Florian Hahn91f11e52017-11-07 16:45:48 +00002700// tryParseSVEDataVectorRegister - Try to parse a SVE vector register name with
2701// optional kind specifier. If it is a register specifier, eat the token
2702// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002703OperandMatchResultTy
2704AArch64AsmParser::tryParseSVERegister(int &Reg, StringRef &Kind,
2705 RegKind MatchKind) {
2706 MCAsmParser &Parser = getParser();
2707 const AsmToken &Tok = Parser.getTok();
2708
Florian Hahn91f11e52017-11-07 16:45:48 +00002709 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002710 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002711
2712 StringRef Name = Tok.getString();
2713 // If there is a kind specifier, it's separated from the register name by
2714 // a '.'.
2715 size_t Start = 0, Next = Name.find('.');
2716 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002717 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002718
2719 if (RegNum) {
2720 if (Next != StringRef::npos) {
2721 Kind = Name.slice(Next, StringRef::npos);
2722 if (!isValidSVEKind(Kind)) {
2723 TokError("invalid sve vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002724 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002725 }
2726 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002727 Parser.Lex(); // Eat the register token.
2728
2729 Reg = RegNum;
2730 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002731 }
2732
Sander de Smalen8e607342017-11-15 15:44:43 +00002733 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002734}
2735
Sander de Smalencd6be962017-12-20 11:02:42 +00002736/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2737OperandMatchResultTy
2738AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2739 // Check for a SVE predicate register specifier first.
2740 const SMLoc S = getLoc();
2741 StringRef Kind;
2742 int RegNum = -1;
2743 auto Res = tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
2744 if (Res != MatchOperand_Success)
2745 return Res;
2746
2747 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
2748 .Case("", -1)
2749 .Case(".b", 8)
2750 .Case(".h", 16)
2751 .Case(".s", 32)
2752 .Case(".d", 64)
2753 .Case(".q", 128)
2754 .Default(0);
2755
2756 if (!ElementWidth)
2757 return MatchOperand_NoMatch;
2758
2759 Operands.push_back(
2760 AArch64Operand::CreateReg(RegNum, RegKind::SVEPredicateVector,
2761 ElementWidth, S, getLoc(), getContext()));
2762
Sander de Smalen7868e742018-01-09 11:17:06 +00002763 // Not all predicates are followed by a '/m' or '/z'.
2764 MCAsmParser &Parser = getParser();
2765 if (Parser.getTok().isNot(AsmToken::Slash))
2766 return MatchOperand_Success;
2767
2768 // But when they do they shouldn't have an element type suffix.
2769 if (!Kind.empty()) {
2770 Error(S, "not expecting size suffix");
2771 return MatchOperand_ParseFail;
2772 }
2773
2774 // Add a literal slash as operand
2775 Operands.push_back(
2776 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2777
2778 Parser.Lex(); // Eat the slash.
2779
2780 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002781 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002782 if (Pred != "z" && Pred != "m") {
2783 Error(getLoc(), "expecting 'm' or 'z' predication");
2784 return MatchOperand_ParseFail;
2785 }
2786
2787 // Add zero/merge token.
2788 const char *ZM = Pred == "z" ? "z" : "m";
2789 Operands.push_back(
2790 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2791
2792 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002793 return MatchOperand_Success;
2794}
2795
Tim Northover3b0846e2014-05-24 12:50:23 +00002796/// parseRegister - Parse a non-vector register operand.
2797bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2798 SMLoc S = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00002799 // Try for a vector (neon) register.
2800 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002801 return false;
2802
2803 // Try for a scalar register.
2804 int64_t Reg = tryParseRegister();
2805 if (Reg == -1)
2806 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002807 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2808 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002809
Tim Northover3b0846e2014-05-24 12:50:23 +00002810 return false;
2811}
2812
2813bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002814 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002815 bool HasELFModifier = false;
2816 AArch64MCExpr::VariantKind RefKind;
2817
Nirav Davee833c6c2016-11-08 18:31:04 +00002818 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002819 HasELFModifier = true;
2820
Nirav Davee833c6c2016-11-08 18:31:04 +00002821 if (Parser.getTok().isNot(AsmToken::Identifier))
2822 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002823
2824 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2825 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2826 .Case("lo12", AArch64MCExpr::VK_LO12)
2827 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2828 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2829 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2830 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2831 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2832 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2833 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2834 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2835 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2836 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2837 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2838 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2839 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2840 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2841 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2842 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2843 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2844 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2845 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2846 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2847 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2848 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2849 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2850 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2851 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2852 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2853 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2854 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2855 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2856 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2857 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2858 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2859 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2860 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002861 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2862 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002863 .Default(AArch64MCExpr::VK_INVALID);
2864
Nirav Davee833c6c2016-11-08 18:31:04 +00002865 if (RefKind == AArch64MCExpr::VK_INVALID)
2866 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002867
2868 Parser.Lex(); // Eat identifier
2869
Nirav Davee833c6c2016-11-08 18:31:04 +00002870 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002871 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002872 }
2873
2874 if (getParser().parseExpression(ImmVal))
2875 return true;
2876
2877 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002878 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002879
2880 return false;
2881}
2882
2883/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2884bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002885 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002886 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2887 SMLoc S = getLoc();
2888 Parser.Lex(); // Eat left bracket token.
2889 StringRef Kind;
2890 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2891 if (FirstReg == -1)
2892 return true;
2893 int64_t PrevReg = FirstReg;
2894 unsigned Count = 1;
2895
Nirav Davee833c6c2016-11-08 18:31:04 +00002896 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002897 SMLoc Loc = getLoc();
2898 StringRef NextKind;
2899 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2900 if (Reg == -1)
2901 return true;
2902 // Any Kind suffices must match on all regs in the list.
2903 if (Kind != NextKind)
2904 return Error(Loc, "mismatched register size suffix");
2905
2906 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2907
2908 if (Space == 0 || Space > 3) {
2909 return Error(Loc, "invalid number of vectors");
2910 }
2911
2912 Count += Space;
2913 }
2914 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002915 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002916 SMLoc Loc = getLoc();
2917 StringRef NextKind;
2918 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2919 if (Reg == -1)
2920 return true;
2921 // Any Kind suffices must match on all regs in the list.
2922 if (Kind != NextKind)
2923 return Error(Loc, "mismatched register size suffix");
2924
2925 // Registers must be incremental (with wraparound at 31)
2926 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2927 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2928 return Error(Loc, "registers must be sequential");
2929
2930 PrevReg = Reg;
2931 ++Count;
2932 }
2933 }
2934
Nirav Davee833c6c2016-11-08 18:31:04 +00002935 if (parseToken(AsmToken::RCurly, "'}' expected"))
2936 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002937
2938 if (Count > 4)
2939 return Error(S, "invalid number of vectors");
2940
2941 unsigned NumElements = 0;
2942 char ElementKind = 0;
2943 if (!Kind.empty())
2944 parseValidVectorKind(Kind, NumElements, ElementKind);
2945
2946 Operands.push_back(AArch64Operand::CreateVectorList(
2947 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
2948
2949 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002950 SMLoc SIdx = getLoc();
2951 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002952 const MCExpr *ImmVal;
2953 if (getParser().parseExpression(ImmVal))
2954 return false;
2955 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2956 if (!MCE) {
2957 TokError("immediate value expected for vector index");
2958 return false;
2959 }
2960
2961 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002962 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002963 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002964
2965 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2966 E, getContext()));
2967 }
2968 return false;
2969}
2970
Alex Bradbury58eba092016-11-01 16:32:05 +00002971OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002972AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002973 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002974 const AsmToken &Tok = Parser.getTok();
2975 if (!Tok.is(AsmToken::Identifier))
2976 return MatchOperand_NoMatch;
2977
Florian Hahnc4422242017-11-07 13:07:50 +00002978 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00002979
2980 MCContext &Ctx = getContext();
2981 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
2982 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
2983 return MatchOperand_NoMatch;
2984
2985 SMLoc S = getLoc();
2986 Parser.Lex(); // Eat register
2987
Nirav Davee833c6c2016-11-08 18:31:04 +00002988 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002989 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00002990 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00002991 return MatchOperand_Success;
2992 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002993
Nirav Davee833c6c2016-11-08 18:31:04 +00002994 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002995
2996 if (Parser.getTok().isNot(AsmToken::Integer)) {
2997 Error(getLoc(), "index must be absent or #0");
2998 return MatchOperand_ParseFail;
2999 }
3000
3001 const MCExpr *ImmVal;
3002 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3003 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3004 Error(getLoc(), "index must be absent or #0");
3005 return MatchOperand_ParseFail;
3006 }
3007
3008 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003009 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003010 return MatchOperand_Success;
3011}
3012
3013/// parseOperand - Parse a arm instruction operand. For now this parses the
3014/// operand regardless of the mnemonic.
3015bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3016 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003017 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003018
3019 OperandMatchResultTy ResTy =
3020 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3021
Tim Northover3b0846e2014-05-24 12:50:23 +00003022 // Check if the current operand has a custom associated parser, if so, try to
3023 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003024 if (ResTy == MatchOperand_Success)
3025 return false;
3026 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3027 // there was a match, but an error occurred, in which case, just return that
3028 // the operand parsing failed.
3029 if (ResTy == MatchOperand_ParseFail)
3030 return true;
3031
3032 // Nothing custom, so do general case parsing.
3033 SMLoc S, E;
3034 switch (getLexer().getKind()) {
3035 default: {
3036 SMLoc S = getLoc();
3037 const MCExpr *Expr;
3038 if (parseSymbolicImmVal(Expr))
3039 return Error(S, "invalid operand");
3040
3041 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3042 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3043 return false;
3044 }
3045 case AsmToken::LBrac: {
3046 SMLoc Loc = Parser.getTok().getLoc();
3047 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3048 getContext()));
3049 Parser.Lex(); // Eat '['
3050
3051 // There's no comma after a '[', so we can parse the next operand
3052 // immediately.
3053 return parseOperand(Operands, false, false);
3054 }
3055 case AsmToken::LCurly:
3056 return parseVectorList(Operands);
3057 case AsmToken::Identifier: {
3058 // If we're expecting a Condition Code operand, then just parse that.
3059 if (isCondCode)
3060 return parseCondCode(Operands, invertCondCode);
3061
3062 // If it's a register name, parse it.
3063 if (!parseRegister(Operands))
3064 return false;
3065
3066 // This could be an optional "shift" or "extend" operand.
3067 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3068 // We can only continue if no tokens were eaten.
3069 if (GotShift != MatchOperand_NoMatch)
3070 return GotShift;
3071
3072 // This was not a register so parse other operands that start with an
3073 // identifier (like labels) as expressions and create them as immediates.
3074 const MCExpr *IdVal;
3075 S = getLoc();
3076 if (getParser().parseExpression(IdVal))
3077 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003078 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3079 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3080 return false;
3081 }
3082 case AsmToken::Integer:
3083 case AsmToken::Real:
3084 case AsmToken::Hash: {
3085 // #42 -> immediate.
3086 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003087
3088 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003089
3090 // Parse a negative sign
3091 bool isNegative = false;
3092 if (Parser.getTok().is(AsmToken::Minus)) {
3093 isNegative = true;
3094 // We need to consume this token only when we have a Real, otherwise
3095 // we let parseSymbolicImmVal take care of it
3096 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3097 Parser.Lex();
3098 }
3099
3100 // The only Real that should come through here is a literal #0.0 for
3101 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3102 // so convert the value.
3103 const AsmToken &Tok = Parser.getTok();
3104 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003105 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003106 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3107 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3108 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3109 Mnemonic != "fcmlt")
3110 return TokError("unexpected floating point literal");
3111 else if (IntVal != 0 || isNegative)
3112 return TokError("expected floating-point constant #0.0");
3113 Parser.Lex(); // Eat the token.
3114
3115 Operands.push_back(
3116 AArch64Operand::CreateToken("#0", false, S, getContext()));
3117 Operands.push_back(
3118 AArch64Operand::CreateToken(".0", false, S, getContext()));
3119 return false;
3120 }
3121
3122 const MCExpr *ImmVal;
3123 if (parseSymbolicImmVal(ImmVal))
3124 return true;
3125
3126 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3127 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3128 return false;
3129 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003130 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003131 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003132 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003133 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003134 Parser.Lex(); // Eat '='
3135 const MCExpr *SubExprVal;
3136 if (getParser().parseExpression(SubExprVal))
3137 return true;
3138
David Peixottoae5ba762014-07-18 16:05:14 +00003139 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003140 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003141 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003142
3143 bool IsXReg =
3144 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3145 Operands[1]->getReg());
3146
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003147 MCContext& Ctx = getContext();
3148 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3149 // 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 +00003150 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003151 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3152 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3153 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3154 ShiftAmt += 16;
3155 Imm >>= 16;
3156 }
3157 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3158 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3159 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003160 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003161 if (ShiftAmt)
3162 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3163 ShiftAmt, true, S, E, Ctx));
3164 return false;
3165 }
David Peixottoae5ba762014-07-18 16:05:14 +00003166 APInt Simm = APInt(64, Imm << ShiftAmt);
3167 // check if the immediate is an unsigned or signed 32-bit int for W regs
3168 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3169 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003170 }
3171 // 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 +00003172 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003173 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003174 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3175 return false;
3176 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003177 }
3178}
3179
3180/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3181/// operands.
3182bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3183 StringRef Name, SMLoc NameLoc,
3184 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003185 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003186 Name = StringSwitch<StringRef>(Name.lower())
3187 .Case("beq", "b.eq")
3188 .Case("bne", "b.ne")
3189 .Case("bhs", "b.hs")
3190 .Case("bcs", "b.cs")
3191 .Case("blo", "b.lo")
3192 .Case("bcc", "b.cc")
3193 .Case("bmi", "b.mi")
3194 .Case("bpl", "b.pl")
3195 .Case("bvs", "b.vs")
3196 .Case("bvc", "b.vc")
3197 .Case("bhi", "b.hi")
3198 .Case("bls", "b.ls")
3199 .Case("bge", "b.ge")
3200 .Case("blt", "b.lt")
3201 .Case("bgt", "b.gt")
3202 .Case("ble", "b.le")
3203 .Case("bal", "b.al")
3204 .Case("bnv", "b.nv")
3205 .Default(Name);
3206
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003207 // First check for the AArch64-specific .req directive.
3208 if (Parser.getTok().is(AsmToken::Identifier) &&
3209 Parser.getTok().getIdentifier() == ".req") {
3210 parseDirectiveReq(Name, NameLoc);
3211 // We always return 'error' for this, as we're done with this
3212 // statement and don't need to match the 'instruction."
3213 return true;
3214 }
3215
Tim Northover3b0846e2014-05-24 12:50:23 +00003216 // Create the leading tokens for the mnemonic, split by '.' characters.
3217 size_t Start = 0, Next = Name.find('.');
3218 StringRef Head = Name.slice(Start, Next);
3219
3220 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003221 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3222 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003223
3224 Operands.push_back(
3225 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3226 Mnemonic = Head;
3227
3228 // Handle condition codes for a branch mnemonic
3229 if (Head == "b" && Next != StringRef::npos) {
3230 Start = Next;
3231 Next = Name.find('.', Start + 1);
3232 Head = Name.slice(Start + 1, Next);
3233
3234 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3235 (Head.data() - Name.data()));
3236 AArch64CC::CondCode CC = parseCondCodeString(Head);
3237 if (CC == AArch64CC::Invalid)
3238 return Error(SuffixLoc, "invalid condition code");
3239 Operands.push_back(
3240 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3241 Operands.push_back(
3242 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3243 }
3244
3245 // Add the remaining tokens in the mnemonic.
3246 while (Next != StringRef::npos) {
3247 Start = Next;
3248 Next = Name.find('.', Start + 1);
3249 Head = Name.slice(Start, Next);
3250 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3251 (Head.data() - Name.data()) + 1);
3252 Operands.push_back(
3253 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3254 }
3255
3256 // Conditional compare instructions have a Condition Code operand, which needs
3257 // to be parsed and an immediate operand created.
3258 bool condCodeFourthOperand =
3259 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3260 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3261 Head == "csinc" || Head == "csinv" || Head == "csneg");
3262
3263 // These instructions are aliases to some of the conditional select
3264 // instructions. However, the condition code is inverted in the aliased
3265 // instruction.
3266 //
3267 // FIXME: Is this the correct way to handle these? Or should the parser
3268 // generate the aliased instructions directly?
3269 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3270 bool condCodeThirdOperand =
3271 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3272
3273 // Read the remaining operands.
3274 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3275 // Read the first operand.
3276 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003277 return true;
3278 }
3279
3280 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003281 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003282 // Parse and remember the operand.
3283 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3284 (N == 3 && condCodeThirdOperand) ||
3285 (N == 2 && condCodeSecondOperand),
3286 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003287 return true;
3288 }
3289
3290 // After successfully parsing some operands there are two special cases to
3291 // consider (i.e. notional operands not separated by commas). Both are due
3292 // to memory specifiers:
3293 // + An RBrac will end an address for load/store/prefetch
3294 // + An '!' will indicate a pre-indexed operation.
3295 //
3296 // It's someone else's responsibility to make sure these tokens are sane
3297 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003298
Nirav Davee833c6c2016-11-08 18:31:04 +00003299 SMLoc RLoc = Parser.getTok().getLoc();
3300 if (parseOptionalToken(AsmToken::RBrac))
3301 Operands.push_back(
3302 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3303 SMLoc ELoc = Parser.getTok().getLoc();
3304 if (parseOptionalToken(AsmToken::Exclaim))
3305 Operands.push_back(
3306 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003307
3308 ++N;
3309 }
3310 }
3311
Nirav Davee833c6c2016-11-08 18:31:04 +00003312 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3313 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003314
Tim Northover3b0846e2014-05-24 12:50:23 +00003315 return false;
3316}
3317
3318// FIXME: This entire function is a giant hack to provide us with decent
3319// operand range validation/diagnostics until TableGen/MC can be extended
3320// to support autogeneration of this kind of validation.
3321bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3322 SmallVectorImpl<SMLoc> &Loc) {
3323 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3324 // Check for indexed addressing modes w/ the base register being the
3325 // same as a destination/source register or pair load where
3326 // the Rt == Rt2. All of those are undefined behaviour.
3327 switch (Inst.getOpcode()) {
3328 case AArch64::LDPSWpre:
3329 case AArch64::LDPWpost:
3330 case AArch64::LDPWpre:
3331 case AArch64::LDPXpost:
3332 case AArch64::LDPXpre: {
3333 unsigned Rt = Inst.getOperand(1).getReg();
3334 unsigned Rt2 = Inst.getOperand(2).getReg();
3335 unsigned Rn = Inst.getOperand(3).getReg();
3336 if (RI->isSubRegisterEq(Rn, Rt))
3337 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3338 "is also a destination");
3339 if (RI->isSubRegisterEq(Rn, Rt2))
3340 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3341 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003342 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003343 }
3344 case AArch64::LDPDi:
3345 case AArch64::LDPQi:
3346 case AArch64::LDPSi:
3347 case AArch64::LDPSWi:
3348 case AArch64::LDPWi:
3349 case AArch64::LDPXi: {
3350 unsigned Rt = Inst.getOperand(0).getReg();
3351 unsigned Rt2 = Inst.getOperand(1).getReg();
3352 if (Rt == Rt2)
3353 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3354 break;
3355 }
3356 case AArch64::LDPDpost:
3357 case AArch64::LDPDpre:
3358 case AArch64::LDPQpost:
3359 case AArch64::LDPQpre:
3360 case AArch64::LDPSpost:
3361 case AArch64::LDPSpre:
3362 case AArch64::LDPSWpost: {
3363 unsigned Rt = Inst.getOperand(1).getReg();
3364 unsigned Rt2 = Inst.getOperand(2).getReg();
3365 if (Rt == Rt2)
3366 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3367 break;
3368 }
3369 case AArch64::STPDpost:
3370 case AArch64::STPDpre:
3371 case AArch64::STPQpost:
3372 case AArch64::STPQpre:
3373 case AArch64::STPSpost:
3374 case AArch64::STPSpre:
3375 case AArch64::STPWpost:
3376 case AArch64::STPWpre:
3377 case AArch64::STPXpost:
3378 case AArch64::STPXpre: {
3379 unsigned Rt = Inst.getOperand(1).getReg();
3380 unsigned Rt2 = Inst.getOperand(2).getReg();
3381 unsigned Rn = Inst.getOperand(3).getReg();
3382 if (RI->isSubRegisterEq(Rn, Rt))
3383 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3384 "is also a source");
3385 if (RI->isSubRegisterEq(Rn, Rt2))
3386 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3387 "is also a source");
3388 break;
3389 }
3390 case AArch64::LDRBBpre:
3391 case AArch64::LDRBpre:
3392 case AArch64::LDRHHpre:
3393 case AArch64::LDRHpre:
3394 case AArch64::LDRSBWpre:
3395 case AArch64::LDRSBXpre:
3396 case AArch64::LDRSHWpre:
3397 case AArch64::LDRSHXpre:
3398 case AArch64::LDRSWpre:
3399 case AArch64::LDRWpre:
3400 case AArch64::LDRXpre:
3401 case AArch64::LDRBBpost:
3402 case AArch64::LDRBpost:
3403 case AArch64::LDRHHpost:
3404 case AArch64::LDRHpost:
3405 case AArch64::LDRSBWpost:
3406 case AArch64::LDRSBXpost:
3407 case AArch64::LDRSHWpost:
3408 case AArch64::LDRSHXpost:
3409 case AArch64::LDRSWpost:
3410 case AArch64::LDRWpost:
3411 case AArch64::LDRXpost: {
3412 unsigned Rt = Inst.getOperand(1).getReg();
3413 unsigned Rn = Inst.getOperand(2).getReg();
3414 if (RI->isSubRegisterEq(Rn, Rt))
3415 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3416 "is also a source");
3417 break;
3418 }
3419 case AArch64::STRBBpost:
3420 case AArch64::STRBpost:
3421 case AArch64::STRHHpost:
3422 case AArch64::STRHpost:
3423 case AArch64::STRWpost:
3424 case AArch64::STRXpost:
3425 case AArch64::STRBBpre:
3426 case AArch64::STRBpre:
3427 case AArch64::STRHHpre:
3428 case AArch64::STRHpre:
3429 case AArch64::STRWpre:
3430 case AArch64::STRXpre: {
3431 unsigned Rt = Inst.getOperand(1).getReg();
3432 unsigned Rn = Inst.getOperand(2).getReg();
3433 if (RI->isSubRegisterEq(Rn, Rt))
3434 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3435 "is also a source");
3436 break;
3437 }
3438 }
3439
3440 // Now check immediate ranges. Separate from the above as there is overlap
3441 // in the instructions being checked and this keeps the nested conditionals
3442 // to a minimum.
3443 switch (Inst.getOpcode()) {
3444 case AArch64::ADDSWri:
3445 case AArch64::ADDSXri:
3446 case AArch64::ADDWri:
3447 case AArch64::ADDXri:
3448 case AArch64::SUBSWri:
3449 case AArch64::SUBSXri:
3450 case AArch64::SUBWri:
3451 case AArch64::SUBXri: {
3452 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3453 // some slight duplication here.
3454 if (Inst.getOperand(2).isExpr()) {
3455 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3456 AArch64MCExpr::VariantKind ELFRefKind;
3457 MCSymbolRefExpr::VariantKind DarwinRefKind;
3458 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003459 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3460
3461 // Only allow these with ADDXri.
3462 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3463 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3464 Inst.getOpcode() == AArch64::ADDXri)
3465 return false;
3466
3467 // Only allow these with ADDXri/ADDWri
3468 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3469 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3470 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3471 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3472 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3473 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3474 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003475 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3476 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3477 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003478 (Inst.getOpcode() == AArch64::ADDXri ||
3479 Inst.getOpcode() == AArch64::ADDWri))
3480 return false;
3481
3482 // Don't allow symbol refs in the immediate field otherwise
3483 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3484 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3485 // 'cmp w0, 'borked')
3486 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003487 }
Diana Picusc93518d2016-10-11 09:17:47 +00003488 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003489 }
3490 return false;
3491 }
3492 default:
3493 return false;
3494 }
3495}
3496
Craig Topper05515562017-10-26 06:46:41 +00003497static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3498 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003499
3500bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3501 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003502 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003503 case Match_InvalidTiedOperand:
3504 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003505 case Match_MissingFeature:
3506 return Error(Loc,
3507 "instruction requires a CPU feature not currently enabled");
3508 case Match_InvalidOperand:
3509 return Error(Loc, "invalid operand for instruction");
3510 case Match_InvalidSuffix:
3511 return Error(Loc, "invalid type suffix for instruction");
3512 case Match_InvalidCondCode:
3513 return Error(Loc, "expected AArch64 condition code");
3514 case Match_AddSubRegExtendSmall:
3515 return Error(Loc,
3516 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3517 case Match_AddSubRegExtendLarge:
3518 return Error(Loc,
3519 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3520 case Match_AddSubSecondSource:
3521 return Error(Loc,
3522 "expected compatible register, symbol or integer in range [0, 4095]");
3523 case Match_LogicalSecondSource:
3524 return Error(Loc, "expected compatible register or logical immediate");
3525 case Match_InvalidMovImm32Shift:
3526 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3527 case Match_InvalidMovImm64Shift:
3528 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3529 case Match_AddSubRegShift32:
3530 return Error(Loc,
3531 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3532 case Match_AddSubRegShift64:
3533 return Error(Loc,
3534 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3535 case Match_InvalidFPImm:
3536 return Error(Loc,
3537 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003538 case Match_InvalidMemoryIndexedSImm6:
3539 return Error(Loc, "index must be an integer in range [-32, 31].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003540 case Match_InvalidMemoryIndexedSImm9:
3541 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003542 case Match_InvalidMemoryIndexedSImm10:
3543 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003544 case Match_InvalidMemoryIndexed4SImm7:
3545 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3546 case Match_InvalidMemoryIndexed8SImm7:
3547 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3548 case Match_InvalidMemoryIndexed16SImm7:
3549 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3550 case Match_InvalidMemoryWExtend8:
3551 return Error(Loc,
3552 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3553 case Match_InvalidMemoryWExtend16:
3554 return Error(Loc,
3555 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3556 case Match_InvalidMemoryWExtend32:
3557 return Error(Loc,
3558 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3559 case Match_InvalidMemoryWExtend64:
3560 return Error(Loc,
3561 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3562 case Match_InvalidMemoryWExtend128:
3563 return Error(Loc,
3564 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3565 case Match_InvalidMemoryXExtend8:
3566 return Error(Loc,
3567 "expected 'lsl' or 'sxtx' with optional shift of #0");
3568 case Match_InvalidMemoryXExtend16:
3569 return Error(Loc,
3570 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3571 case Match_InvalidMemoryXExtend32:
3572 return Error(Loc,
3573 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3574 case Match_InvalidMemoryXExtend64:
3575 return Error(Loc,
3576 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3577 case Match_InvalidMemoryXExtend128:
3578 return Error(Loc,
3579 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3580 case Match_InvalidMemoryIndexed1:
3581 return Error(Loc, "index must be an integer in range [0, 4095].");
3582 case Match_InvalidMemoryIndexed2:
3583 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3584 case Match_InvalidMemoryIndexed4:
3585 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3586 case Match_InvalidMemoryIndexed8:
3587 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3588 case Match_InvalidMemoryIndexed16:
3589 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003590 case Match_InvalidImm0_1:
3591 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003592 case Match_InvalidImm0_7:
3593 return Error(Loc, "immediate must be an integer in range [0, 7].");
3594 case Match_InvalidImm0_15:
3595 return Error(Loc, "immediate must be an integer in range [0, 15].");
3596 case Match_InvalidImm0_31:
3597 return Error(Loc, "immediate must be an integer in range [0, 31].");
3598 case Match_InvalidImm0_63:
3599 return Error(Loc, "immediate must be an integer in range [0, 63].");
3600 case Match_InvalidImm0_127:
3601 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003602 case Match_InvalidImm0_255:
3603 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003604 case Match_InvalidImm0_65535:
3605 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3606 case Match_InvalidImm1_8:
3607 return Error(Loc, "immediate must be an integer in range [1, 8].");
3608 case Match_InvalidImm1_16:
3609 return Error(Loc, "immediate must be an integer in range [1, 16].");
3610 case Match_InvalidImm1_32:
3611 return Error(Loc, "immediate must be an integer in range [1, 32].");
3612 case Match_InvalidImm1_64:
3613 return Error(Loc, "immediate must be an integer in range [1, 64].");
3614 case Match_InvalidIndex1:
3615 return Error(Loc, "expected lane specifier '[1]'");
3616 case Match_InvalidIndexB:
3617 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3618 case Match_InvalidIndexH:
3619 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3620 case Match_InvalidIndexS:
3621 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3622 case Match_InvalidIndexD:
3623 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3624 case Match_InvalidLabel:
3625 return Error(Loc, "expected label or encodable integer pc offset");
3626 case Match_MRS:
3627 return Error(Loc, "expected readable system register");
3628 case Match_MSR:
3629 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003630 case Match_InvalidComplexRotationEven:
3631 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3632 case Match_InvalidComplexRotationOdd:
3633 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003634 case Match_MnemonicFail: {
3635 std::string Suggestion = AArch64MnemonicSpellCheck(
3636 ((AArch64Operand &)*Operands[0]).getToken(),
3637 ComputeAvailableFeatures(STI->getFeatureBits()));
3638 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3639 }
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003640 case Match_InvalidSVEPattern:
3641 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003642 case Match_InvalidSVEPredicateAnyReg:
3643 case Match_InvalidSVEPredicateBReg:
3644 case Match_InvalidSVEPredicateHReg:
3645 case Match_InvalidSVEPredicateSReg:
3646 case Match_InvalidSVEPredicateDReg:
3647 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003648 case Match_InvalidSVEPredicate3bAnyReg:
3649 case Match_InvalidSVEPredicate3bBReg:
3650 case Match_InvalidSVEPredicate3bHReg:
3651 case Match_InvalidSVEPredicate3bSReg:
3652 case Match_InvalidSVEPredicate3bDReg:
3653 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003654 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003655 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003656 }
3657}
3658
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003659static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003660
3661bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3662 OperandVector &Operands,
3663 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003664 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003665 bool MatchingInlineAsm) {
3666 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003667 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3668 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003669
David Blaikie960ea3f2014-06-08 16:18:35 +00003670 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003671 unsigned NumOperands = Operands.size();
3672
3673 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003674 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3675 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003676 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003677 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003678 if (Op3CE) {
3679 uint64_t Op3Val = Op3CE->getValue();
3680 uint64_t NewOp3Val = 0;
3681 uint64_t NewOp4Val = 0;
3682 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003683 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003684 NewOp3Val = (32 - Op3Val) & 0x1f;
3685 NewOp4Val = 31 - Op3Val;
3686 } else {
3687 NewOp3Val = (64 - Op3Val) & 0x3f;
3688 NewOp4Val = 63 - Op3Val;
3689 }
3690
Jim Grosbach13760bd2015-05-30 01:25:56 +00003691 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3692 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003693
3694 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003695 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003696 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003697 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3698 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3699 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003700 }
3701 }
Tim Northover03b99f62015-04-30 18:28:58 +00003702 } else if (NumOperands == 4 && Tok == "bfc") {
3703 // FIXME: Horrible hack to handle BFC->BFM alias.
3704 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3705 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3706 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3707
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003708 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003709 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3710 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3711
3712 if (LSBCE && WidthCE) {
3713 uint64_t LSB = LSBCE->getValue();
3714 uint64_t Width = WidthCE->getValue();
3715
3716 uint64_t RegWidth = 0;
3717 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3718 Op1.getReg()))
3719 RegWidth = 64;
3720 else
3721 RegWidth = 32;
3722
3723 if (LSB >= RegWidth)
3724 return Error(LSBOp.getStartLoc(),
3725 "expected integer in range [0, 31]");
3726 if (Width < 1 || Width > RegWidth)
3727 return Error(WidthOp.getStartLoc(),
3728 "expected integer in range [1, 32]");
3729
3730 uint64_t ImmR = 0;
3731 if (RegWidth == 32)
3732 ImmR = (32 - LSB) & 0x1f;
3733 else
3734 ImmR = (64 - LSB) & 0x3f;
3735
3736 uint64_t ImmS = Width - 1;
3737
3738 if (ImmR != 0 && ImmS >= ImmR)
3739 return Error(WidthOp.getStartLoc(),
3740 "requested insert overflows register");
3741
Jim Grosbach13760bd2015-05-30 01:25:56 +00003742 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3743 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003744 Operands[0] = AArch64Operand::CreateToken(
3745 "bfm", false, Op.getStartLoc(), getContext());
3746 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003747 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3748 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003749 Operands[3] = AArch64Operand::CreateImm(
3750 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3751 Operands.emplace_back(
3752 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3753 WidthOp.getEndLoc(), getContext()));
3754 }
3755 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003756 } else if (NumOperands == 5) {
3757 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3758 // UBFIZ -> UBFM aliases.
3759 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003760 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3761 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3762 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003763
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003764 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003765 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3766 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003767
3768 if (Op3CE && Op4CE) {
3769 uint64_t Op3Val = Op3CE->getValue();
3770 uint64_t Op4Val = Op4CE->getValue();
3771
3772 uint64_t RegWidth = 0;
3773 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003774 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003775 RegWidth = 64;
3776 else
3777 RegWidth = 32;
3778
3779 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003780 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003781 "expected integer in range [0, 31]");
3782 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003783 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003784 "expected integer in range [1, 32]");
3785
3786 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003787 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003788 NewOp3Val = (32 - Op3Val) & 0x1f;
3789 else
3790 NewOp3Val = (64 - Op3Val) & 0x3f;
3791
3792 uint64_t NewOp4Val = Op4Val - 1;
3793
3794 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003795 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003796 "requested insert overflows register");
3797
3798 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003799 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003800 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003801 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003802 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003803 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003804 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003805 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003806 if (Tok == "bfi")
3807 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003808 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003809 else if (Tok == "sbfiz")
3810 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003811 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003812 else if (Tok == "ubfiz")
3813 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003814 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003815 else
3816 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003817 }
3818 }
3819
3820 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3821 // UBFX -> UBFM aliases.
3822 } else if (NumOperands == 5 &&
3823 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003824 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3825 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3826 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003827
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003828 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003829 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3830 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003831
3832 if (Op3CE && Op4CE) {
3833 uint64_t Op3Val = Op3CE->getValue();
3834 uint64_t Op4Val = Op4CE->getValue();
3835
3836 uint64_t RegWidth = 0;
3837 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003838 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003839 RegWidth = 64;
3840 else
3841 RegWidth = 32;
3842
3843 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003844 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003845 "expected integer in range [0, 31]");
3846 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003847 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003848 "expected integer in range [1, 32]");
3849
3850 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3851
3852 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003853 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003854 "requested extract overflows register");
3855
3856 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003857 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003858 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003859 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003860 if (Tok == "bfxil")
3861 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003862 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003863 else if (Tok == "sbfx")
3864 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003865 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003866 else if (Tok == "ubfx")
3867 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003868 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003869 else
3870 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003871 }
3872 }
3873 }
3874 }
Tim Northover9097a072017-12-18 10:36:00 +00003875
3876 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
3877 // instruction for FP registers correctly in some rare circumstances. Convert
3878 // it to a safe instruction and warn (because silently changing someone's
3879 // assembly is rude).
3880 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
3881 NumOperands == 4 && Tok == "movi") {
3882 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3883 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3884 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3885 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
3886 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
3887 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
3888 if (Suffix.lower() == ".2d" &&
3889 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
3890 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
3891 " correctly on this CPU, converting to equivalent movi.16b");
3892 // Switch the suffix to .16b.
3893 unsigned Idx = Op1.isToken() ? 1 : 2;
3894 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
3895 getContext());
3896 }
3897 }
3898 }
3899
Tim Northover3b0846e2014-05-24 12:50:23 +00003900 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3901 // InstAlias can't quite handle this since the reg classes aren't
3902 // subclasses.
3903 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3904 // The source register can be Wn here, but the matcher expects a
3905 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003906 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003907 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003908 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003909 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3910 Op.getStartLoc(), Op.getEndLoc(),
3911 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003912 }
3913 }
3914 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3915 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003916 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003917 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003918 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003919 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003920 // The source register can be Wn here, but the matcher expects a
3921 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003922 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003923 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003924 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003925 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3926 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003927 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003928 }
3929 }
3930 }
3931 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3932 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003933 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003934 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003935 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003936 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003937 // The source register can be Wn here, but the matcher expects a
3938 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003939 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003940 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003941 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003942 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3943 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003944 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003945 }
3946 }
3947 }
3948
Tim Northover3b0846e2014-05-24 12:50:23 +00003949 MCInst Inst;
3950 // First try to match against the secondary set of tables containing the
3951 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3952 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003953 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003954
3955 // If that fails, try against the alternate table containing long-form NEON:
3956 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003957 if (MatchResult != Match_Success) {
3958 // But first, save the short-form match result: we can use it in case the
3959 // long-form match also fails.
3960 auto ShortFormNEONErrorInfo = ErrorInfo;
3961 auto ShortFormNEONMatchResult = MatchResult;
3962
Tim Northover3b0846e2014-05-24 12:50:23 +00003963 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003964 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003965
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003966 // Now, both matches failed, and the long-form match failed on the mnemonic
3967 // suffix token operand. The short-form match failure is probably more
3968 // relevant: use it instead.
3969 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003970 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003971 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3972 MatchResult = ShortFormNEONMatchResult;
3973 ErrorInfo = ShortFormNEONErrorInfo;
3974 }
3975 }
3976
Tim Northover3b0846e2014-05-24 12:50:23 +00003977 switch (MatchResult) {
3978 case Match_Success: {
3979 // Perform range checking and other semantic validations
3980 SmallVector<SMLoc, 8> OperandLocs;
3981 NumOperands = Operands.size();
3982 for (unsigned i = 1; i < NumOperands; ++i)
3983 OperandLocs.push_back(Operands[i]->getStartLoc());
3984 if (validateInstruction(Inst, OperandLocs))
3985 return true;
3986
3987 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003988 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00003989 return false;
3990 }
3991 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003992 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003993 // Special case the error message for the very common case where only
3994 // a single subtarget feature is missing (neon, e.g.).
3995 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003996 uint64_t Mask = 1;
3997 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
3998 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003999 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004000 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004001 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004002 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004003 }
4004 return Error(IDLoc, Msg);
4005 }
4006 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004007 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004008 case Match_InvalidOperand: {
4009 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004010
Tim Northover26bb14e2014-08-18 11:49:42 +00004011 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004012 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004013 return Error(IDLoc, "too few operands for instruction",
4014 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004015
David Blaikie960ea3f2014-06-08 16:18:35 +00004016 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004017 if (ErrorLoc == SMLoc())
4018 ErrorLoc = IDLoc;
4019 }
4020 // If the match failed on a suffix token operand, tweak the diagnostic
4021 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004022 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4023 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004024 MatchResult = Match_InvalidSuffix;
4025
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004026 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004027 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004028 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004029 case Match_InvalidMemoryIndexed1:
4030 case Match_InvalidMemoryIndexed2:
4031 case Match_InvalidMemoryIndexed4:
4032 case Match_InvalidMemoryIndexed8:
4033 case Match_InvalidMemoryIndexed16:
4034 case Match_InvalidCondCode:
4035 case Match_AddSubRegExtendSmall:
4036 case Match_AddSubRegExtendLarge:
4037 case Match_AddSubSecondSource:
4038 case Match_LogicalSecondSource:
4039 case Match_AddSubRegShift32:
4040 case Match_AddSubRegShift64:
4041 case Match_InvalidMovImm32Shift:
4042 case Match_InvalidMovImm64Shift:
4043 case Match_InvalidFPImm:
4044 case Match_InvalidMemoryWExtend8:
4045 case Match_InvalidMemoryWExtend16:
4046 case Match_InvalidMemoryWExtend32:
4047 case Match_InvalidMemoryWExtend64:
4048 case Match_InvalidMemoryWExtend128:
4049 case Match_InvalidMemoryXExtend8:
4050 case Match_InvalidMemoryXExtend16:
4051 case Match_InvalidMemoryXExtend32:
4052 case Match_InvalidMemoryXExtend64:
4053 case Match_InvalidMemoryXExtend128:
Sander de Smalen909cf952018-01-19 15:22:00 +00004054 case Match_InvalidMemoryIndexedSImm6:
Tim Northover3b0846e2014-05-24 12:50:23 +00004055 case Match_InvalidMemoryIndexed4SImm7:
4056 case Match_InvalidMemoryIndexed8SImm7:
4057 case Match_InvalidMemoryIndexed16SImm7:
4058 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004059 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004060 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004061 case Match_InvalidImm0_7:
4062 case Match_InvalidImm0_15:
4063 case Match_InvalidImm0_31:
4064 case Match_InvalidImm0_63:
4065 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004066 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004067 case Match_InvalidImm0_65535:
4068 case Match_InvalidImm1_8:
4069 case Match_InvalidImm1_16:
4070 case Match_InvalidImm1_32:
4071 case Match_InvalidImm1_64:
4072 case Match_InvalidIndex1:
4073 case Match_InvalidIndexB:
4074 case Match_InvalidIndexH:
4075 case Match_InvalidIndexS:
4076 case Match_InvalidIndexD:
4077 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004078 case Match_InvalidComplexRotationEven:
4079 case Match_InvalidComplexRotationOdd:
Sander de Smalencd6be962017-12-20 11:02:42 +00004080 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004081 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004082 case Match_InvalidSVEPredicateBReg:
4083 case Match_InvalidSVEPredicateHReg:
4084 case Match_InvalidSVEPredicateSReg:
4085 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004086 case Match_InvalidSVEPredicate3bAnyReg:
4087 case Match_InvalidSVEPredicate3bBReg:
4088 case Match_InvalidSVEPredicate3bHReg:
4089 case Match_InvalidSVEPredicate3bSReg:
4090 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004091 case Match_MSR:
4092 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004093 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004094 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004095 // Any time we get here, there's nothing fancy to do. Just get the
4096 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004097 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004098 if (ErrorLoc == SMLoc())
4099 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004100 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004101 }
4102 }
4103
4104 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004105}
4106
4107/// ParseDirective parses the arm specific directives
4108bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004109 const MCObjectFileInfo::Environment Format =
4110 getContext().getObjectFileInfo()->getObjectFileType();
4111 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4112 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004113
Tim Northover3b0846e2014-05-24 12:50:23 +00004114 StringRef IDVal = DirectiveID.getIdentifier();
4115 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004116 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004117 parseDirectiveArch(Loc);
4118 else if (IDVal == ".cpu")
4119 parseDirectiveCPU(Loc);
4120 else if (IDVal == ".hword")
4121 parseDirectiveWord(2, Loc);
4122 else if (IDVal == ".word")
4123 parseDirectiveWord(4, Loc);
4124 else if (IDVal == ".xword")
4125 parseDirectiveWord(8, Loc);
4126 else if (IDVal == ".tlsdesccall")
4127 parseDirectiveTLSDescCall(Loc);
4128 else if (IDVal == ".ltorg" || IDVal == ".pool")
4129 parseDirectiveLtorg(Loc);
4130 else if (IDVal == ".unreq")
4131 parseDirectiveUnreq(Loc);
4132 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004133 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004134 parseDirectiveInst(Loc);
4135 else
4136 return true;
4137 } else if (IDVal == MCLOHDirectiveName())
4138 parseDirectiveLOH(IDVal, Loc);
4139 else
4140 return true;
4141 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004142}
4143
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004144static const struct {
4145 const char *Name;
4146 const FeatureBitset Features;
4147} ExtensionMap[] = {
4148 { "crc", {AArch64::FeatureCRC} },
4149 { "crypto", {AArch64::FeatureCrypto} },
4150 { "fp", {AArch64::FeatureFPARMv8} },
4151 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004152 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004153 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004154
4155 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004156 { "pan", {} },
4157 { "lor", {} },
4158 { "rdma", {} },
4159 { "profile", {} },
4160};
4161
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004162/// parseDirectiveArch
4163/// ::= .arch token
4164bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4165 SMLoc ArchLoc = getLoc();
4166
4167 StringRef Arch, ExtensionString;
4168 std::tie(Arch, ExtensionString) =
4169 getParser().parseStringToEndOfStatement().trim().split('+');
4170
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004171 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4172 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004173 return Error(ArchLoc, "unknown arch name");
4174
4175 if (parseToken(AsmToken::EndOfStatement))
4176 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004177
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004178 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004179 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004180 AArch64::getArchFeatures(ID, AArch64Features);
4181 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4182 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004183
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004184 MCSubtargetInfo &STI = copySTI();
4185 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4186 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4187
4188 SmallVector<StringRef, 4> RequestedExtensions;
4189 if (!ExtensionString.empty())
4190 ExtensionString.split(RequestedExtensions, '+');
4191
4192 FeatureBitset Features = STI.getFeatureBits();
4193 for (auto Name : RequestedExtensions) {
4194 bool EnableFeature = true;
4195
4196 if (Name.startswith_lower("no")) {
4197 EnableFeature = false;
4198 Name = Name.substr(2);
4199 }
4200
4201 for (const auto &Extension : ExtensionMap) {
4202 if (Extension.Name != Name)
4203 continue;
4204
4205 if (Extension.Features.none())
4206 report_fatal_error("unsupported architectural extension: " + Name);
4207
4208 FeatureBitset ToggleFeatures = EnableFeature
4209 ? (~Features & Extension.Features)
4210 : ( Features & Extension.Features);
4211 uint64_t Features =
4212 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4213 setAvailableFeatures(Features);
4214 break;
4215 }
4216 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004217 return false;
4218}
4219
Tim Northover8b96c7e2017-05-15 19:42:15 +00004220static SMLoc incrementLoc(SMLoc L, int Offset) {
4221 return SMLoc::getFromPointer(L.getPointer() + Offset);
4222}
4223
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004224/// parseDirectiveCPU
4225/// ::= .cpu id
4226bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004227 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004228
4229 StringRef CPU, ExtensionString;
4230 std::tie(CPU, ExtensionString) =
4231 getParser().parseStringToEndOfStatement().trim().split('+');
4232
Nirav Davee833c6c2016-11-08 18:31:04 +00004233 if (parseToken(AsmToken::EndOfStatement))
4234 return true;
4235
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004236 SmallVector<StringRef, 4> RequestedExtensions;
4237 if (!ExtensionString.empty())
4238 ExtensionString.split(RequestedExtensions, '+');
4239
4240 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4241 // once that is tablegen'ed
4242 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004243 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004244 return false;
4245 }
4246
4247 MCSubtargetInfo &STI = copySTI();
4248 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004249 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004250
4251 FeatureBitset Features = STI.getFeatureBits();
4252 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004253 // Advance source location past '+'.
4254 CurLoc = incrementLoc(CurLoc, 1);
4255
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004256 bool EnableFeature = true;
4257
4258 if (Name.startswith_lower("no")) {
4259 EnableFeature = false;
4260 Name = Name.substr(2);
4261 }
4262
Tim Northover8b96c7e2017-05-15 19:42:15 +00004263 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004264 for (const auto &Extension : ExtensionMap) {
4265 if (Extension.Name != Name)
4266 continue;
4267
4268 if (Extension.Features.none())
4269 report_fatal_error("unsupported architectural extension: " + Name);
4270
4271 FeatureBitset ToggleFeatures = EnableFeature
4272 ? (~Features & Extension.Features)
4273 : ( Features & Extension.Features);
4274 uint64_t Features =
4275 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4276 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004277 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004278
4279 break;
4280 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004281
4282 if (!FoundExtension)
4283 Error(CurLoc, "unsupported architectural extension");
4284
4285 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004286 }
4287 return false;
4288}
4289
Tim Northover3b0846e2014-05-24 12:50:23 +00004290/// parseDirectiveWord
4291/// ::= .word [ expression (, expression)* ]
4292bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004293 auto parseOp = [&]() -> bool {
4294 const MCExpr *Value;
4295 if (getParser().parseExpression(Value))
4296 return true;
4297 getParser().getStreamer().EmitValue(Value, Size, L);
4298 return false;
4299 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004300
Nirav Davee833c6c2016-11-08 18:31:04 +00004301 if (parseMany(parseOp))
4302 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004303 return false;
4304}
4305
Chad Rosierdcd2a302014-10-22 20:35:57 +00004306/// parseDirectiveInst
4307/// ::= .inst opcode [, ...]
4308bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004309 if (getLexer().is(AsmToken::EndOfStatement))
4310 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004311
Nirav Davee833c6c2016-11-08 18:31:04 +00004312 auto parseOp = [&]() -> bool {
4313 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004314 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004315 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4316 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004317 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004318 if (check(!Value, L, "expected constant expression"))
4319 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004320 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004321 return false;
4322 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004323
Nirav Davee833c6c2016-11-08 18:31:04 +00004324 if (parseMany(parseOp))
4325 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004326 return false;
4327}
4328
Tim Northover3b0846e2014-05-24 12:50:23 +00004329// parseDirectiveTLSDescCall:
4330// ::= .tlsdesccall symbol
4331bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4332 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004333 if (check(getParser().parseIdentifier(Name), L,
4334 "expected symbol after directive") ||
4335 parseToken(AsmToken::EndOfStatement))
4336 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004337
Jim Grosbach6f482002015-05-18 18:43:14 +00004338 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004339 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4340 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004341
4342 MCInst Inst;
4343 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004344 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004345
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004346 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004347 return false;
4348}
4349
4350/// ::= .loh <lohName | lohId> label1, ..., labelN
4351/// The number of arguments depends on the loh identifier.
4352bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004353 MCLOHType Kind;
4354 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4355 if (getParser().getTok().isNot(AsmToken::Integer))
4356 return TokError("expected an identifier or a number in directive");
4357 // We successfully get a numeric value for the identifier.
4358 // Check if it is valid.
4359 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004360 if (Id <= -1U && !isValidMCLOHType(Id))
4361 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004362 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004363 } else {
4364 StringRef Name = getTok().getIdentifier();
4365 // We successfully parse an identifier.
4366 // Check if it is a recognized one.
4367 int Id = MCLOHNameToId(Name);
4368
4369 if (Id == -1)
4370 return TokError("invalid identifier in directive");
4371 Kind = (MCLOHType)Id;
4372 }
4373 // Consume the identifier.
4374 Lex();
4375 // Get the number of arguments of this LOH.
4376 int NbArgs = MCLOHIdToNbArgs(Kind);
4377
4378 assert(NbArgs != -1 && "Invalid number of arguments");
4379
4380 SmallVector<MCSymbol *, 3> Args;
4381 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4382 StringRef Name;
4383 if (getParser().parseIdentifier(Name))
4384 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004385 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004386
4387 if (Idx + 1 == NbArgs)
4388 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004389 if (parseToken(AsmToken::Comma,
4390 "unexpected token in '" + Twine(IDVal) + "' directive"))
4391 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004392 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004393 if (parseToken(AsmToken::EndOfStatement,
4394 "unexpected token in '" + Twine(IDVal) + "' directive"))
4395 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004396
4397 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4398 return false;
4399}
4400
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004401/// parseDirectiveLtorg
4402/// ::= .ltorg | .pool
4403bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004404 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4405 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004406 getTargetStreamer().emitCurrentConstantPool();
4407 return false;
4408}
4409
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004410/// parseDirectiveReq
4411/// ::= name .req registername
4412bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004413 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004414 Parser.Lex(); // Eat the '.req' token.
4415 SMLoc SRegLoc = getLoc();
Sander de Smalen8e607342017-11-15 15:44:43 +00004416 int RegNum = tryParseRegister();
Florian Hahnc4422242017-11-07 13:07:50 +00004417 RegKind RegisterKind = RegKind::Scalar;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004418
Sander de Smalen8e607342017-11-15 15:44:43 +00004419 if (RegNum == -1) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004420 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004421 RegisterKind = RegKind::NeonVector;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004422 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004423 if (!Kind.empty())
4424 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004425 }
4426
Sander de Smalen8e607342017-11-15 15:44:43 +00004427 if (RegNum == -1) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004428 StringRef Kind;
4429 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen8e607342017-11-15 15:44:43 +00004430 OperandMatchResultTy Res =
4431 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4432
4433 if (Res == MatchOperand_ParseFail)
4434 return true;
4435
4436 if (Res == MatchOperand_Success && !Kind.empty())
4437 return Error(SRegLoc,
4438 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004439 }
4440
Sander de Smalencd6be962017-12-20 11:02:42 +00004441 if (RegNum == -1) {
4442 StringRef Kind;
4443 RegisterKind = RegKind::SVEPredicateVector;
4444 OperandMatchResultTy Res =
4445 tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
4446
4447 if (Res == MatchOperand_ParseFail)
4448 return true;
4449
4450 if (Res == MatchOperand_Success && !Kind.empty())
4451 return Error(SRegLoc,
4452 "sve predicate register without type specifier expected");
4453 }
4454
Sander de Smalen8e607342017-11-15 15:44:43 +00004455 if (RegNum == -1)
Nirav Dave2364748a2016-09-16 18:30:20 +00004456 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004457
4458 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004459 if (parseToken(AsmToken::EndOfStatement,
4460 "unexpected input in .req directive"))
4461 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004462
Sander de Smalen8e607342017-11-15 15:44:43 +00004463 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004464 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004465 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4466
Nirav Dave2364748a2016-09-16 18:30:20 +00004467 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004468}
4469
4470/// parseDirectiveUneq
4471/// ::= .unreq registername
4472bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004473 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004474 if (getTok().isNot(AsmToken::Identifier))
4475 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004476 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4477 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004478 if (parseToken(AsmToken::EndOfStatement))
4479 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004480 return false;
4481}
4482
Tim Northover3b0846e2014-05-24 12:50:23 +00004483bool
4484AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4485 AArch64MCExpr::VariantKind &ELFRefKind,
4486 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4487 int64_t &Addend) {
4488 ELFRefKind = AArch64MCExpr::VK_INVALID;
4489 DarwinRefKind = MCSymbolRefExpr::VK_None;
4490 Addend = 0;
4491
4492 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4493 ELFRefKind = AE->getKind();
4494 Expr = AE->getSubExpr();
4495 }
4496
4497 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4498 if (SE) {
4499 // It's a simple symbol reference with no addend.
4500 DarwinRefKind = SE->getKind();
4501 return true;
4502 }
4503
4504 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4505 if (!BE)
4506 return false;
4507
4508 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4509 if (!SE)
4510 return false;
4511 DarwinRefKind = SE->getKind();
4512
4513 if (BE->getOpcode() != MCBinaryExpr::Add &&
4514 BE->getOpcode() != MCBinaryExpr::Sub)
4515 return false;
4516
4517 // See if the addend is is a constant, otherwise there's more going
4518 // on here than we can deal with.
4519 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4520 if (!AddendExpr)
4521 return false;
4522
4523 Addend = AddendExpr->getValue();
4524 if (BE->getOpcode() == MCBinaryExpr::Sub)
4525 Addend = -Addend;
4526
4527 // It's some symbol reference + a constant addend, but really
4528 // shouldn't use both Darwin and ELF syntax.
4529 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4530 DarwinRefKind == MCSymbolRefExpr::VK_None;
4531}
4532
4533/// Force static initialization.
4534extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004535 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4536 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4537 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004538}
4539
4540#define GET_REGISTER_MATCHER
4541#define GET_SUBTARGET_FEATURE_NAME
4542#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004543#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004544#include "AArch64GenAsmMatcher.inc"
4545
4546// Define this matcher function after the auto-generated include so we
4547// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004548unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004549 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004550 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004551 // If the kind is a token for a literal immediate, check if our asm
4552 // operand matches. This is for InstAliases which have a fixed-value
4553 // immediate in the syntax.
4554 int64_t ExpectedVal;
4555 switch (Kind) {
4556 default:
4557 return Match_InvalidOperand;
4558 case MCK__35_0:
4559 ExpectedVal = 0;
4560 break;
4561 case MCK__35_1:
4562 ExpectedVal = 1;
4563 break;
4564 case MCK__35_12:
4565 ExpectedVal = 12;
4566 break;
4567 case MCK__35_16:
4568 ExpectedVal = 16;
4569 break;
4570 case MCK__35_2:
4571 ExpectedVal = 2;
4572 break;
4573 case MCK__35_24:
4574 ExpectedVal = 24;
4575 break;
4576 case MCK__35_3:
4577 ExpectedVal = 3;
4578 break;
4579 case MCK__35_32:
4580 ExpectedVal = 32;
4581 break;
4582 case MCK__35_4:
4583 ExpectedVal = 4;
4584 break;
4585 case MCK__35_48:
4586 ExpectedVal = 48;
4587 break;
4588 case MCK__35_6:
4589 ExpectedVal = 6;
4590 break;
4591 case MCK__35_64:
4592 ExpectedVal = 64;
4593 break;
4594 case MCK__35_8:
4595 ExpectedVal = 8;
4596 break;
4597 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004598 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004599 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004600 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004601 if (!CE)
4602 return Match_InvalidOperand;
4603 if (CE->getValue() == ExpectedVal)
4604 return Match_Success;
4605 return Match_InvalidOperand;
4606}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004607
Alex Bradbury58eba092016-11-01 16:32:05 +00004608OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004609AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4610
4611 SMLoc S = getLoc();
4612
4613 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4614 Error(S, "expected register");
4615 return MatchOperand_ParseFail;
4616 }
4617
4618 int FirstReg = tryParseRegister();
4619 if (FirstReg == -1) {
4620 return MatchOperand_ParseFail;
4621 }
4622 const MCRegisterClass &WRegClass =
4623 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4624 const MCRegisterClass &XRegClass =
4625 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4626
4627 bool isXReg = XRegClass.contains(FirstReg),
4628 isWReg = WRegClass.contains(FirstReg);
4629 if (!isXReg && !isWReg) {
4630 Error(S, "expected first even register of a "
4631 "consecutive same-size even/odd register pair");
4632 return MatchOperand_ParseFail;
4633 }
4634
4635 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4636 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4637
4638 if (FirstEncoding & 0x1) {
4639 Error(S, "expected first even register of a "
4640 "consecutive same-size even/odd register pair");
4641 return MatchOperand_ParseFail;
4642 }
4643
4644 SMLoc M = getLoc();
4645 if (getParser().getTok().isNot(AsmToken::Comma)) {
4646 Error(M, "expected comma");
4647 return MatchOperand_ParseFail;
4648 }
4649 // Eat the comma
4650 getParser().Lex();
4651
4652 SMLoc E = getLoc();
4653 int SecondReg = tryParseRegister();
4654 if (SecondReg ==-1) {
4655 return MatchOperand_ParseFail;
4656 }
4657
Eugene Zelenko049b0172017-01-06 00:30:53 +00004658 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004659 (isXReg && !XRegClass.contains(SecondReg)) ||
4660 (isWReg && !WRegClass.contains(SecondReg))) {
4661 Error(E,"expected second odd register of a "
4662 "consecutive same-size even/odd register pair");
4663 return MatchOperand_ParseFail;
4664 }
Joel Jones504bf332016-10-24 13:37:13 +00004665
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004666 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004667 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004668 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4669 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4670 } else {
4671 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4672 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4673 }
4674
Florian Hahnc4422242017-11-07 13:07:50 +00004675 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4676 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004677
4678 return MatchOperand_Success;
4679}
Florian Hahn91f11e52017-11-07 16:45:48 +00004680
4681template <bool ParseSuffix>
4682OperandMatchResultTy
4683AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004684 const SMLoc S = getLoc();
4685 // Check for a SVE vector register specifier first.
Sander de Smalen8e607342017-11-15 15:44:43 +00004686 int RegNum = -1;
Florian Hahn91f11e52017-11-07 16:45:48 +00004687 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004688
Sander de Smalen8e607342017-11-15 15:44:43 +00004689 OperandMatchResultTy Res =
4690 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4691
4692 if (Res != MatchOperand_Success)
4693 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004694
4695 if (ParseSuffix && Kind.empty())
4696 return MatchOperand_NoMatch;
4697
4698 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
4699 .Case("", -1)
4700 .Case(".b", 8)
4701 .Case(".h", 16)
4702 .Case(".s", 32)
4703 .Case(".d", 64)
4704 .Case(".q", 128)
4705 .Default(0);
4706 if (!ElementWidth)
4707 return MatchOperand_NoMatch;
4708
4709 Operands.push_back(
4710 AArch64Operand::CreateReg(RegNum, RegKind::SVEDataVector, ElementWidth,
4711 S, S, getContext()));
4712
4713 return MatchOperand_Success;
4714}
Sander de Smalen245e0e62018-01-22 10:46:00 +00004715
4716OperandMatchResultTy
4717AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
4718 MCAsmParser &Parser = getParser();
4719
4720 SMLoc SS = getLoc();
4721 const AsmToken &TokE = Parser.getTok();
4722 bool IsHash = TokE.is(AsmToken::Hash);
4723
4724 if (!IsHash && TokE.isNot(AsmToken::Identifier))
4725 return MatchOperand_NoMatch;
4726
4727 int64_t Pattern;
4728 if (IsHash) {
4729 Parser.Lex(); // Eat hash
4730
4731 // Parse the immediate operand.
4732 const MCExpr *ImmVal;
4733 SS = getLoc();
4734 if (Parser.parseExpression(ImmVal))
4735 return MatchOperand_ParseFail;
4736
4737 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4738 if (!MCE)
4739 return MatchOperand_ParseFail;
4740
4741 Pattern = MCE->getValue();
4742 } else {
4743 // Parse the pattern
4744 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
4745 if (!Pat)
4746 return MatchOperand_NoMatch;
4747
4748 Parser.Lex();
4749 Pattern = Pat->Encoding;
4750 assert(Pattern >= 0 && Pattern < 32);
4751 }
4752
4753 Operands.push_back(
4754 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
4755 SS, getLoc(), getContext()));
4756
4757 return MatchOperand_Success;
4758}