blob: 34e1fce72438d86188f7afab27e3f677bea770b7 [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 ||
521 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) {
522 // Note that we don't range-check the addend. It's adjusted modulo page
523 // size when converted, so there is no "out of range" condition when using
524 // @pageoff.
525 return Addend >= 0 && (Addend % Scale) == 0;
526 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
527 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
528 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
529 return Addend == 0;
530 }
531
532 return false;
533 }
534
535 template <int Scale> bool isUImm12Offset() const {
536 if (!isImm())
537 return false;
538
539 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
540 if (!MCE)
541 return isSymbolicUImm12Offset(getImm(), Scale);
542
543 int64_t Val = MCE->getValue();
544 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
545 }
546
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000547 template <int N, int M>
548 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000549 if (!isImm())
550 return false;
551 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
552 if (!MCE)
553 return false;
554 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000555 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000556 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000557
Tim Northover3b0846e2014-05-24 12:50:23 +0000558 bool isLogicalImm32() const {
559 if (!isImm())
560 return false;
561 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
562 if (!MCE)
563 return false;
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000564 int64_t Val = MCE->getValue();
565 if (Val >> 32 != 0 && Val >> 32 != ~0LL)
566 return false;
567 Val &= 0xFFFFFFFF;
568 return AArch64_AM::isLogicalImmediate(Val, 32);
Tim Northover3b0846e2014-05-24 12:50:23 +0000569 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000570
Tim Northover3b0846e2014-05-24 12:50:23 +0000571 bool isLogicalImm64() const {
572 if (!isImm())
573 return false;
574 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
575 if (!MCE)
576 return false;
577 return AArch64_AM::isLogicalImmediate(MCE->getValue(), 64);
578 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000579
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000580 bool isLogicalImm32Not() const {
581 if (!isImm())
582 return false;
583 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
584 if (!MCE)
585 return false;
586 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
587 return AArch64_AM::isLogicalImmediate(Val, 32);
588 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000589
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000590 bool isLogicalImm64Not() const {
591 if (!isImm())
592 return false;
593 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
594 if (!MCE)
595 return false;
596 return AArch64_AM::isLogicalImmediate(~MCE->getValue(), 64);
597 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000598
Tim Northover3b0846e2014-05-24 12:50:23 +0000599 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000600
Tim Northover3b0846e2014-05-24 12:50:23 +0000601 bool isAddSubImm() const {
602 if (!isShiftedImm() && !isImm())
603 return false;
604
605 const MCExpr *Expr;
606
607 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
608 if (isShiftedImm()) {
609 unsigned Shift = ShiftedImm.ShiftAmount;
610 Expr = ShiftedImm.Val;
611 if (Shift != 0 && Shift != 12)
612 return false;
613 } else {
614 Expr = getImm();
615 }
616
617 AArch64MCExpr::VariantKind ELFRefKind;
618 MCSymbolRefExpr::VariantKind DarwinRefKind;
619 int64_t Addend;
620 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
621 DarwinRefKind, Addend)) {
622 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
623 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
624 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
625 || ELFRefKind == AArch64MCExpr::VK_LO12
626 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
627 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
628 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
629 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
630 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
631 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
632 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12;
633 }
634
Diana Picusc93518d2016-10-11 09:17:47 +0000635 // If it's a constant, it should be a real immediate in range:
636 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
637 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
638
639 // If it's an expression, we hope for the best and let the fixup/relocation
640 // code deal with it.
641 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000642 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000643
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000644 bool isAddSubImmNeg() const {
645 if (!isShiftedImm() && !isImm())
646 return false;
647
648 const MCExpr *Expr;
649
650 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
651 if (isShiftedImm()) {
652 unsigned Shift = ShiftedImm.ShiftAmount;
653 Expr = ShiftedImm.Val;
654 if (Shift != 0 && Shift != 12)
655 return false;
656 } else
657 Expr = getImm();
658
659 // Otherwise it should be a real negative immediate in range:
660 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
661 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
662 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000663
Tim Northover3b0846e2014-05-24 12:50:23 +0000664 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000665
Tim Northover3b0846e2014-05-24 12:50:23 +0000666 bool isSIMDImmType10() const {
667 if (!isImm())
668 return false;
669 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
670 if (!MCE)
671 return false;
672 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
673 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000674
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000675 template<int N>
676 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000677 if (!isImm())
678 return false;
679 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
680 if (!MCE)
681 return true;
682 int64_t Val = MCE->getValue();
683 if (Val & 0x3)
684 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000685 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
686 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000687 }
688
689 bool
690 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
691 if (!isImm())
692 return false;
693
694 AArch64MCExpr::VariantKind ELFRefKind;
695 MCSymbolRefExpr::VariantKind DarwinRefKind;
696 int64_t Addend;
697 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
698 DarwinRefKind, Addend)) {
699 return false;
700 }
701 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
702 return false;
703
704 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
705 if (ELFRefKind == AllowedModifiers[i])
706 return Addend == 0;
707 }
708
709 return false;
710 }
711
712 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000713 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000714 }
715
716 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000717 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
718 AArch64MCExpr::VK_TPREL_G2,
719 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000720 }
721
722 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000723 return isMovWSymbol({
724 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000725 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
726 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000727 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000728 }
729
730 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000731 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
732 AArch64MCExpr::VK_TPREL_G0,
733 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000734 }
735
736 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000737 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000738 }
739
740 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000741 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000742 }
743
744 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000745 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
746 AArch64MCExpr::VK_TPREL_G1_NC,
747 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000748 }
749
750 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000751 return isMovWSymbol(
752 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
753 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000754 }
755
756 template<int RegWidth, int Shift>
757 bool isMOVZMovAlias() const {
758 if (!isImm()) return false;
759
760 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
761 if (!CE) return false;
762 uint64_t Value = CE->getValue();
763
Tim Northoverdaa1c012016-06-16 01:42:25 +0000764 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000765 }
766
767 template<int RegWidth, int Shift>
768 bool isMOVNMovAlias() const {
769 if (!isImm()) return false;
770
771 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
772 if (!CE) return false;
773 uint64_t Value = CE->getValue();
774
Tim Northoverdaa1c012016-06-16 01:42:25 +0000775 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000776 }
777
778 bool isFPImm() const { return Kind == k_FPImm; }
779 bool isBarrier() const { return Kind == k_Barrier; }
780 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000781
Tim Northover3b0846e2014-05-24 12:50:23 +0000782 bool isMRSSystemRegister() const {
783 if (!isSysReg()) return false;
784
Tim Northover7cd58932015-01-22 17:23:04 +0000785 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000786 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000787
Tim Northover3b0846e2014-05-24 12:50:23 +0000788 bool isMSRSystemRegister() const {
789 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000790 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000791 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000792
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000793 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000794 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000795 return (SysReg.PStateField == AArch64PState::PAN ||
796 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000797 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000798
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000799 bool isSystemPStateFieldWithImm0_15() const {
800 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000801 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000802 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000803
Florian Hahnc4422242017-11-07 13:07:50 +0000804 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000805 return Kind == k_Register;
806 }
807
808 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000809 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
810 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000811
Florian Hahnc4422242017-11-07 13:07:50 +0000812 bool isNeonVectorReg() const {
813 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
814 }
815
816 bool isNeonVectorRegLo() const {
817 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000818 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
819 Reg.RegNum);
820 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000821
Sander de Smalencd6be962017-12-20 11:02:42 +0000822 template <unsigned Class> bool isSVEVectorReg() const {
823 RegKind RK;
824 switch (Class) {
825 case AArch64::ZPRRegClassID:
826 RK = RegKind::SVEDataVector;
827 break;
828 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000829 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000830 RK = RegKind::SVEPredicateVector;
831 break;
832 default:
833 llvm_unreachable("Unsupport register class");
834 }
835
836 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000837 AArch64MCRegisterClasses[Class].contains(getReg());
838 }
839
Sander de Smalencd6be962017-12-20 11:02:42 +0000840 template <int ElementWidth, unsigned Class>
841 bool isSVEVectorRegOfWidth() const {
842 return isSVEVectorReg<Class>() &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000843 (ElementWidth == -1 || Reg.ElementWidth == ElementWidth);
844 }
845
Tim Northover3b0846e2014-05-24 12:50:23 +0000846 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000847 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000848 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
849 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000850
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000851 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000852 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000853 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
854 Reg.RegNum);
855 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000856
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000857 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000858 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000859 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
860 Reg.RegNum);
861 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000862
863 bool isGPR64sp0() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000864 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000865 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
866 }
867
Sam Parker5f934642017-08-31 09:27:04 +0000868 template<int64_t Angle, int64_t Remainder>
869 bool isComplexRotation() const {
870 if (!isImm()) return false;
871
872 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
873 if (!CE) return false;
874 uint64_t Value = CE->getValue();
875
876 return (Value % Angle == Remainder && Value <= 270);
877 }
878
Tim Northover3b0846e2014-05-24 12:50:23 +0000879 /// Is this a vector list with the type implicit (presumably attached to the
880 /// instruction itself)?
881 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
882 return Kind == k_VectorList && VectorList.Count == NumRegs &&
883 !VectorList.ElementKind;
884 }
885
886 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
887 bool isTypedVectorList() const {
888 if (Kind != k_VectorList)
889 return false;
890 if (VectorList.Count != NumRegs)
891 return false;
892 if (VectorList.ElementKind != ElementKind)
893 return false;
894 return VectorList.NumElements == NumElements;
895 }
896
897 bool isVectorIndex1() const {
898 return Kind == k_VectorIndex && VectorIndex.Val == 1;
899 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000900
Tim Northover3b0846e2014-05-24 12:50:23 +0000901 bool isVectorIndexB() const {
902 return Kind == k_VectorIndex && VectorIndex.Val < 16;
903 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000904
Tim Northover3b0846e2014-05-24 12:50:23 +0000905 bool isVectorIndexH() const {
906 return Kind == k_VectorIndex && VectorIndex.Val < 8;
907 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000908
Tim Northover3b0846e2014-05-24 12:50:23 +0000909 bool isVectorIndexS() const {
910 return Kind == k_VectorIndex && VectorIndex.Val < 4;
911 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000912
Tim Northover3b0846e2014-05-24 12:50:23 +0000913 bool isVectorIndexD() const {
914 return Kind == k_VectorIndex && VectorIndex.Val < 2;
915 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000916
Tim Northover3b0846e2014-05-24 12:50:23 +0000917 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000918
Tim Northover3b0846e2014-05-24 12:50:23 +0000919 bool isTokenEqual(StringRef Str) const {
920 return Kind == k_Token && getToken() == Str;
921 }
922 bool isSysCR() const { return Kind == k_SysCR; }
923 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000924 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000925 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
926 bool isShifter() const {
927 if (!isShiftExtend())
928 return false;
929
930 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
931 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
932 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
933 ST == AArch64_AM::MSL);
934 }
935 bool isExtend() const {
936 if (!isShiftExtend())
937 return false;
938
939 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
940 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
941 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
942 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
943 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
944 ET == AArch64_AM::LSL) &&
945 getShiftExtendAmount() <= 4;
946 }
947
948 bool isExtend64() const {
949 if (!isExtend())
950 return false;
951 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
952 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
953 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
954 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000955
Tim Northover3b0846e2014-05-24 12:50:23 +0000956 bool isExtendLSL64() const {
957 if (!isExtend())
958 return false;
959 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
960 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
961 ET == AArch64_AM::LSL) &&
962 getShiftExtendAmount() <= 4;
963 }
964
965 template<int Width> bool isMemXExtend() const {
966 if (!isExtend())
967 return false;
968 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
969 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
970 (getShiftExtendAmount() == Log2_32(Width / 8) ||
971 getShiftExtendAmount() == 0);
972 }
973
974 template<int Width> bool isMemWExtend() const {
975 if (!isExtend())
976 return false;
977 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
978 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
979 (getShiftExtendAmount() == Log2_32(Width / 8) ||
980 getShiftExtendAmount() == 0);
981 }
982
983 template <unsigned width>
984 bool isArithmeticShifter() const {
985 if (!isShifter())
986 return false;
987
988 // An arithmetic shifter is LSL, LSR, or ASR.
989 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
990 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
991 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
992 }
993
994 template <unsigned width>
995 bool isLogicalShifter() const {
996 if (!isShifter())
997 return false;
998
999 // A logical shifter is LSL, LSR, ASR or ROR.
1000 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1001 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1002 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1003 getShiftExtendAmount() < width;
1004 }
1005
1006 bool isMovImm32Shifter() const {
1007 if (!isShifter())
1008 return false;
1009
1010 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1011 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1012 if (ST != AArch64_AM::LSL)
1013 return false;
1014 uint64_t Val = getShiftExtendAmount();
1015 return (Val == 0 || Val == 16);
1016 }
1017
1018 bool isMovImm64Shifter() const {
1019 if (!isShifter())
1020 return false;
1021
1022 // A MOVi shifter is LSL of 0 or 16.
1023 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1024 if (ST != AArch64_AM::LSL)
1025 return false;
1026 uint64_t Val = getShiftExtendAmount();
1027 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1028 }
1029
1030 bool isLogicalVecShifter() const {
1031 if (!isShifter())
1032 return false;
1033
1034 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1035 unsigned Shift = getShiftExtendAmount();
1036 return getShiftExtendType() == AArch64_AM::LSL &&
1037 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1038 }
1039
1040 bool isLogicalVecHalfWordShifter() const {
1041 if (!isLogicalVecShifter())
1042 return false;
1043
1044 // A logical vector shifter is a left shift by 0 or 8.
1045 unsigned Shift = getShiftExtendAmount();
1046 return getShiftExtendType() == AArch64_AM::LSL &&
1047 (Shift == 0 || Shift == 8);
1048 }
1049
1050 bool isMoveVecShifter() const {
1051 if (!isShiftExtend())
1052 return false;
1053
1054 // A logical vector shifter is a left shift by 8 or 16.
1055 unsigned Shift = getShiftExtendAmount();
1056 return getShiftExtendType() == AArch64_AM::MSL &&
1057 (Shift == 8 || Shift == 16);
1058 }
1059
1060 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1061 // to LDUR/STUR when the offset is not legal for the former but is for
1062 // the latter. As such, in addition to checking for being a legal unscaled
1063 // address, also check that it is not a legal scaled address. This avoids
1064 // ambiguity in the matcher.
1065 template<int Width>
1066 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001067 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001068 }
1069
1070 bool isAdrpLabel() const {
1071 // Validation was handled during parsing, so we just sanity check that
1072 // something didn't go haywire.
1073 if (!isImm())
1074 return false;
1075
1076 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1077 int64_t Val = CE->getValue();
1078 int64_t Min = - (4096 * (1LL << (21 - 1)));
1079 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1080 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1081 }
1082
1083 return true;
1084 }
1085
1086 bool isAdrLabel() const {
1087 // Validation was handled during parsing, so we just sanity check that
1088 // something didn't go haywire.
1089 if (!isImm())
1090 return false;
1091
1092 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1093 int64_t Val = CE->getValue();
1094 int64_t Min = - (1LL << (21 - 1));
1095 int64_t Max = ((1LL << (21 - 1)) - 1);
1096 return Val >= Min && Val <= Max;
1097 }
1098
1099 return true;
1100 }
1101
1102 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1103 // Add as immediates when possible. Null MCExpr = 0.
1104 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001105 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001106 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001107 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001108 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001109 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001110 }
1111
1112 void addRegOperands(MCInst &Inst, unsigned N) const {
1113 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001114 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001115 }
1116
1117 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1118 assert(N == 1 && "Invalid number of operands!");
1119 assert(
1120 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1121
1122 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1123 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1124 RI->getEncodingValue(getReg()));
1125
Jim Grosbache9119e42015-05-13 18:37:00 +00001126 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001127 }
1128
1129 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1130 assert(N == 1 && "Invalid number of operands!");
1131 assert(
1132 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001133 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001134 }
1135
1136 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1137 assert(N == 1 && "Invalid number of operands!");
1138 assert(
1139 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001140 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001141 }
1142
1143 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1144 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001145 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001146 }
1147
1148 template <unsigned NumRegs>
1149 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1150 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001151 static const unsigned FirstRegs[] = { AArch64::D0,
1152 AArch64::D0_D1,
1153 AArch64::D0_D1_D2,
1154 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001155 unsigned FirstReg = FirstRegs[NumRegs - 1];
1156
1157 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001158 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001159 }
1160
1161 template <unsigned NumRegs>
1162 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1163 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001164 static const unsigned FirstRegs[] = { AArch64::Q0,
1165 AArch64::Q0_Q1,
1166 AArch64::Q0_Q1_Q2,
1167 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001168 unsigned FirstReg = FirstRegs[NumRegs - 1];
1169
1170 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001171 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001172 }
1173
1174 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1175 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001176 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001177 }
1178
1179 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1180 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001181 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001182 }
1183
1184 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1185 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001186 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001187 }
1188
1189 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1190 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001191 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001192 }
1193
1194 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1195 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001196 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001197 }
1198
1199 void addImmOperands(MCInst &Inst, unsigned N) const {
1200 assert(N == 1 && "Invalid number of operands!");
1201 // If this is a pageoff symrefexpr with an addend, adjust the addend
1202 // to be only the page-offset portion. Otherwise, just add the expr
1203 // as-is.
1204 addExpr(Inst, getImm());
1205 }
1206
1207 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1208 assert(N == 2 && "Invalid number of operands!");
1209 if (isShiftedImm()) {
1210 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001211 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001212 } else {
1213 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001214 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001215 }
1216 }
1217
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001218 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1219 assert(N == 2 && "Invalid number of operands!");
1220
1221 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1222 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1223 int64_t Val = -CE->getValue();
1224 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1225
1226 Inst.addOperand(MCOperand::createImm(Val));
1227 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1228 }
1229
Tim Northover3b0846e2014-05-24 12:50:23 +00001230 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1231 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001232 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001233 }
1234
1235 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1236 assert(N == 1 && "Invalid number of operands!");
1237 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1238 if (!MCE)
1239 addExpr(Inst, getImm());
1240 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001241 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001242 }
1243
1244 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1245 addImmOperands(Inst, N);
1246 }
1247
1248 template<int Scale>
1249 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1250 assert(N == 1 && "Invalid number of operands!");
1251 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1252
1253 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001254 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001255 return;
1256 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001257 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001258 }
1259
1260 void addSImm9Operands(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()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001264 }
1265
Sam Parker6d42de72017-08-11 13:14:00 +00001266 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1267 assert(N == 1 && "Invalid number of operands!");
1268 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1269 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1270 }
1271
Tim Northover3b0846e2014-05-24 12:50:23 +00001272 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1273 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001274 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001275 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001276 }
1277
1278 void addSImm7s8Operands(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() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001282 }
1283
1284 void addSImm7s16Operands(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() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001288 }
1289
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001290 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1291 assert(N == 1 && "Invalid number of operands!");
1292 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1293 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1294 }
1295
Tim Northover3b0846e2014-05-24 12:50:23 +00001296 void addImm0_7Operands(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());
Jim Grosbache9119e42015-05-13 18:37:00 +00001299 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001300 }
1301
1302 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1303 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001304 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001305 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001306 }
1307
1308 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1309 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001310 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001311 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001312 }
1313
1314 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1315 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001316 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001317 assert(MCE && "Invalid constant immediate operand!");
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_31Operands(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_31Operands(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_32Operands(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_63Operands(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 addImm1_63Operands(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 addImm1_64Operands(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 addImm0_127Operands(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
1363 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1364 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001365 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001366 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001367 }
1368
1369 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1370 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001371 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001372 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001373 }
1374
1375 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1376 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001377 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001378 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001379 }
1380
1381 void addLogicalImm32Operands(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());
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +00001384 uint64_t encoding =
1385 AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001386 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001387 }
1388
1389 void addLogicalImm64Operands(MCInst &Inst, unsigned N) const {
1390 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001391 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001392 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001393 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001394 }
1395
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001396 void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
1397 assert(N == 1 && "Invalid number of operands!");
1398 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1399 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
1400 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001401 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001402 }
1403
1404 void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
1405 assert(N == 1 && "Invalid number of operands!");
1406 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1407 uint64_t encoding =
1408 AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001409 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001410 }
1411
Tim Northover3b0846e2014-05-24 12:50:23 +00001412 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1413 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001414 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001415 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001416 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001417 }
1418
1419 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1420 // Branch operands don't encode the low bits, so shift them off
1421 // here. If it's a label, however, just put it on directly as there's
1422 // not enough information now to do anything.
1423 assert(N == 1 && "Invalid number of operands!");
1424 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1425 if (!MCE) {
1426 addExpr(Inst, getImm());
1427 return;
1428 }
1429 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001430 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001431 }
1432
1433 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1434 // Branch operands don't encode the low bits, so shift them off
1435 // here. If it's a label, however, just put it on directly as there's
1436 // not enough information now to do anything.
1437 assert(N == 1 && "Invalid number of operands!");
1438 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1439 if (!MCE) {
1440 addExpr(Inst, getImm());
1441 return;
1442 }
1443 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001444 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001445 }
1446
1447 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1448 // Branch operands don't encode the low bits, so shift them off
1449 // here. If it's a label, however, just put it on directly as there's
1450 // not enough information now to do anything.
1451 assert(N == 1 && "Invalid number of operands!");
1452 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1453 if (!MCE) {
1454 addExpr(Inst, getImm());
1455 return;
1456 }
1457 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001458 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001459 }
1460
1461 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1462 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001463 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001464 }
1465
1466 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1467 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001468 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001469 }
1470
1471 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1472 assert(N == 1 && "Invalid number of operands!");
1473
Jim Grosbache9119e42015-05-13 18:37:00 +00001474 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001475 }
1476
1477 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1478 assert(N == 1 && "Invalid number of operands!");
1479
Jim Grosbache9119e42015-05-13 18:37:00 +00001480 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001481 }
1482
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001483 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1484 assert(N == 1 && "Invalid number of operands!");
1485
1486 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1487 }
1488
1489 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001490 assert(N == 1 && "Invalid number of operands!");
1491
Jim Grosbache9119e42015-05-13 18:37:00 +00001492 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001493 }
1494
1495 void addSysCROperands(MCInst &Inst, unsigned N) const {
1496 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001497 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001498 }
1499
1500 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1501 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001502 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001503 }
1504
Oliver Stannarda34e4702015-12-01 10:48:51 +00001505 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1506 assert(N == 1 && "Invalid number of operands!");
1507 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1508 }
1509
Tim Northover3b0846e2014-05-24 12:50:23 +00001510 void addShifterOperands(MCInst &Inst, unsigned N) const {
1511 assert(N == 1 && "Invalid number of operands!");
1512 unsigned Imm =
1513 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001514 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001515 }
1516
1517 void addExtendOperands(MCInst &Inst, unsigned N) const {
1518 assert(N == 1 && "Invalid number of operands!");
1519 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1520 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1521 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001522 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001523 }
1524
1525 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1526 assert(N == 1 && "Invalid number of operands!");
1527 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1528 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1529 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001530 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001531 }
1532
1533 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1534 assert(N == 2 && "Invalid number of operands!");
1535 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1536 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001537 Inst.addOperand(MCOperand::createImm(IsSigned));
1538 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001539 }
1540
1541 // For 8-bit load/store instructions with a register offset, both the
1542 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1543 // they're disambiguated by whether the shift was explicit or implicit rather
1544 // than its size.
1545 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1546 assert(N == 2 && "Invalid number of operands!");
1547 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1548 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001549 Inst.addOperand(MCOperand::createImm(IsSigned));
1550 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001551 }
1552
1553 template<int Shift>
1554 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1555 assert(N == 1 && "Invalid number of operands!");
1556
1557 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1558 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001559 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001560 }
1561
1562 template<int Shift>
1563 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1564 assert(N == 1 && "Invalid number of operands!");
1565
1566 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1567 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001568 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001569 }
1570
Sam Parker5f934642017-08-31 09:27:04 +00001571 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1572 assert(N == 1 && "Invalid number of operands!");
1573 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1574 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1575 }
1576
1577 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1578 assert(N == 1 && "Invalid number of operands!");
1579 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1580 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1581 }
1582
Tim Northover3b0846e2014-05-24 12:50:23 +00001583 void print(raw_ostream &OS) const override;
1584
David Blaikie960ea3f2014-06-08 16:18:35 +00001585 static std::unique_ptr<AArch64Operand>
1586 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1587 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001588 Op->Tok.Data = Str.data();
1589 Op->Tok.Length = Str.size();
1590 Op->Tok.IsSuffix = IsSuffix;
1591 Op->StartLoc = S;
1592 Op->EndLoc = S;
1593 return Op;
1594 }
1595
David Blaikie960ea3f2014-06-08 16:18:35 +00001596 static std::unique_ptr<AArch64Operand>
Florian Hahnc4422242017-11-07 13:07:50 +00001597 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001598 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001599 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001600 Op->Reg.Kind = Kind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001601 Op->StartLoc = S;
1602 Op->EndLoc = E;
1603 return Op;
1604 }
1605
David Blaikie960ea3f2014-06-08 16:18:35 +00001606 static std::unique_ptr<AArch64Operand>
Florian Hahn91f11e52017-11-07 16:45:48 +00001607 CreateReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1608 SMLoc S, SMLoc E, MCContext &Ctx) {
1609 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1610 Op->Reg.RegNum = RegNum;
1611 Op->Reg.ElementWidth = ElementWidth;
1612 Op->Reg.Kind = Kind;
1613 Op->StartLoc = S;
1614 Op->EndLoc = E;
1615 return Op;
1616 }
1617
1618 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001619 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1620 char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1621 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001622 Op->VectorList.RegNum = RegNum;
1623 Op->VectorList.Count = Count;
1624 Op->VectorList.NumElements = NumElements;
1625 Op->VectorList.ElementKind = ElementKind;
1626 Op->StartLoc = S;
1627 Op->EndLoc = E;
1628 return Op;
1629 }
1630
David Blaikie960ea3f2014-06-08 16:18:35 +00001631 static std::unique_ptr<AArch64Operand>
1632 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1633 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001634 Op->VectorIndex.Val = Idx;
1635 Op->StartLoc = S;
1636 Op->EndLoc = E;
1637 return Op;
1638 }
1639
David Blaikie960ea3f2014-06-08 16:18:35 +00001640 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1641 SMLoc E, MCContext &Ctx) {
1642 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001643 Op->Imm.Val = Val;
1644 Op->StartLoc = S;
1645 Op->EndLoc = E;
1646 return Op;
1647 }
1648
David Blaikie960ea3f2014-06-08 16:18:35 +00001649 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1650 unsigned ShiftAmount,
1651 SMLoc S, SMLoc E,
1652 MCContext &Ctx) {
1653 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001654 Op->ShiftedImm .Val = Val;
1655 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1656 Op->StartLoc = S;
1657 Op->EndLoc = E;
1658 return Op;
1659 }
1660
David Blaikie960ea3f2014-06-08 16:18:35 +00001661 static std::unique_ptr<AArch64Operand>
1662 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1663 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001664 Op->CondCode.Code = Code;
1665 Op->StartLoc = S;
1666 Op->EndLoc = E;
1667 return Op;
1668 }
1669
David Blaikie960ea3f2014-06-08 16:18:35 +00001670 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1671 MCContext &Ctx) {
1672 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001673 Op->FPImm.Val = Val;
1674 Op->StartLoc = S;
1675 Op->EndLoc = S;
1676 return Op;
1677 }
1678
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001679 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1680 StringRef Str,
1681 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001682 MCContext &Ctx) {
1683 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001684 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001685 Op->Barrier.Data = Str.data();
1686 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001687 Op->StartLoc = S;
1688 Op->EndLoc = S;
1689 return Op;
1690 }
1691
Tim Northover7cd58932015-01-22 17:23:04 +00001692 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1693 uint32_t MRSReg,
1694 uint32_t MSRReg,
1695 uint32_t PStateField,
1696 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001697 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001698 Op->SysReg.Data = Str.data();
1699 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001700 Op->SysReg.MRSReg = MRSReg;
1701 Op->SysReg.MSRReg = MSRReg;
1702 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001703 Op->StartLoc = S;
1704 Op->EndLoc = S;
1705 return Op;
1706 }
1707
David Blaikie960ea3f2014-06-08 16:18:35 +00001708 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1709 SMLoc E, MCContext &Ctx) {
1710 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001711 Op->SysCRImm.Val = Val;
1712 Op->StartLoc = S;
1713 Op->EndLoc = E;
1714 return Op;
1715 }
1716
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001717 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1718 StringRef Str,
1719 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001720 MCContext &Ctx) {
1721 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001722 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001723 Op->Barrier.Data = Str.data();
1724 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001725 Op->StartLoc = S;
1726 Op->EndLoc = S;
1727 return Op;
1728 }
1729
Oliver Stannarda34e4702015-12-01 10:48:51 +00001730 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1731 StringRef Str,
1732 SMLoc S,
1733 MCContext &Ctx) {
1734 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1735 Op->PSBHint.Val = Val;
1736 Op->PSBHint.Data = Str.data();
1737 Op->PSBHint.Length = Str.size();
1738 Op->StartLoc = S;
1739 Op->EndLoc = S;
1740 return Op;
1741 }
1742
David Blaikie960ea3f2014-06-08 16:18:35 +00001743 static std::unique_ptr<AArch64Operand>
1744 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1745 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1746 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001747 Op->ShiftExtend.Type = ShOp;
1748 Op->ShiftExtend.Amount = Val;
1749 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1750 Op->StartLoc = S;
1751 Op->EndLoc = E;
1752 return Op;
1753 }
1754};
1755
1756} // end anonymous namespace.
1757
1758void AArch64Operand::print(raw_ostream &OS) const {
1759 switch (Kind) {
1760 case k_FPImm:
1761 OS << "<fpimm " << getFPImm() << "("
1762 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1763 break;
1764 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001765 StringRef Name = getBarrierName();
1766 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001767 OS << "<barrier " << Name << ">";
1768 else
1769 OS << "<barrier invalid #" << getBarrier() << ">";
1770 break;
1771 }
1772 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001773 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001774 break;
1775 case k_ShiftedImm: {
1776 unsigned Shift = getShiftedImmShift();
1777 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001778 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001779 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1780 break;
1781 }
1782 case k_CondCode:
1783 OS << "<condcode " << getCondCode() << ">";
1784 break;
1785 case k_Register:
1786 OS << "<register " << getReg() << ">";
1787 break;
1788 case k_VectorList: {
1789 OS << "<vectorlist ";
1790 unsigned Reg = getVectorListStart();
1791 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1792 OS << Reg + i << " ";
1793 OS << ">";
1794 break;
1795 }
1796 case k_VectorIndex:
1797 OS << "<vectorindex " << getVectorIndex() << ">";
1798 break;
1799 case k_SysReg:
1800 OS << "<sysreg: " << getSysReg() << '>';
1801 break;
1802 case k_Token:
1803 OS << "'" << getToken() << "'";
1804 break;
1805 case k_SysCR:
1806 OS << "c" << getSysCR();
1807 break;
1808 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001809 StringRef Name = getPrefetchName();
1810 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001811 OS << "<prfop " << Name << ">";
1812 else
1813 OS << "<prfop invalid #" << getPrefetch() << ">";
1814 break;
1815 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001816 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001817 OS << getPSBHintName();
1818 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001819 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001820 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1821 << getShiftExtendAmount();
1822 if (!hasShiftExtendAmount())
1823 OS << "<imp>";
1824 OS << '>';
1825 break;
1826 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001827}
1828
1829/// @name Auto-generated Match Functions
1830/// {
1831
1832static unsigned MatchRegisterName(StringRef Name);
1833
1834/// }
1835
Florian Hahnc4422242017-11-07 13:07:50 +00001836static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001837 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001838 .Case("v0", AArch64::Q0)
1839 .Case("v1", AArch64::Q1)
1840 .Case("v2", AArch64::Q2)
1841 .Case("v3", AArch64::Q3)
1842 .Case("v4", AArch64::Q4)
1843 .Case("v5", AArch64::Q5)
1844 .Case("v6", AArch64::Q6)
1845 .Case("v7", AArch64::Q7)
1846 .Case("v8", AArch64::Q8)
1847 .Case("v9", AArch64::Q9)
1848 .Case("v10", AArch64::Q10)
1849 .Case("v11", AArch64::Q11)
1850 .Case("v12", AArch64::Q12)
1851 .Case("v13", AArch64::Q13)
1852 .Case("v14", AArch64::Q14)
1853 .Case("v15", AArch64::Q15)
1854 .Case("v16", AArch64::Q16)
1855 .Case("v17", AArch64::Q17)
1856 .Case("v18", AArch64::Q18)
1857 .Case("v19", AArch64::Q19)
1858 .Case("v20", AArch64::Q20)
1859 .Case("v21", AArch64::Q21)
1860 .Case("v22", AArch64::Q22)
1861 .Case("v23", AArch64::Q23)
1862 .Case("v24", AArch64::Q24)
1863 .Case("v25", AArch64::Q25)
1864 .Case("v26", AArch64::Q26)
1865 .Case("v27", AArch64::Q27)
1866 .Case("v28", AArch64::Q28)
1867 .Case("v29", AArch64::Q29)
1868 .Case("v30", AArch64::Q30)
1869 .Case("v31", AArch64::Q31)
1870 .Default(0);
1871}
1872
1873static bool isValidVectorKind(StringRef Name) {
1874 return StringSwitch<bool>(Name.lower())
1875 .Case(".8b", true)
1876 .Case(".16b", true)
1877 .Case(".4h", true)
1878 .Case(".8h", true)
1879 .Case(".2s", true)
1880 .Case(".4s", true)
1881 .Case(".1d", true)
1882 .Case(".2d", true)
1883 .Case(".1q", true)
1884 // Accept the width neutral ones, too, for verbose syntax. If those
1885 // aren't used in the right places, the token operand won't match so
1886 // all will work out.
1887 .Case(".b", true)
1888 .Case(".h", true)
1889 .Case(".s", true)
1890 .Case(".d", true)
Oliver Stannarde4c3d212015-12-08 12:16:10 +00001891 // Needed for fp16 scalar pairwise reductions
1892 .Case(".2h", true)
Sjoerd Meijer79876332017-08-09 14:59:54 +00001893 // another special case for the ARMv8.2a dot product operand
1894 .Case(".4b", true)
Tim Northover3b0846e2014-05-24 12:50:23 +00001895 .Default(false);
1896}
1897
Florian Hahn91f11e52017-11-07 16:45:48 +00001898static unsigned matchSVEDataVectorRegName(StringRef Name) {
1899 return StringSwitch<unsigned>(Name.lower())
1900 .Case("z0", AArch64::Z0)
1901 .Case("z1", AArch64::Z1)
1902 .Case("z2", AArch64::Z2)
1903 .Case("z3", AArch64::Z3)
1904 .Case("z4", AArch64::Z4)
1905 .Case("z5", AArch64::Z5)
1906 .Case("z6", AArch64::Z6)
1907 .Case("z7", AArch64::Z7)
1908 .Case("z8", AArch64::Z8)
1909 .Case("z9", AArch64::Z9)
1910 .Case("z10", AArch64::Z10)
1911 .Case("z11", AArch64::Z11)
1912 .Case("z12", AArch64::Z12)
1913 .Case("z13", AArch64::Z13)
1914 .Case("z14", AArch64::Z14)
1915 .Case("z15", AArch64::Z15)
1916 .Case("z16", AArch64::Z16)
1917 .Case("z17", AArch64::Z17)
1918 .Case("z18", AArch64::Z18)
1919 .Case("z19", AArch64::Z19)
1920 .Case("z20", AArch64::Z20)
1921 .Case("z21", AArch64::Z21)
1922 .Case("z22", AArch64::Z22)
1923 .Case("z23", AArch64::Z23)
1924 .Case("z24", AArch64::Z24)
1925 .Case("z25", AArch64::Z25)
1926 .Case("z26", AArch64::Z26)
1927 .Case("z27", AArch64::Z27)
1928 .Case("z28", AArch64::Z28)
1929 .Case("z29", AArch64::Z29)
1930 .Case("z30", AArch64::Z30)
1931 .Case("z31", AArch64::Z31)
1932 .Default(0);
1933}
1934
Sander de Smalencd6be962017-12-20 11:02:42 +00001935static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1936 return StringSwitch<unsigned>(Name.lower())
1937 .Case("p0", AArch64::P0)
1938 .Case("p1", AArch64::P1)
1939 .Case("p2", AArch64::P2)
1940 .Case("p3", AArch64::P3)
1941 .Case("p4", AArch64::P4)
1942 .Case("p5", AArch64::P5)
1943 .Case("p6", AArch64::P6)
1944 .Case("p7", AArch64::P7)
1945 .Case("p8", AArch64::P8)
1946 .Case("p9", AArch64::P9)
1947 .Case("p10", AArch64::P10)
1948 .Case("p11", AArch64::P11)
1949 .Case("p12", AArch64::P12)
1950 .Case("p13", AArch64::P13)
1951 .Case("p14", AArch64::P14)
1952 .Case("p15", AArch64::P15)
1953 .Default(0);
1954}
1955
Florian Hahn91f11e52017-11-07 16:45:48 +00001956static bool isValidSVEKind(StringRef Name) {
1957 return StringSwitch<bool>(Name.lower())
1958 .Case(".b", true)
1959 .Case(".h", true)
1960 .Case(".s", true)
1961 .Case(".d", true)
1962 .Case(".q", true)
1963 .Default(false);
1964}
1965
Tim Northover3b0846e2014-05-24 12:50:23 +00001966static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1967 char &ElementKind) {
1968 assert(isValidVectorKind(Name));
1969
1970 ElementKind = Name.lower()[Name.size() - 1];
1971 NumElements = 0;
1972
1973 if (Name.size() == 2)
1974 return;
1975
1976 // Parse the lane count
1977 Name = Name.drop_front();
1978 while (isdigit(Name.front())) {
1979 NumElements = 10 * NumElements + (Name.front() - '0');
1980 Name = Name.drop_front();
1981 }
1982}
1983
1984bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1985 SMLoc &EndLoc) {
1986 StartLoc = getLoc();
1987 RegNo = tryParseRegister();
1988 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1989 return (RegNo == (unsigned)-1);
1990}
1991
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001992// Matches a register name or register alias previously defined by '.req'
1993unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001994 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001995 unsigned RegNum = 0;
1996 if ((RegNum = matchSVEDataVectorRegName(Name)))
1997 return Kind == RegKind::SVEDataVector ? RegNum : 0;
1998
Sander de Smalencd6be962017-12-20 11:02:42 +00001999 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2000 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2001
Sander de Smalenc067c302017-12-20 09:45:45 +00002002 if ((RegNum = MatchNeonVectorRegName(Name)))
2003 return Kind == RegKind::NeonVector ? RegNum : 0;
2004
2005 // The parsed register must be of RegKind Scalar
2006 if ((RegNum = MatchRegisterName(Name)))
2007 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002008
Florian Hahnc4422242017-11-07 13:07:50 +00002009 if (!RegNum) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002010 // Check for aliases registered via .req. Canonicalize to lower case.
2011 // That's more consistent since register names are case insensitive, and
2012 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2013 auto Entry = RegisterReqs.find(Name.lower());
2014 if (Entry == RegisterReqs.end())
2015 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002016
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002017 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002018 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002019 RegNum = Entry->getValue().second;
2020 }
2021 return RegNum;
2022}
2023
Tim Northover3b0846e2014-05-24 12:50:23 +00002024/// tryParseRegister - Try to parse a register name. The token must be an
2025/// Identifier when called, and if it is a register name the token is eaten and
2026/// the register is added to the operand list.
2027int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002028 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002029 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002030 if (Tok.isNot(AsmToken::Identifier))
2031 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00002032
2033 std::string lowerCase = Tok.getString().lower();
Florian Hahnc4422242017-11-07 13:07:50 +00002034 unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
Sander de Smalenc067c302017-12-20 09:45:45 +00002035
Tim Northover3b0846e2014-05-24 12:50:23 +00002036 // Also handle a few aliases of registers.
2037 if (RegNum == 0)
2038 RegNum = StringSwitch<unsigned>(lowerCase)
2039 .Case("fp", AArch64::FP)
2040 .Case("lr", AArch64::LR)
2041 .Case("x31", AArch64::XZR)
2042 .Case("w31", AArch64::WZR)
2043 .Default(0);
2044
2045 if (RegNum == 0)
2046 return -1;
2047
2048 Parser.Lex(); // Eat identifier token.
2049 return RegNum;
2050}
2051
2052/// tryMatchVectorRegister - Try to parse a vector register name with optional
2053/// kind specifier. If it is a register specifier, eat the token and return it.
2054int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002055 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002056 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2057 TokError("vector register expected");
2058 return -1;
2059 }
2060
2061 StringRef Name = Parser.getTok().getString();
2062 // If there is a kind specifier, it's separated from the register name by
2063 // a '.'.
2064 size_t Start = 0, Next = Name.find('.');
2065 StringRef Head = Name.slice(Start, Next);
Florian Hahnc4422242017-11-07 13:07:50 +00002066 unsigned RegNum = matchRegisterNameAlias(Head, RegKind::NeonVector);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002067
Tim Northover3b0846e2014-05-24 12:50:23 +00002068 if (RegNum) {
2069 if (Next != StringRef::npos) {
2070 Kind = Name.slice(Next, StringRef::npos);
2071 if (!isValidVectorKind(Kind)) {
2072 TokError("invalid vector kind qualifier");
2073 return -1;
2074 }
2075 }
2076 Parser.Lex(); // Eat the register token.
2077 return RegNum;
2078 }
2079
2080 if (expected)
2081 TokError("vector register expected");
2082 return -1;
2083}
2084
2085/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002086OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002087AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002088 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002089 SMLoc S = getLoc();
2090
2091 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2092 Error(S, "Expected cN operand where 0 <= N <= 15");
2093 return MatchOperand_ParseFail;
2094 }
2095
2096 StringRef Tok = Parser.getTok().getIdentifier();
2097 if (Tok[0] != 'c' && Tok[0] != 'C') {
2098 Error(S, "Expected cN operand where 0 <= N <= 15");
2099 return MatchOperand_ParseFail;
2100 }
2101
2102 uint32_t CRNum;
2103 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2104 if (BadNum || CRNum > 15) {
2105 Error(S, "Expected cN operand where 0 <= N <= 15");
2106 return MatchOperand_ParseFail;
2107 }
2108
2109 Parser.Lex(); // Eat identifier token.
2110 Operands.push_back(
2111 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2112 return MatchOperand_Success;
2113}
2114
2115/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002116OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002117AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002118 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002119 SMLoc S = getLoc();
2120 const AsmToken &Tok = Parser.getTok();
2121 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002122 // Eat optional hash.
2123 if (parseOptionalToken(AsmToken::Hash) ||
2124 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002125 const MCExpr *ImmVal;
2126 if (getParser().parseExpression(ImmVal))
2127 return MatchOperand_ParseFail;
2128
2129 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2130 if (!MCE) {
2131 TokError("immediate value expected for prefetch operand");
2132 return MatchOperand_ParseFail;
2133 }
2134 unsigned prfop = MCE->getValue();
2135 if (prfop > 31) {
2136 TokError("prefetch operand out of range, [0,31] expected");
2137 return MatchOperand_ParseFail;
2138 }
2139
Tim Northovere6ae6762016-07-05 21:23:04 +00002140 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2141 Operands.push_back(AArch64Operand::CreatePrefetch(
2142 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002143 return MatchOperand_Success;
2144 }
2145
2146 if (Tok.isNot(AsmToken::Identifier)) {
2147 TokError("pre-fetch hint expected");
2148 return MatchOperand_ParseFail;
2149 }
2150
Tim Northovere6ae6762016-07-05 21:23:04 +00002151 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2152 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002153 TokError("pre-fetch hint expected");
2154 return MatchOperand_ParseFail;
2155 }
2156
2157 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002158 Operands.push_back(AArch64Operand::CreatePrefetch(
2159 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002160 return MatchOperand_Success;
2161}
2162
Oliver Stannarda34e4702015-12-01 10:48:51 +00002163/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002164OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002165AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2166 MCAsmParser &Parser = getParser();
2167 SMLoc S = getLoc();
2168 const AsmToken &Tok = Parser.getTok();
2169 if (Tok.isNot(AsmToken::Identifier)) {
2170 TokError("invalid operand for instruction");
2171 return MatchOperand_ParseFail;
2172 }
2173
Tim Northovere6ae6762016-07-05 21:23:04 +00002174 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2175 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002176 TokError("invalid operand for instruction");
2177 return MatchOperand_ParseFail;
2178 }
2179
2180 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002181 Operands.push_back(AArch64Operand::CreatePSBHint(
2182 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002183 return MatchOperand_Success;
2184}
2185
Tim Northover3b0846e2014-05-24 12:50:23 +00002186/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2187/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002188OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002189AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002190 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002191 SMLoc S = getLoc();
2192 const MCExpr *Expr;
2193
2194 if (Parser.getTok().is(AsmToken::Hash)) {
2195 Parser.Lex(); // Eat hash token.
2196 }
2197
2198 if (parseSymbolicImmVal(Expr))
2199 return MatchOperand_ParseFail;
2200
2201 AArch64MCExpr::VariantKind ELFRefKind;
2202 MCSymbolRefExpr::VariantKind DarwinRefKind;
2203 int64_t Addend;
2204 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2205 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2206 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2207 // No modifier was specified at all; this is the syntax for an ELF basic
2208 // ADRP relocation (unfortunately).
2209 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002210 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002211 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2212 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2213 Addend != 0) {
2214 Error(S, "gotpage label reference not allowed an addend");
2215 return MatchOperand_ParseFail;
2216 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2217 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2218 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2219 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2220 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2221 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2222 // The operand must be an @page or @gotpage qualified symbolref.
2223 Error(S, "page or gotpage label reference expected");
2224 return MatchOperand_ParseFail;
2225 }
2226 }
2227
2228 // We have either a label reference possibly with addend or an immediate. The
2229 // addend is a raw value here. The linker will adjust it to only reference the
2230 // page.
2231 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2232 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2233
2234 return MatchOperand_Success;
2235}
2236
2237/// tryParseAdrLabel - Parse and validate a source label for the ADR
2238/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002239OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002240AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2241 SMLoc S = getLoc();
2242 const MCExpr *Expr;
2243
Nirav Davee833c6c2016-11-08 18:31:04 +00002244 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002245 if (getParser().parseExpression(Expr))
2246 return MatchOperand_ParseFail;
2247
2248 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2249 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2250
2251 return MatchOperand_Success;
2252}
2253
2254/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002255OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002256AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002257 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002258 SMLoc S = getLoc();
2259
Nirav Davee833c6c2016-11-08 18:31:04 +00002260 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002261
2262 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002263 bool isNegative = parseOptionalToken(AsmToken::Minus);
2264
Tim Northover3b0846e2014-05-24 12:50:23 +00002265 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002266 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002267 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002268 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002269 Val = Tok.getIntVal();
2270 if (Val > 255 || Val < 0) {
2271 TokError("encoded floating point value out of range");
2272 return MatchOperand_ParseFail;
2273 }
2274 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002275 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002276 if (isNegative)
2277 RealVal.changeSign();
2278
Tim Northover3b0846e2014-05-24 12:50:23 +00002279 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002280 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002281
John Brawn5ca5daa2017-04-20 10:13:54 +00002282 // Check for out of range values. As an exception we let Zero through,
2283 // but as tokens instead of an FPImm so that it can be matched by the
2284 // appropriate alias if one exists.
2285 if (RealVal.isPosZero()) {
2286 Parser.Lex(); // Eat the token.
2287 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2288 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2289 return MatchOperand_Success;
2290 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002291 TokError("expected compatible register or floating-point constant");
2292 return MatchOperand_ParseFail;
2293 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002294 }
2295 Parser.Lex(); // Eat the token.
2296 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2297 return MatchOperand_Success;
2298 }
2299
2300 if (!Hash)
2301 return MatchOperand_NoMatch;
2302
2303 TokError("invalid floating point immediate");
2304 return MatchOperand_ParseFail;
2305}
2306
2307/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002308OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002309AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002310 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002311 SMLoc S = getLoc();
2312
2313 if (Parser.getTok().is(AsmToken::Hash))
2314 Parser.Lex(); // Eat '#'
2315 else if (Parser.getTok().isNot(AsmToken::Integer))
2316 // Operand should start from # or should be integer, emit error otherwise.
2317 return MatchOperand_NoMatch;
2318
2319 const MCExpr *Imm;
2320 if (parseSymbolicImmVal(Imm))
2321 return MatchOperand_ParseFail;
2322 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2323 uint64_t ShiftAmount = 0;
2324 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2325 if (MCE) {
2326 int64_t Val = MCE->getValue();
2327 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002328 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002329 ShiftAmount = 12;
2330 }
2331 }
2332 SMLoc E = Parser.getTok().getLoc();
2333 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2334 getContext()));
2335 return MatchOperand_Success;
2336 }
2337
2338 // Eat ','
2339 Parser.Lex();
2340
2341 // The optional operand must be "lsl #N" where N is non-negative.
2342 if (!Parser.getTok().is(AsmToken::Identifier) ||
2343 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2344 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2345 return MatchOperand_ParseFail;
2346 }
2347
2348 // Eat 'lsl'
2349 Parser.Lex();
2350
Nirav Davee833c6c2016-11-08 18:31:04 +00002351 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002352
2353 if (Parser.getTok().isNot(AsmToken::Integer)) {
2354 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2355 return MatchOperand_ParseFail;
2356 }
2357
2358 int64_t ShiftAmount = Parser.getTok().getIntVal();
2359
2360 if (ShiftAmount < 0) {
2361 Error(Parser.getTok().getLoc(), "positive shift amount required");
2362 return MatchOperand_ParseFail;
2363 }
2364 Parser.Lex(); // Eat the number
2365
2366 SMLoc E = Parser.getTok().getLoc();
2367 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2368 S, E, getContext()));
2369 return MatchOperand_Success;
2370}
2371
2372/// parseCondCodeString - Parse a Condition Code string.
2373AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2374 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2375 .Case("eq", AArch64CC::EQ)
2376 .Case("ne", AArch64CC::NE)
2377 .Case("cs", AArch64CC::HS)
2378 .Case("hs", AArch64CC::HS)
2379 .Case("cc", AArch64CC::LO)
2380 .Case("lo", AArch64CC::LO)
2381 .Case("mi", AArch64CC::MI)
2382 .Case("pl", AArch64CC::PL)
2383 .Case("vs", AArch64CC::VS)
2384 .Case("vc", AArch64CC::VC)
2385 .Case("hi", AArch64CC::HI)
2386 .Case("ls", AArch64CC::LS)
2387 .Case("ge", AArch64CC::GE)
2388 .Case("lt", AArch64CC::LT)
2389 .Case("gt", AArch64CC::GT)
2390 .Case("le", AArch64CC::LE)
2391 .Case("al", AArch64CC::AL)
2392 .Case("nv", AArch64CC::NV)
2393 .Default(AArch64CC::Invalid);
2394 return CC;
2395}
2396
2397/// parseCondCode - Parse a Condition Code operand.
2398bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2399 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002400 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002401 SMLoc S = getLoc();
2402 const AsmToken &Tok = Parser.getTok();
2403 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2404
2405 StringRef Cond = Tok.getString();
2406 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2407 if (CC == AArch64CC::Invalid)
2408 return TokError("invalid condition code");
2409 Parser.Lex(); // Eat identifier token.
2410
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002411 if (invertCondCode) {
2412 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2413 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002414 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002415 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002416
2417 Operands.push_back(
2418 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2419 return false;
2420}
2421
2422/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2423/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002424OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002425AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002426 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002427 const AsmToken &Tok = Parser.getTok();
2428 std::string LowerID = Tok.getString().lower();
2429 AArch64_AM::ShiftExtendType ShOp =
2430 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2431 .Case("lsl", AArch64_AM::LSL)
2432 .Case("lsr", AArch64_AM::LSR)
2433 .Case("asr", AArch64_AM::ASR)
2434 .Case("ror", AArch64_AM::ROR)
2435 .Case("msl", AArch64_AM::MSL)
2436 .Case("uxtb", AArch64_AM::UXTB)
2437 .Case("uxth", AArch64_AM::UXTH)
2438 .Case("uxtw", AArch64_AM::UXTW)
2439 .Case("uxtx", AArch64_AM::UXTX)
2440 .Case("sxtb", AArch64_AM::SXTB)
2441 .Case("sxth", AArch64_AM::SXTH)
2442 .Case("sxtw", AArch64_AM::SXTW)
2443 .Case("sxtx", AArch64_AM::SXTX)
2444 .Default(AArch64_AM::InvalidShiftExtend);
2445
2446 if (ShOp == AArch64_AM::InvalidShiftExtend)
2447 return MatchOperand_NoMatch;
2448
2449 SMLoc S = Tok.getLoc();
2450 Parser.Lex();
2451
Nirav Davee833c6c2016-11-08 18:31:04 +00002452 bool Hash = parseOptionalToken(AsmToken::Hash);
2453
Tim Northover3b0846e2014-05-24 12:50:23 +00002454 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2455 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2456 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2457 ShOp == AArch64_AM::MSL) {
2458 // We expect a number here.
2459 TokError("expected #imm after shift specifier");
2460 return MatchOperand_ParseFail;
2461 }
2462
Chad Rosier2ff37b82016-12-27 16:58:09 +00002463 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002464 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2465 Operands.push_back(
2466 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2467 return MatchOperand_Success;
2468 }
2469
Chad Rosier2ff37b82016-12-27 16:58:09 +00002470 // Make sure we do actually have a number, identifier or a parenthesized
2471 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002472 SMLoc E = Parser.getTok().getLoc();
2473 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002474 !Parser.getTok().is(AsmToken::LParen) &&
2475 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002476 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002477 return MatchOperand_ParseFail;
2478 }
2479
2480 const MCExpr *ImmVal;
2481 if (getParser().parseExpression(ImmVal))
2482 return MatchOperand_ParseFail;
2483
2484 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2485 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002486 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002487 return MatchOperand_ParseFail;
2488 }
2489
Jim Grosbach57fd2622014-09-23 22:16:02 +00002490 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002491 Operands.push_back(AArch64Operand::CreateShiftExtend(
2492 ShOp, MCE->getValue(), true, S, E, getContext()));
2493 return MatchOperand_Success;
2494}
2495
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002496static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2497 if (FBS[AArch64::HasV8_1aOps])
2498 Str += "ARMv8.1a";
2499 else if (FBS[AArch64::HasV8_2aOps])
2500 Str += "ARMv8.2a";
2501 else
2502 Str += "(unknown)";
2503}
2504
2505void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2506 SMLoc S) {
2507 const uint16_t Op2 = Encoding & 7;
2508 const uint16_t Cm = (Encoding & 0x78) >> 3;
2509 const uint16_t Cn = (Encoding & 0x780) >> 7;
2510 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2511
2512 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2513
2514 Operands.push_back(
2515 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2516 Operands.push_back(
2517 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2518 Operands.push_back(
2519 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2520 Expr = MCConstantExpr::create(Op2, getContext());
2521 Operands.push_back(
2522 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2523}
2524
Tim Northover3b0846e2014-05-24 12:50:23 +00002525/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2526/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2527bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2528 OperandVector &Operands) {
2529 if (Name.find('.') != StringRef::npos)
2530 return TokError("invalid operand");
2531
2532 Mnemonic = Name;
2533 Operands.push_back(
2534 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2535
Rafael Espindola961d4692014-11-11 05:18:41 +00002536 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002537 const AsmToken &Tok = Parser.getTok();
2538 StringRef Op = Tok.getString();
2539 SMLoc S = Tok.getLoc();
2540
Tim Northover3b0846e2014-05-24 12:50:23 +00002541 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002542 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2543 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002544 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002545 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2546 std::string Str("IC " + std::string(IC->Name) + " requires ");
2547 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2548 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002549 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002550 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002551 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002552 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2553 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002554 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002555 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2556 std::string Str("DC " + std::string(DC->Name) + " requires ");
2557 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2558 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002559 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002560 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002561 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002562 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2563 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002564 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002565 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2566 std::string Str("AT " + std::string(AT->Name) + " requires ");
2567 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2568 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002569 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002570 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002571 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002572 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2573 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002574 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002575 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2576 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2577 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2578 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002579 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002580 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002581 }
2582
Tim Northover3b0846e2014-05-24 12:50:23 +00002583 Parser.Lex(); // Eat operand.
2584
2585 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2586 bool HasRegister = false;
2587
2588 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002589 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002590 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2591 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002592 HasRegister = true;
2593 }
2594
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002595 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002596 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002597 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002598 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002599
Nirav Davee833c6c2016-11-08 18:31:04 +00002600 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2601 return true;
2602
Tim Northover3b0846e2014-05-24 12:50:23 +00002603 return false;
2604}
2605
Alex Bradbury58eba092016-11-01 16:32:05 +00002606OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002607AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002608 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002609 const AsmToken &Tok = Parser.getTok();
2610
2611 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002612 if (parseOptionalToken(AsmToken::Hash) ||
2613 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002614 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002615 const MCExpr *ImmVal;
2616 SMLoc ExprLoc = getLoc();
2617 if (getParser().parseExpression(ImmVal))
2618 return MatchOperand_ParseFail;
2619 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2620 if (!MCE) {
2621 Error(ExprLoc, "immediate value expected for barrier operand");
2622 return MatchOperand_ParseFail;
2623 }
2624 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2625 Error(ExprLoc, "barrier operand out of range");
2626 return MatchOperand_ParseFail;
2627 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002628 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2629 Operands.push_back(AArch64Operand::CreateBarrier(
2630 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002631 return MatchOperand_Success;
2632 }
2633
2634 if (Tok.isNot(AsmToken::Identifier)) {
2635 TokError("invalid operand for instruction");
2636 return MatchOperand_ParseFail;
2637 }
2638
Tim Northover3b0846e2014-05-24 12:50:23 +00002639 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002640 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2641 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002642 TokError("'sy' or #imm operand expected");
2643 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002644 } else if (!DB) {
2645 TokError("invalid barrier option name");
2646 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002647 }
2648
Tim Northovere6ae6762016-07-05 21:23:04 +00002649 Operands.push_back(AArch64Operand::CreateBarrier(
2650 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002651 Parser.Lex(); // Consume the option
2652
2653 return MatchOperand_Success;
2654}
2655
Alex Bradbury58eba092016-11-01 16:32:05 +00002656OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002657AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002658 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002659 const AsmToken &Tok = Parser.getTok();
2660
2661 if (Tok.isNot(AsmToken::Identifier))
2662 return MatchOperand_NoMatch;
2663
Tim Northovere6ae6762016-07-05 21:23:04 +00002664 int MRSReg, MSRReg;
2665 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2666 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2667 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2668 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2669 } else
2670 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002671
Tim Northovere6ae6762016-07-05 21:23:04 +00002672 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2673 unsigned PStateImm = -1;
2674 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2675 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002676
Tim Northovere6ae6762016-07-05 21:23:04 +00002677 Operands.push_back(
2678 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2679 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002680 Parser.Lex(); // Eat identifier
2681
2682 return MatchOperand_Success;
2683}
2684
Florian Hahnc4422242017-11-07 13:07:50 +00002685/// tryParseNeonVectorRegister - Parse a vector register operand.
2686bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002687 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002688 if (Parser.getTok().isNot(AsmToken::Identifier))
2689 return true;
2690
2691 SMLoc S = getLoc();
2692 // Check for a vector register specifier first.
2693 StringRef Kind;
2694 int64_t Reg = tryMatchVectorRegister(Kind, false);
2695 if (Reg == -1)
2696 return true;
2697 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00002698 AArch64Operand::CreateReg(Reg, RegKind::NeonVector, S, getLoc(),
2699 getContext()));
2700
Tim Northover3b0846e2014-05-24 12:50:23 +00002701 // If there was an explicit qualifier, that goes on as a literal text
2702 // operand.
2703 if (!Kind.empty())
2704 Operands.push_back(
2705 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2706
2707 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002708 SMLoc SIdx = getLoc();
2709 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002710 const MCExpr *ImmVal;
2711 if (getParser().parseExpression(ImmVal))
2712 return false;
2713 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2714 if (!MCE) {
2715 TokError("immediate value expected for vector index");
2716 return false;
2717 }
2718
2719 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002720
Nirav Davee833c6c2016-11-08 18:31:04 +00002721 if (parseToken(AsmToken::RBrac, "']' expected"))
2722 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002723
2724 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2725 E, getContext()));
2726 }
2727
2728 return false;
2729}
2730
Florian Hahn91f11e52017-11-07 16:45:48 +00002731// tryParseSVEDataVectorRegister - Try to parse a SVE vector register name with
2732// optional kind specifier. If it is a register specifier, eat the token
2733// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002734OperandMatchResultTy
2735AArch64AsmParser::tryParseSVERegister(int &Reg, StringRef &Kind,
2736 RegKind MatchKind) {
2737 MCAsmParser &Parser = getParser();
2738 const AsmToken &Tok = Parser.getTok();
2739
Florian Hahn91f11e52017-11-07 16:45:48 +00002740 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002741 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002742
2743 StringRef Name = Tok.getString();
2744 // If there is a kind specifier, it's separated from the register name by
2745 // a '.'.
2746 size_t Start = 0, Next = Name.find('.');
2747 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002748 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002749
2750 if (RegNum) {
2751 if (Next != StringRef::npos) {
2752 Kind = Name.slice(Next, StringRef::npos);
2753 if (!isValidSVEKind(Kind)) {
2754 TokError("invalid sve vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002755 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002756 }
2757 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002758 Parser.Lex(); // Eat the register token.
2759
2760 Reg = RegNum;
2761 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002762 }
2763
Sander de Smalen8e607342017-11-15 15:44:43 +00002764 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002765}
2766
Sander de Smalencd6be962017-12-20 11:02:42 +00002767/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2768OperandMatchResultTy
2769AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2770 // Check for a SVE predicate register specifier first.
2771 const SMLoc S = getLoc();
2772 StringRef Kind;
2773 int RegNum = -1;
2774 auto Res = tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
2775 if (Res != MatchOperand_Success)
2776 return Res;
2777
2778 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
2779 .Case("", -1)
2780 .Case(".b", 8)
2781 .Case(".h", 16)
2782 .Case(".s", 32)
2783 .Case(".d", 64)
2784 .Case(".q", 128)
2785 .Default(0);
2786
2787 if (!ElementWidth)
2788 return MatchOperand_NoMatch;
2789
2790 Operands.push_back(
2791 AArch64Operand::CreateReg(RegNum, RegKind::SVEPredicateVector,
2792 ElementWidth, S, getLoc(), getContext()));
2793
Sander de Smalen7868e742018-01-09 11:17:06 +00002794 // Not all predicates are followed by a '/m' or '/z'.
2795 MCAsmParser &Parser = getParser();
2796 if (Parser.getTok().isNot(AsmToken::Slash))
2797 return MatchOperand_Success;
2798
2799 // But when they do they shouldn't have an element type suffix.
2800 if (!Kind.empty()) {
2801 Error(S, "not expecting size suffix");
2802 return MatchOperand_ParseFail;
2803 }
2804
2805 // Add a literal slash as operand
2806 Operands.push_back(
2807 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2808
2809 Parser.Lex(); // Eat the slash.
2810
2811 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002812 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002813 if (Pred != "z" && Pred != "m") {
2814 Error(getLoc(), "expecting 'm' or 'z' predication");
2815 return MatchOperand_ParseFail;
2816 }
2817
2818 // Add zero/merge token.
2819 const char *ZM = Pred == "z" ? "z" : "m";
2820 Operands.push_back(
2821 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2822
2823 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002824 return MatchOperand_Success;
2825}
2826
Tim Northover3b0846e2014-05-24 12:50:23 +00002827/// parseRegister - Parse a non-vector register operand.
2828bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2829 SMLoc S = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00002830 // Try for a vector (neon) register.
2831 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002832 return false;
2833
2834 // Try for a scalar register.
2835 int64_t Reg = tryParseRegister();
2836 if (Reg == -1)
2837 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002838 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2839 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002840
Tim Northover3b0846e2014-05-24 12:50:23 +00002841 return false;
2842}
2843
2844bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002845 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002846 bool HasELFModifier = false;
2847 AArch64MCExpr::VariantKind RefKind;
2848
Nirav Davee833c6c2016-11-08 18:31:04 +00002849 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002850 HasELFModifier = true;
2851
Nirav Davee833c6c2016-11-08 18:31:04 +00002852 if (Parser.getTok().isNot(AsmToken::Identifier))
2853 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002854
2855 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2856 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2857 .Case("lo12", AArch64MCExpr::VK_LO12)
2858 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2859 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2860 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2861 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2862 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2863 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2864 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2865 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2866 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2867 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2868 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2869 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2870 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2871 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2872 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2873 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2874 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2875 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2876 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2877 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2878 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2879 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2880 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2881 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2882 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2883 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2884 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2885 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2886 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2887 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2888 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2889 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2890 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2891 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2892 .Default(AArch64MCExpr::VK_INVALID);
2893
Nirav Davee833c6c2016-11-08 18:31:04 +00002894 if (RefKind == AArch64MCExpr::VK_INVALID)
2895 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002896
2897 Parser.Lex(); // Eat identifier
2898
Nirav Davee833c6c2016-11-08 18:31:04 +00002899 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002900 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002901 }
2902
2903 if (getParser().parseExpression(ImmVal))
2904 return true;
2905
2906 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002907 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002908
2909 return false;
2910}
2911
2912/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2913bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002914 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002915 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2916 SMLoc S = getLoc();
2917 Parser.Lex(); // Eat left bracket token.
2918 StringRef Kind;
2919 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2920 if (FirstReg == -1)
2921 return true;
2922 int64_t PrevReg = FirstReg;
2923 unsigned Count = 1;
2924
Nirav Davee833c6c2016-11-08 18:31:04 +00002925 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002926 SMLoc Loc = getLoc();
2927 StringRef NextKind;
2928 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2929 if (Reg == -1)
2930 return true;
2931 // Any Kind suffices must match on all regs in the list.
2932 if (Kind != NextKind)
2933 return Error(Loc, "mismatched register size suffix");
2934
2935 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2936
2937 if (Space == 0 || Space > 3) {
2938 return Error(Loc, "invalid number of vectors");
2939 }
2940
2941 Count += Space;
2942 }
2943 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002944 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002945 SMLoc Loc = getLoc();
2946 StringRef NextKind;
2947 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2948 if (Reg == -1)
2949 return true;
2950 // Any Kind suffices must match on all regs in the list.
2951 if (Kind != NextKind)
2952 return Error(Loc, "mismatched register size suffix");
2953
2954 // Registers must be incremental (with wraparound at 31)
2955 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2956 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2957 return Error(Loc, "registers must be sequential");
2958
2959 PrevReg = Reg;
2960 ++Count;
2961 }
2962 }
2963
Nirav Davee833c6c2016-11-08 18:31:04 +00002964 if (parseToken(AsmToken::RCurly, "'}' expected"))
2965 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002966
2967 if (Count > 4)
2968 return Error(S, "invalid number of vectors");
2969
2970 unsigned NumElements = 0;
2971 char ElementKind = 0;
2972 if (!Kind.empty())
2973 parseValidVectorKind(Kind, NumElements, ElementKind);
2974
2975 Operands.push_back(AArch64Operand::CreateVectorList(
2976 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
2977
2978 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002979 SMLoc SIdx = getLoc();
2980 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002981 const MCExpr *ImmVal;
2982 if (getParser().parseExpression(ImmVal))
2983 return false;
2984 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2985 if (!MCE) {
2986 TokError("immediate value expected for vector index");
2987 return false;
2988 }
2989
2990 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002991 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002992 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002993
2994 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2995 E, getContext()));
2996 }
2997 return false;
2998}
2999
Alex Bradbury58eba092016-11-01 16:32:05 +00003000OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003001AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003002 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003003 const AsmToken &Tok = Parser.getTok();
3004 if (!Tok.is(AsmToken::Identifier))
3005 return MatchOperand_NoMatch;
3006
Florian Hahnc4422242017-11-07 13:07:50 +00003007 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00003008
3009 MCContext &Ctx = getContext();
3010 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
3011 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
3012 return MatchOperand_NoMatch;
3013
3014 SMLoc S = getLoc();
3015 Parser.Lex(); // Eat register
3016
Nirav Davee833c6c2016-11-08 18:31:04 +00003017 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003018 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003019 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003020 return MatchOperand_Success;
3021 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003022
Nirav Davee833c6c2016-11-08 18:31:04 +00003023 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003024
3025 if (Parser.getTok().isNot(AsmToken::Integer)) {
3026 Error(getLoc(), "index must be absent or #0");
3027 return MatchOperand_ParseFail;
3028 }
3029
3030 const MCExpr *ImmVal;
3031 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3032 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3033 Error(getLoc(), "index must be absent or #0");
3034 return MatchOperand_ParseFail;
3035 }
3036
3037 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003038 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003039 return MatchOperand_Success;
3040}
3041
3042/// parseOperand - Parse a arm instruction operand. For now this parses the
3043/// operand regardless of the mnemonic.
3044bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3045 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003046 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003047
3048 OperandMatchResultTy ResTy =
3049 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3050
Tim Northover3b0846e2014-05-24 12:50:23 +00003051 // Check if the current operand has a custom associated parser, if so, try to
3052 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003053 if (ResTy == MatchOperand_Success)
3054 return false;
3055 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3056 // there was a match, but an error occurred, in which case, just return that
3057 // the operand parsing failed.
3058 if (ResTy == MatchOperand_ParseFail)
3059 return true;
3060
3061 // Nothing custom, so do general case parsing.
3062 SMLoc S, E;
3063 switch (getLexer().getKind()) {
3064 default: {
3065 SMLoc S = getLoc();
3066 const MCExpr *Expr;
3067 if (parseSymbolicImmVal(Expr))
3068 return Error(S, "invalid operand");
3069
3070 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3071 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3072 return false;
3073 }
3074 case AsmToken::LBrac: {
3075 SMLoc Loc = Parser.getTok().getLoc();
3076 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3077 getContext()));
3078 Parser.Lex(); // Eat '['
3079
3080 // There's no comma after a '[', so we can parse the next operand
3081 // immediately.
3082 return parseOperand(Operands, false, false);
3083 }
3084 case AsmToken::LCurly:
3085 return parseVectorList(Operands);
3086 case AsmToken::Identifier: {
3087 // If we're expecting a Condition Code operand, then just parse that.
3088 if (isCondCode)
3089 return parseCondCode(Operands, invertCondCode);
3090
3091 // If it's a register name, parse it.
3092 if (!parseRegister(Operands))
3093 return false;
3094
3095 // This could be an optional "shift" or "extend" operand.
3096 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3097 // We can only continue if no tokens were eaten.
3098 if (GotShift != MatchOperand_NoMatch)
3099 return GotShift;
3100
3101 // This was not a register so parse other operands that start with an
3102 // identifier (like labels) as expressions and create them as immediates.
3103 const MCExpr *IdVal;
3104 S = getLoc();
3105 if (getParser().parseExpression(IdVal))
3106 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003107 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3108 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3109 return false;
3110 }
3111 case AsmToken::Integer:
3112 case AsmToken::Real:
3113 case AsmToken::Hash: {
3114 // #42 -> immediate.
3115 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003116
3117 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003118
3119 // Parse a negative sign
3120 bool isNegative = false;
3121 if (Parser.getTok().is(AsmToken::Minus)) {
3122 isNegative = true;
3123 // We need to consume this token only when we have a Real, otherwise
3124 // we let parseSymbolicImmVal take care of it
3125 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3126 Parser.Lex();
3127 }
3128
3129 // The only Real that should come through here is a literal #0.0 for
3130 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3131 // so convert the value.
3132 const AsmToken &Tok = Parser.getTok();
3133 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003134 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003135 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3136 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3137 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3138 Mnemonic != "fcmlt")
3139 return TokError("unexpected floating point literal");
3140 else if (IntVal != 0 || isNegative)
3141 return TokError("expected floating-point constant #0.0");
3142 Parser.Lex(); // Eat the token.
3143
3144 Operands.push_back(
3145 AArch64Operand::CreateToken("#0", false, S, getContext()));
3146 Operands.push_back(
3147 AArch64Operand::CreateToken(".0", false, S, getContext()));
3148 return false;
3149 }
3150
3151 const MCExpr *ImmVal;
3152 if (parseSymbolicImmVal(ImmVal))
3153 return true;
3154
3155 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3156 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3157 return false;
3158 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003159 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003160 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003161 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003162 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003163 Parser.Lex(); // Eat '='
3164 const MCExpr *SubExprVal;
3165 if (getParser().parseExpression(SubExprVal))
3166 return true;
3167
David Peixottoae5ba762014-07-18 16:05:14 +00003168 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003169 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003170 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003171
3172 bool IsXReg =
3173 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3174 Operands[1]->getReg());
3175
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003176 MCContext& Ctx = getContext();
3177 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3178 // 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 +00003179 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003180 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3181 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3182 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3183 ShiftAmt += 16;
3184 Imm >>= 16;
3185 }
3186 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3187 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3188 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003189 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003190 if (ShiftAmt)
3191 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3192 ShiftAmt, true, S, E, Ctx));
3193 return false;
3194 }
David Peixottoae5ba762014-07-18 16:05:14 +00003195 APInt Simm = APInt(64, Imm << ShiftAmt);
3196 // check if the immediate is an unsigned or signed 32-bit int for W regs
3197 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3198 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003199 }
3200 // 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 +00003201 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003202 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003203 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3204 return false;
3205 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003206 }
3207}
3208
3209/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3210/// operands.
3211bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3212 StringRef Name, SMLoc NameLoc,
3213 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003214 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003215 Name = StringSwitch<StringRef>(Name.lower())
3216 .Case("beq", "b.eq")
3217 .Case("bne", "b.ne")
3218 .Case("bhs", "b.hs")
3219 .Case("bcs", "b.cs")
3220 .Case("blo", "b.lo")
3221 .Case("bcc", "b.cc")
3222 .Case("bmi", "b.mi")
3223 .Case("bpl", "b.pl")
3224 .Case("bvs", "b.vs")
3225 .Case("bvc", "b.vc")
3226 .Case("bhi", "b.hi")
3227 .Case("bls", "b.ls")
3228 .Case("bge", "b.ge")
3229 .Case("blt", "b.lt")
3230 .Case("bgt", "b.gt")
3231 .Case("ble", "b.le")
3232 .Case("bal", "b.al")
3233 .Case("bnv", "b.nv")
3234 .Default(Name);
3235
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003236 // First check for the AArch64-specific .req directive.
3237 if (Parser.getTok().is(AsmToken::Identifier) &&
3238 Parser.getTok().getIdentifier() == ".req") {
3239 parseDirectiveReq(Name, NameLoc);
3240 // We always return 'error' for this, as we're done with this
3241 // statement and don't need to match the 'instruction."
3242 return true;
3243 }
3244
Tim Northover3b0846e2014-05-24 12:50:23 +00003245 // Create the leading tokens for the mnemonic, split by '.' characters.
3246 size_t Start = 0, Next = Name.find('.');
3247 StringRef Head = Name.slice(Start, Next);
3248
3249 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003250 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3251 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003252
3253 Operands.push_back(
3254 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3255 Mnemonic = Head;
3256
3257 // Handle condition codes for a branch mnemonic
3258 if (Head == "b" && Next != StringRef::npos) {
3259 Start = Next;
3260 Next = Name.find('.', Start + 1);
3261 Head = Name.slice(Start + 1, Next);
3262
3263 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3264 (Head.data() - Name.data()));
3265 AArch64CC::CondCode CC = parseCondCodeString(Head);
3266 if (CC == AArch64CC::Invalid)
3267 return Error(SuffixLoc, "invalid condition code");
3268 Operands.push_back(
3269 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3270 Operands.push_back(
3271 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3272 }
3273
3274 // Add the remaining tokens in the mnemonic.
3275 while (Next != StringRef::npos) {
3276 Start = Next;
3277 Next = Name.find('.', Start + 1);
3278 Head = Name.slice(Start, Next);
3279 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3280 (Head.data() - Name.data()) + 1);
3281 Operands.push_back(
3282 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3283 }
3284
3285 // Conditional compare instructions have a Condition Code operand, which needs
3286 // to be parsed and an immediate operand created.
3287 bool condCodeFourthOperand =
3288 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3289 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3290 Head == "csinc" || Head == "csinv" || Head == "csneg");
3291
3292 // These instructions are aliases to some of the conditional select
3293 // instructions. However, the condition code is inverted in the aliased
3294 // instruction.
3295 //
3296 // FIXME: Is this the correct way to handle these? Or should the parser
3297 // generate the aliased instructions directly?
3298 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3299 bool condCodeThirdOperand =
3300 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3301
3302 // Read the remaining operands.
3303 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3304 // Read the first operand.
3305 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003306 return true;
3307 }
3308
3309 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003310 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003311 // Parse and remember the operand.
3312 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3313 (N == 3 && condCodeThirdOperand) ||
3314 (N == 2 && condCodeSecondOperand),
3315 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003316 return true;
3317 }
3318
3319 // After successfully parsing some operands there are two special cases to
3320 // consider (i.e. notional operands not separated by commas). Both are due
3321 // to memory specifiers:
3322 // + An RBrac will end an address for load/store/prefetch
3323 // + An '!' will indicate a pre-indexed operation.
3324 //
3325 // It's someone else's responsibility to make sure these tokens are sane
3326 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003327
Nirav Davee833c6c2016-11-08 18:31:04 +00003328 SMLoc RLoc = Parser.getTok().getLoc();
3329 if (parseOptionalToken(AsmToken::RBrac))
3330 Operands.push_back(
3331 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3332 SMLoc ELoc = Parser.getTok().getLoc();
3333 if (parseOptionalToken(AsmToken::Exclaim))
3334 Operands.push_back(
3335 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003336
3337 ++N;
3338 }
3339 }
3340
Nirav Davee833c6c2016-11-08 18:31:04 +00003341 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3342 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003343
Tim Northover3b0846e2014-05-24 12:50:23 +00003344 return false;
3345}
3346
3347// FIXME: This entire function is a giant hack to provide us with decent
3348// operand range validation/diagnostics until TableGen/MC can be extended
3349// to support autogeneration of this kind of validation.
3350bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3351 SmallVectorImpl<SMLoc> &Loc) {
3352 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3353 // Check for indexed addressing modes w/ the base register being the
3354 // same as a destination/source register or pair load where
3355 // the Rt == Rt2. All of those are undefined behaviour.
3356 switch (Inst.getOpcode()) {
3357 case AArch64::LDPSWpre:
3358 case AArch64::LDPWpost:
3359 case AArch64::LDPWpre:
3360 case AArch64::LDPXpost:
3361 case AArch64::LDPXpre: {
3362 unsigned Rt = Inst.getOperand(1).getReg();
3363 unsigned Rt2 = Inst.getOperand(2).getReg();
3364 unsigned Rn = Inst.getOperand(3).getReg();
3365 if (RI->isSubRegisterEq(Rn, Rt))
3366 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3367 "is also a destination");
3368 if (RI->isSubRegisterEq(Rn, Rt2))
3369 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3370 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003371 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003372 }
3373 case AArch64::LDPDi:
3374 case AArch64::LDPQi:
3375 case AArch64::LDPSi:
3376 case AArch64::LDPSWi:
3377 case AArch64::LDPWi:
3378 case AArch64::LDPXi: {
3379 unsigned Rt = Inst.getOperand(0).getReg();
3380 unsigned Rt2 = Inst.getOperand(1).getReg();
3381 if (Rt == Rt2)
3382 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3383 break;
3384 }
3385 case AArch64::LDPDpost:
3386 case AArch64::LDPDpre:
3387 case AArch64::LDPQpost:
3388 case AArch64::LDPQpre:
3389 case AArch64::LDPSpost:
3390 case AArch64::LDPSpre:
3391 case AArch64::LDPSWpost: {
3392 unsigned Rt = Inst.getOperand(1).getReg();
3393 unsigned Rt2 = Inst.getOperand(2).getReg();
3394 if (Rt == Rt2)
3395 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3396 break;
3397 }
3398 case AArch64::STPDpost:
3399 case AArch64::STPDpre:
3400 case AArch64::STPQpost:
3401 case AArch64::STPQpre:
3402 case AArch64::STPSpost:
3403 case AArch64::STPSpre:
3404 case AArch64::STPWpost:
3405 case AArch64::STPWpre:
3406 case AArch64::STPXpost:
3407 case AArch64::STPXpre: {
3408 unsigned Rt = Inst.getOperand(1).getReg();
3409 unsigned Rt2 = Inst.getOperand(2).getReg();
3410 unsigned Rn = Inst.getOperand(3).getReg();
3411 if (RI->isSubRegisterEq(Rn, Rt))
3412 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3413 "is also a source");
3414 if (RI->isSubRegisterEq(Rn, Rt2))
3415 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3416 "is also a source");
3417 break;
3418 }
3419 case AArch64::LDRBBpre:
3420 case AArch64::LDRBpre:
3421 case AArch64::LDRHHpre:
3422 case AArch64::LDRHpre:
3423 case AArch64::LDRSBWpre:
3424 case AArch64::LDRSBXpre:
3425 case AArch64::LDRSHWpre:
3426 case AArch64::LDRSHXpre:
3427 case AArch64::LDRSWpre:
3428 case AArch64::LDRWpre:
3429 case AArch64::LDRXpre:
3430 case AArch64::LDRBBpost:
3431 case AArch64::LDRBpost:
3432 case AArch64::LDRHHpost:
3433 case AArch64::LDRHpost:
3434 case AArch64::LDRSBWpost:
3435 case AArch64::LDRSBXpost:
3436 case AArch64::LDRSHWpost:
3437 case AArch64::LDRSHXpost:
3438 case AArch64::LDRSWpost:
3439 case AArch64::LDRWpost:
3440 case AArch64::LDRXpost: {
3441 unsigned Rt = Inst.getOperand(1).getReg();
3442 unsigned Rn = Inst.getOperand(2).getReg();
3443 if (RI->isSubRegisterEq(Rn, Rt))
3444 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3445 "is also a source");
3446 break;
3447 }
3448 case AArch64::STRBBpost:
3449 case AArch64::STRBpost:
3450 case AArch64::STRHHpost:
3451 case AArch64::STRHpost:
3452 case AArch64::STRWpost:
3453 case AArch64::STRXpost:
3454 case AArch64::STRBBpre:
3455 case AArch64::STRBpre:
3456 case AArch64::STRHHpre:
3457 case AArch64::STRHpre:
3458 case AArch64::STRWpre:
3459 case AArch64::STRXpre: {
3460 unsigned Rt = Inst.getOperand(1).getReg();
3461 unsigned Rn = Inst.getOperand(2).getReg();
3462 if (RI->isSubRegisterEq(Rn, Rt))
3463 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3464 "is also a source");
3465 break;
3466 }
3467 }
3468
3469 // Now check immediate ranges. Separate from the above as there is overlap
3470 // in the instructions being checked and this keeps the nested conditionals
3471 // to a minimum.
3472 switch (Inst.getOpcode()) {
3473 case AArch64::ADDSWri:
3474 case AArch64::ADDSXri:
3475 case AArch64::ADDWri:
3476 case AArch64::ADDXri:
3477 case AArch64::SUBSWri:
3478 case AArch64::SUBSXri:
3479 case AArch64::SUBWri:
3480 case AArch64::SUBXri: {
3481 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3482 // some slight duplication here.
3483 if (Inst.getOperand(2).isExpr()) {
3484 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3485 AArch64MCExpr::VariantKind ELFRefKind;
3486 MCSymbolRefExpr::VariantKind DarwinRefKind;
3487 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003488 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3489
3490 // Only allow these with ADDXri.
3491 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3492 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3493 Inst.getOpcode() == AArch64::ADDXri)
3494 return false;
3495
3496 // Only allow these with ADDXri/ADDWri
3497 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3498 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3499 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3500 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3501 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3502 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3503 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3504 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3505 (Inst.getOpcode() == AArch64::ADDXri ||
3506 Inst.getOpcode() == AArch64::ADDWri))
3507 return false;
3508
3509 // Don't allow symbol refs in the immediate field otherwise
3510 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3511 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3512 // 'cmp w0, 'borked')
3513 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003514 }
Diana Picusc93518d2016-10-11 09:17:47 +00003515 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003516 }
3517 return false;
3518 }
3519 default:
3520 return false;
3521 }
3522}
3523
Craig Topper05515562017-10-26 06:46:41 +00003524static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3525 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003526
3527bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3528 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003529 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003530 case Match_InvalidTiedOperand:
3531 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003532 case Match_MissingFeature:
3533 return Error(Loc,
3534 "instruction requires a CPU feature not currently enabled");
3535 case Match_InvalidOperand:
3536 return Error(Loc, "invalid operand for instruction");
3537 case Match_InvalidSuffix:
3538 return Error(Loc, "invalid type suffix for instruction");
3539 case Match_InvalidCondCode:
3540 return Error(Loc, "expected AArch64 condition code");
3541 case Match_AddSubRegExtendSmall:
3542 return Error(Loc,
3543 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3544 case Match_AddSubRegExtendLarge:
3545 return Error(Loc,
3546 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3547 case Match_AddSubSecondSource:
3548 return Error(Loc,
3549 "expected compatible register, symbol or integer in range [0, 4095]");
3550 case Match_LogicalSecondSource:
3551 return Error(Loc, "expected compatible register or logical immediate");
3552 case Match_InvalidMovImm32Shift:
3553 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3554 case Match_InvalidMovImm64Shift:
3555 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3556 case Match_AddSubRegShift32:
3557 return Error(Loc,
3558 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3559 case Match_AddSubRegShift64:
3560 return Error(Loc,
3561 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3562 case Match_InvalidFPImm:
3563 return Error(Loc,
3564 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003565 case Match_InvalidMemoryIndexedSImm6:
3566 return Error(Loc, "index must be an integer in range [-32, 31].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003567 case Match_InvalidMemoryIndexedSImm9:
3568 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003569 case Match_InvalidMemoryIndexedSImm10:
3570 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003571 case Match_InvalidMemoryIndexed4SImm7:
3572 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3573 case Match_InvalidMemoryIndexed8SImm7:
3574 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3575 case Match_InvalidMemoryIndexed16SImm7:
3576 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3577 case Match_InvalidMemoryWExtend8:
3578 return Error(Loc,
3579 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3580 case Match_InvalidMemoryWExtend16:
3581 return Error(Loc,
3582 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3583 case Match_InvalidMemoryWExtend32:
3584 return Error(Loc,
3585 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3586 case Match_InvalidMemoryWExtend64:
3587 return Error(Loc,
3588 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3589 case Match_InvalidMemoryWExtend128:
3590 return Error(Loc,
3591 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3592 case Match_InvalidMemoryXExtend8:
3593 return Error(Loc,
3594 "expected 'lsl' or 'sxtx' with optional shift of #0");
3595 case Match_InvalidMemoryXExtend16:
3596 return Error(Loc,
3597 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3598 case Match_InvalidMemoryXExtend32:
3599 return Error(Loc,
3600 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3601 case Match_InvalidMemoryXExtend64:
3602 return Error(Loc,
3603 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3604 case Match_InvalidMemoryXExtend128:
3605 return Error(Loc,
3606 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3607 case Match_InvalidMemoryIndexed1:
3608 return Error(Loc, "index must be an integer in range [0, 4095].");
3609 case Match_InvalidMemoryIndexed2:
3610 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3611 case Match_InvalidMemoryIndexed4:
3612 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3613 case Match_InvalidMemoryIndexed8:
3614 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3615 case Match_InvalidMemoryIndexed16:
3616 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003617 case Match_InvalidImm0_1:
3618 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003619 case Match_InvalidImm0_7:
3620 return Error(Loc, "immediate must be an integer in range [0, 7].");
3621 case Match_InvalidImm0_15:
3622 return Error(Loc, "immediate must be an integer in range [0, 15].");
3623 case Match_InvalidImm0_31:
3624 return Error(Loc, "immediate must be an integer in range [0, 31].");
3625 case Match_InvalidImm0_63:
3626 return Error(Loc, "immediate must be an integer in range [0, 63].");
3627 case Match_InvalidImm0_127:
3628 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003629 case Match_InvalidImm0_255:
3630 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003631 case Match_InvalidImm0_65535:
3632 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3633 case Match_InvalidImm1_8:
3634 return Error(Loc, "immediate must be an integer in range [1, 8].");
3635 case Match_InvalidImm1_16:
3636 return Error(Loc, "immediate must be an integer in range [1, 16].");
3637 case Match_InvalidImm1_32:
3638 return Error(Loc, "immediate must be an integer in range [1, 32].");
3639 case Match_InvalidImm1_64:
3640 return Error(Loc, "immediate must be an integer in range [1, 64].");
3641 case Match_InvalidIndex1:
3642 return Error(Loc, "expected lane specifier '[1]'");
3643 case Match_InvalidIndexB:
3644 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3645 case Match_InvalidIndexH:
3646 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3647 case Match_InvalidIndexS:
3648 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3649 case Match_InvalidIndexD:
3650 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3651 case Match_InvalidLabel:
3652 return Error(Loc, "expected label or encodable integer pc offset");
3653 case Match_MRS:
3654 return Error(Loc, "expected readable system register");
3655 case Match_MSR:
3656 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003657 case Match_InvalidComplexRotationEven:
3658 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3659 case Match_InvalidComplexRotationOdd:
3660 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003661 case Match_MnemonicFail: {
3662 std::string Suggestion = AArch64MnemonicSpellCheck(
3663 ((AArch64Operand &)*Operands[0]).getToken(),
3664 ComputeAvailableFeatures(STI->getFeatureBits()));
3665 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3666 }
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003667 case Match_InvalidSVEPattern:
3668 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003669 case Match_InvalidSVEPredicateAnyReg:
3670 case Match_InvalidSVEPredicateBReg:
3671 case Match_InvalidSVEPredicateHReg:
3672 case Match_InvalidSVEPredicateSReg:
3673 case Match_InvalidSVEPredicateDReg:
3674 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003675 case Match_InvalidSVEPredicate3bAnyReg:
3676 case Match_InvalidSVEPredicate3bBReg:
3677 case Match_InvalidSVEPredicate3bHReg:
3678 case Match_InvalidSVEPredicate3bSReg:
3679 case Match_InvalidSVEPredicate3bDReg:
3680 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003681 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003682 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003683 }
3684}
3685
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003686static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003687
3688bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3689 OperandVector &Operands,
3690 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003691 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003692 bool MatchingInlineAsm) {
3693 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003694 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3695 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003696
David Blaikie960ea3f2014-06-08 16:18:35 +00003697 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003698 unsigned NumOperands = Operands.size();
3699
3700 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003701 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3702 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003703 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003704 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003705 if (Op3CE) {
3706 uint64_t Op3Val = Op3CE->getValue();
3707 uint64_t NewOp3Val = 0;
3708 uint64_t NewOp4Val = 0;
3709 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003710 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003711 NewOp3Val = (32 - Op3Val) & 0x1f;
3712 NewOp4Val = 31 - Op3Val;
3713 } else {
3714 NewOp3Val = (64 - Op3Val) & 0x3f;
3715 NewOp4Val = 63 - Op3Val;
3716 }
3717
Jim Grosbach13760bd2015-05-30 01:25:56 +00003718 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3719 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003720
3721 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003722 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003723 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003724 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3725 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3726 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003727 }
3728 }
Tim Northover03b99f62015-04-30 18:28:58 +00003729 } else if (NumOperands == 4 && Tok == "bfc") {
3730 // FIXME: Horrible hack to handle BFC->BFM alias.
3731 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3732 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3733 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3734
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003735 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003736 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3737 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3738
3739 if (LSBCE && WidthCE) {
3740 uint64_t LSB = LSBCE->getValue();
3741 uint64_t Width = WidthCE->getValue();
3742
3743 uint64_t RegWidth = 0;
3744 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3745 Op1.getReg()))
3746 RegWidth = 64;
3747 else
3748 RegWidth = 32;
3749
3750 if (LSB >= RegWidth)
3751 return Error(LSBOp.getStartLoc(),
3752 "expected integer in range [0, 31]");
3753 if (Width < 1 || Width > RegWidth)
3754 return Error(WidthOp.getStartLoc(),
3755 "expected integer in range [1, 32]");
3756
3757 uint64_t ImmR = 0;
3758 if (RegWidth == 32)
3759 ImmR = (32 - LSB) & 0x1f;
3760 else
3761 ImmR = (64 - LSB) & 0x3f;
3762
3763 uint64_t ImmS = Width - 1;
3764
3765 if (ImmR != 0 && ImmS >= ImmR)
3766 return Error(WidthOp.getStartLoc(),
3767 "requested insert overflows register");
3768
Jim Grosbach13760bd2015-05-30 01:25:56 +00003769 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3770 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003771 Operands[0] = AArch64Operand::CreateToken(
3772 "bfm", false, Op.getStartLoc(), getContext());
3773 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003774 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3775 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003776 Operands[3] = AArch64Operand::CreateImm(
3777 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3778 Operands.emplace_back(
3779 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3780 WidthOp.getEndLoc(), getContext()));
3781 }
3782 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003783 } else if (NumOperands == 5) {
3784 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3785 // UBFIZ -> UBFM aliases.
3786 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003787 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3788 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3789 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003790
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003791 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003792 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3793 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003794
3795 if (Op3CE && Op4CE) {
3796 uint64_t Op3Val = Op3CE->getValue();
3797 uint64_t Op4Val = Op4CE->getValue();
3798
3799 uint64_t RegWidth = 0;
3800 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003801 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003802 RegWidth = 64;
3803 else
3804 RegWidth = 32;
3805
3806 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003807 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003808 "expected integer in range [0, 31]");
3809 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003810 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003811 "expected integer in range [1, 32]");
3812
3813 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003814 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003815 NewOp3Val = (32 - Op3Val) & 0x1f;
3816 else
3817 NewOp3Val = (64 - Op3Val) & 0x3f;
3818
3819 uint64_t NewOp4Val = Op4Val - 1;
3820
3821 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003822 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003823 "requested insert overflows register");
3824
3825 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003826 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003827 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003828 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003829 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003830 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003831 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003832 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003833 if (Tok == "bfi")
3834 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003835 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003836 else if (Tok == "sbfiz")
3837 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003838 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003839 else if (Tok == "ubfiz")
3840 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003841 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003842 else
3843 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003844 }
3845 }
3846
3847 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3848 // UBFX -> UBFM aliases.
3849 } else if (NumOperands == 5 &&
3850 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003851 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3852 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3853 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003854
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003855 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003856 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3857 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003858
3859 if (Op3CE && Op4CE) {
3860 uint64_t Op3Val = Op3CE->getValue();
3861 uint64_t Op4Val = Op4CE->getValue();
3862
3863 uint64_t RegWidth = 0;
3864 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003865 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003866 RegWidth = 64;
3867 else
3868 RegWidth = 32;
3869
3870 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003871 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003872 "expected integer in range [0, 31]");
3873 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003874 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003875 "expected integer in range [1, 32]");
3876
3877 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3878
3879 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003880 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003881 "requested extract overflows register");
3882
3883 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003884 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003885 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003886 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003887 if (Tok == "bfxil")
3888 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003889 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003890 else if (Tok == "sbfx")
3891 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003892 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003893 else if (Tok == "ubfx")
3894 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003895 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003896 else
3897 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003898 }
3899 }
3900 }
3901 }
Tim Northover9097a072017-12-18 10:36:00 +00003902
3903 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
3904 // instruction for FP registers correctly in some rare circumstances. Convert
3905 // it to a safe instruction and warn (because silently changing someone's
3906 // assembly is rude).
3907 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
3908 NumOperands == 4 && Tok == "movi") {
3909 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3910 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3911 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3912 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
3913 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
3914 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
3915 if (Suffix.lower() == ".2d" &&
3916 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
3917 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
3918 " correctly on this CPU, converting to equivalent movi.16b");
3919 // Switch the suffix to .16b.
3920 unsigned Idx = Op1.isToken() ? 1 : 2;
3921 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
3922 getContext());
3923 }
3924 }
3925 }
3926
Tim Northover3b0846e2014-05-24 12:50:23 +00003927 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3928 // InstAlias can't quite handle this since the reg classes aren't
3929 // subclasses.
3930 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3931 // The source register can be Wn here, but the matcher expects a
3932 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003933 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003934 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003935 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003936 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3937 Op.getStartLoc(), Op.getEndLoc(),
3938 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003939 }
3940 }
3941 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3942 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003943 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003944 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003945 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003946 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003947 // The source register can be Wn here, but the matcher expects a
3948 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003949 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003950 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003951 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003952 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3953 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003954 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003955 }
3956 }
3957 }
3958 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3959 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003960 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003961 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003962 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003963 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003964 // The source register can be Wn here, but the matcher expects a
3965 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003966 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003967 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003968 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003969 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3970 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003971 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003972 }
3973 }
3974 }
3975
Tim Northover3b0846e2014-05-24 12:50:23 +00003976 MCInst Inst;
3977 // First try to match against the secondary set of tables containing the
3978 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3979 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003980 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003981
3982 // If that fails, try against the alternate table containing long-form NEON:
3983 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003984 if (MatchResult != Match_Success) {
3985 // But first, save the short-form match result: we can use it in case the
3986 // long-form match also fails.
3987 auto ShortFormNEONErrorInfo = ErrorInfo;
3988 auto ShortFormNEONMatchResult = MatchResult;
3989
Tim Northover3b0846e2014-05-24 12:50:23 +00003990 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003991 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003992
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003993 // Now, both matches failed, and the long-form match failed on the mnemonic
3994 // suffix token operand. The short-form match failure is probably more
3995 // relevant: use it instead.
3996 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003997 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003998 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3999 MatchResult = ShortFormNEONMatchResult;
4000 ErrorInfo = ShortFormNEONErrorInfo;
4001 }
4002 }
4003
Tim Northover3b0846e2014-05-24 12:50:23 +00004004 switch (MatchResult) {
4005 case Match_Success: {
4006 // Perform range checking and other semantic validations
4007 SmallVector<SMLoc, 8> OperandLocs;
4008 NumOperands = Operands.size();
4009 for (unsigned i = 1; i < NumOperands; ++i)
4010 OperandLocs.push_back(Operands[i]->getStartLoc());
4011 if (validateInstruction(Inst, OperandLocs))
4012 return true;
4013
4014 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004015 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004016 return false;
4017 }
4018 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004019 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004020 // Special case the error message for the very common case where only
4021 // a single subtarget feature is missing (neon, e.g.).
4022 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004023 uint64_t Mask = 1;
4024 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4025 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004026 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004027 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004028 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004029 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004030 }
4031 return Error(IDLoc, Msg);
4032 }
4033 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004034 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004035 case Match_InvalidOperand: {
4036 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004037
Tim Northover26bb14e2014-08-18 11:49:42 +00004038 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004039 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004040 return Error(IDLoc, "too few operands for instruction",
4041 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004042
David Blaikie960ea3f2014-06-08 16:18:35 +00004043 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004044 if (ErrorLoc == SMLoc())
4045 ErrorLoc = IDLoc;
4046 }
4047 // If the match failed on a suffix token operand, tweak the diagnostic
4048 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004049 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4050 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004051 MatchResult = Match_InvalidSuffix;
4052
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004053 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004054 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004055 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004056 case Match_InvalidMemoryIndexed1:
4057 case Match_InvalidMemoryIndexed2:
4058 case Match_InvalidMemoryIndexed4:
4059 case Match_InvalidMemoryIndexed8:
4060 case Match_InvalidMemoryIndexed16:
4061 case Match_InvalidCondCode:
4062 case Match_AddSubRegExtendSmall:
4063 case Match_AddSubRegExtendLarge:
4064 case Match_AddSubSecondSource:
4065 case Match_LogicalSecondSource:
4066 case Match_AddSubRegShift32:
4067 case Match_AddSubRegShift64:
4068 case Match_InvalidMovImm32Shift:
4069 case Match_InvalidMovImm64Shift:
4070 case Match_InvalidFPImm:
4071 case Match_InvalidMemoryWExtend8:
4072 case Match_InvalidMemoryWExtend16:
4073 case Match_InvalidMemoryWExtend32:
4074 case Match_InvalidMemoryWExtend64:
4075 case Match_InvalidMemoryWExtend128:
4076 case Match_InvalidMemoryXExtend8:
4077 case Match_InvalidMemoryXExtend16:
4078 case Match_InvalidMemoryXExtend32:
4079 case Match_InvalidMemoryXExtend64:
4080 case Match_InvalidMemoryXExtend128:
Sander de Smalen909cf952018-01-19 15:22:00 +00004081 case Match_InvalidMemoryIndexedSImm6:
Tim Northover3b0846e2014-05-24 12:50:23 +00004082 case Match_InvalidMemoryIndexed4SImm7:
4083 case Match_InvalidMemoryIndexed8SImm7:
4084 case Match_InvalidMemoryIndexed16SImm7:
4085 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004086 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004087 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004088 case Match_InvalidImm0_7:
4089 case Match_InvalidImm0_15:
4090 case Match_InvalidImm0_31:
4091 case Match_InvalidImm0_63:
4092 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004093 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004094 case Match_InvalidImm0_65535:
4095 case Match_InvalidImm1_8:
4096 case Match_InvalidImm1_16:
4097 case Match_InvalidImm1_32:
4098 case Match_InvalidImm1_64:
4099 case Match_InvalidIndex1:
4100 case Match_InvalidIndexB:
4101 case Match_InvalidIndexH:
4102 case Match_InvalidIndexS:
4103 case Match_InvalidIndexD:
4104 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004105 case Match_InvalidComplexRotationEven:
4106 case Match_InvalidComplexRotationOdd:
Sander de Smalencd6be962017-12-20 11:02:42 +00004107 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004108 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004109 case Match_InvalidSVEPredicateBReg:
4110 case Match_InvalidSVEPredicateHReg:
4111 case Match_InvalidSVEPredicateSReg:
4112 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004113 case Match_InvalidSVEPredicate3bAnyReg:
4114 case Match_InvalidSVEPredicate3bBReg:
4115 case Match_InvalidSVEPredicate3bHReg:
4116 case Match_InvalidSVEPredicate3bSReg:
4117 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004118 case Match_MSR:
4119 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004120 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004121 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004122 // Any time we get here, there's nothing fancy to do. Just get the
4123 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004124 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004125 if (ErrorLoc == SMLoc())
4126 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004127 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004128 }
4129 }
4130
4131 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004132}
4133
4134/// ParseDirective parses the arm specific directives
4135bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004136 const MCObjectFileInfo::Environment Format =
4137 getContext().getObjectFileInfo()->getObjectFileType();
4138 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4139 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004140
Tim Northover3b0846e2014-05-24 12:50:23 +00004141 StringRef IDVal = DirectiveID.getIdentifier();
4142 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004143 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004144 parseDirectiveArch(Loc);
4145 else if (IDVal == ".cpu")
4146 parseDirectiveCPU(Loc);
4147 else if (IDVal == ".hword")
4148 parseDirectiveWord(2, Loc);
4149 else if (IDVal == ".word")
4150 parseDirectiveWord(4, Loc);
4151 else if (IDVal == ".xword")
4152 parseDirectiveWord(8, Loc);
4153 else if (IDVal == ".tlsdesccall")
4154 parseDirectiveTLSDescCall(Loc);
4155 else if (IDVal == ".ltorg" || IDVal == ".pool")
4156 parseDirectiveLtorg(Loc);
4157 else if (IDVal == ".unreq")
4158 parseDirectiveUnreq(Loc);
4159 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004160 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004161 parseDirectiveInst(Loc);
4162 else
4163 return true;
4164 } else if (IDVal == MCLOHDirectiveName())
4165 parseDirectiveLOH(IDVal, Loc);
4166 else
4167 return true;
4168 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004169}
4170
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004171static const struct {
4172 const char *Name;
4173 const FeatureBitset Features;
4174} ExtensionMap[] = {
4175 { "crc", {AArch64::FeatureCRC} },
4176 { "crypto", {AArch64::FeatureCrypto} },
4177 { "fp", {AArch64::FeatureFPARMv8} },
4178 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004179 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004180 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004181
4182 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004183 { "pan", {} },
4184 { "lor", {} },
4185 { "rdma", {} },
4186 { "profile", {} },
4187};
4188
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004189/// parseDirectiveArch
4190/// ::= .arch token
4191bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4192 SMLoc ArchLoc = getLoc();
4193
4194 StringRef Arch, ExtensionString;
4195 std::tie(Arch, ExtensionString) =
4196 getParser().parseStringToEndOfStatement().trim().split('+');
4197
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004198 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4199 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004200 return Error(ArchLoc, "unknown arch name");
4201
4202 if (parseToken(AsmToken::EndOfStatement))
4203 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004204
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004205 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004206 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004207 AArch64::getArchFeatures(ID, AArch64Features);
4208 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4209 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004210
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004211 MCSubtargetInfo &STI = copySTI();
4212 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4213 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4214
4215 SmallVector<StringRef, 4> RequestedExtensions;
4216 if (!ExtensionString.empty())
4217 ExtensionString.split(RequestedExtensions, '+');
4218
4219 FeatureBitset Features = STI.getFeatureBits();
4220 for (auto Name : RequestedExtensions) {
4221 bool EnableFeature = true;
4222
4223 if (Name.startswith_lower("no")) {
4224 EnableFeature = false;
4225 Name = Name.substr(2);
4226 }
4227
4228 for (const auto &Extension : ExtensionMap) {
4229 if (Extension.Name != Name)
4230 continue;
4231
4232 if (Extension.Features.none())
4233 report_fatal_error("unsupported architectural extension: " + Name);
4234
4235 FeatureBitset ToggleFeatures = EnableFeature
4236 ? (~Features & Extension.Features)
4237 : ( Features & Extension.Features);
4238 uint64_t Features =
4239 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4240 setAvailableFeatures(Features);
4241 break;
4242 }
4243 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004244 return false;
4245}
4246
Tim Northover8b96c7e2017-05-15 19:42:15 +00004247static SMLoc incrementLoc(SMLoc L, int Offset) {
4248 return SMLoc::getFromPointer(L.getPointer() + Offset);
4249}
4250
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004251/// parseDirectiveCPU
4252/// ::= .cpu id
4253bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004254 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004255
4256 StringRef CPU, ExtensionString;
4257 std::tie(CPU, ExtensionString) =
4258 getParser().parseStringToEndOfStatement().trim().split('+');
4259
Nirav Davee833c6c2016-11-08 18:31:04 +00004260 if (parseToken(AsmToken::EndOfStatement))
4261 return true;
4262
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004263 SmallVector<StringRef, 4> RequestedExtensions;
4264 if (!ExtensionString.empty())
4265 ExtensionString.split(RequestedExtensions, '+');
4266
4267 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4268 // once that is tablegen'ed
4269 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004270 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004271 return false;
4272 }
4273
4274 MCSubtargetInfo &STI = copySTI();
4275 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004276 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004277
4278 FeatureBitset Features = STI.getFeatureBits();
4279 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004280 // Advance source location past '+'.
4281 CurLoc = incrementLoc(CurLoc, 1);
4282
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004283 bool EnableFeature = true;
4284
4285 if (Name.startswith_lower("no")) {
4286 EnableFeature = false;
4287 Name = Name.substr(2);
4288 }
4289
Tim Northover8b96c7e2017-05-15 19:42:15 +00004290 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004291 for (const auto &Extension : ExtensionMap) {
4292 if (Extension.Name != Name)
4293 continue;
4294
4295 if (Extension.Features.none())
4296 report_fatal_error("unsupported architectural extension: " + Name);
4297
4298 FeatureBitset ToggleFeatures = EnableFeature
4299 ? (~Features & Extension.Features)
4300 : ( Features & Extension.Features);
4301 uint64_t Features =
4302 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4303 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004304 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004305
4306 break;
4307 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004308
4309 if (!FoundExtension)
4310 Error(CurLoc, "unsupported architectural extension");
4311
4312 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004313 }
4314 return false;
4315}
4316
Tim Northover3b0846e2014-05-24 12:50:23 +00004317/// parseDirectiveWord
4318/// ::= .word [ expression (, expression)* ]
4319bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004320 auto parseOp = [&]() -> bool {
4321 const MCExpr *Value;
4322 if (getParser().parseExpression(Value))
4323 return true;
4324 getParser().getStreamer().EmitValue(Value, Size, L);
4325 return false;
4326 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004327
Nirav Davee833c6c2016-11-08 18:31:04 +00004328 if (parseMany(parseOp))
4329 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004330 return false;
4331}
4332
Chad Rosierdcd2a302014-10-22 20:35:57 +00004333/// parseDirectiveInst
4334/// ::= .inst opcode [, ...]
4335bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004336 if (getLexer().is(AsmToken::EndOfStatement))
4337 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004338
Nirav Davee833c6c2016-11-08 18:31:04 +00004339 auto parseOp = [&]() -> bool {
4340 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004341 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004342 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4343 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004344 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004345 if (check(!Value, L, "expected constant expression"))
4346 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004347 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004348 return false;
4349 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004350
Nirav Davee833c6c2016-11-08 18:31:04 +00004351 if (parseMany(parseOp))
4352 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004353 return false;
4354}
4355
Tim Northover3b0846e2014-05-24 12:50:23 +00004356// parseDirectiveTLSDescCall:
4357// ::= .tlsdesccall symbol
4358bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4359 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004360 if (check(getParser().parseIdentifier(Name), L,
4361 "expected symbol after directive") ||
4362 parseToken(AsmToken::EndOfStatement))
4363 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004364
Jim Grosbach6f482002015-05-18 18:43:14 +00004365 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004366 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4367 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004368
4369 MCInst Inst;
4370 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004371 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004372
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004373 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004374 return false;
4375}
4376
4377/// ::= .loh <lohName | lohId> label1, ..., labelN
4378/// The number of arguments depends on the loh identifier.
4379bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004380 MCLOHType Kind;
4381 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4382 if (getParser().getTok().isNot(AsmToken::Integer))
4383 return TokError("expected an identifier or a number in directive");
4384 // We successfully get a numeric value for the identifier.
4385 // Check if it is valid.
4386 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004387 if (Id <= -1U && !isValidMCLOHType(Id))
4388 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004389 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004390 } else {
4391 StringRef Name = getTok().getIdentifier();
4392 // We successfully parse an identifier.
4393 // Check if it is a recognized one.
4394 int Id = MCLOHNameToId(Name);
4395
4396 if (Id == -1)
4397 return TokError("invalid identifier in directive");
4398 Kind = (MCLOHType)Id;
4399 }
4400 // Consume the identifier.
4401 Lex();
4402 // Get the number of arguments of this LOH.
4403 int NbArgs = MCLOHIdToNbArgs(Kind);
4404
4405 assert(NbArgs != -1 && "Invalid number of arguments");
4406
4407 SmallVector<MCSymbol *, 3> Args;
4408 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4409 StringRef Name;
4410 if (getParser().parseIdentifier(Name))
4411 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004412 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004413
4414 if (Idx + 1 == NbArgs)
4415 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004416 if (parseToken(AsmToken::Comma,
4417 "unexpected token in '" + Twine(IDVal) + "' directive"))
4418 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004419 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004420 if (parseToken(AsmToken::EndOfStatement,
4421 "unexpected token in '" + Twine(IDVal) + "' directive"))
4422 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004423
4424 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4425 return false;
4426}
4427
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004428/// parseDirectiveLtorg
4429/// ::= .ltorg | .pool
4430bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004431 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4432 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004433 getTargetStreamer().emitCurrentConstantPool();
4434 return false;
4435}
4436
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004437/// parseDirectiveReq
4438/// ::= name .req registername
4439bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004440 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004441 Parser.Lex(); // Eat the '.req' token.
4442 SMLoc SRegLoc = getLoc();
Sander de Smalen8e607342017-11-15 15:44:43 +00004443 int RegNum = tryParseRegister();
Florian Hahnc4422242017-11-07 13:07:50 +00004444 RegKind RegisterKind = RegKind::Scalar;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004445
Sander de Smalen8e607342017-11-15 15:44:43 +00004446 if (RegNum == -1) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004447 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004448 RegisterKind = RegKind::NeonVector;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004449 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004450 if (!Kind.empty())
4451 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004452 }
4453
Sander de Smalen8e607342017-11-15 15:44:43 +00004454 if (RegNum == -1) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004455 StringRef Kind;
4456 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen8e607342017-11-15 15:44:43 +00004457 OperandMatchResultTy Res =
4458 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4459
4460 if (Res == MatchOperand_ParseFail)
4461 return true;
4462
4463 if (Res == MatchOperand_Success && !Kind.empty())
4464 return Error(SRegLoc,
4465 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004466 }
4467
Sander de Smalencd6be962017-12-20 11:02:42 +00004468 if (RegNum == -1) {
4469 StringRef Kind;
4470 RegisterKind = RegKind::SVEPredicateVector;
4471 OperandMatchResultTy Res =
4472 tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
4473
4474 if (Res == MatchOperand_ParseFail)
4475 return true;
4476
4477 if (Res == MatchOperand_Success && !Kind.empty())
4478 return Error(SRegLoc,
4479 "sve predicate register without type specifier expected");
4480 }
4481
Sander de Smalen8e607342017-11-15 15:44:43 +00004482 if (RegNum == -1)
Nirav Dave2364748a2016-09-16 18:30:20 +00004483 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004484
4485 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004486 if (parseToken(AsmToken::EndOfStatement,
4487 "unexpected input in .req directive"))
4488 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004489
Sander de Smalen8e607342017-11-15 15:44:43 +00004490 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004491 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004492 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4493
Nirav Dave2364748a2016-09-16 18:30:20 +00004494 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004495}
4496
4497/// parseDirectiveUneq
4498/// ::= .unreq registername
4499bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004500 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004501 if (getTok().isNot(AsmToken::Identifier))
4502 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004503 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4504 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004505 if (parseToken(AsmToken::EndOfStatement))
4506 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004507 return false;
4508}
4509
Tim Northover3b0846e2014-05-24 12:50:23 +00004510bool
4511AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4512 AArch64MCExpr::VariantKind &ELFRefKind,
4513 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4514 int64_t &Addend) {
4515 ELFRefKind = AArch64MCExpr::VK_INVALID;
4516 DarwinRefKind = MCSymbolRefExpr::VK_None;
4517 Addend = 0;
4518
4519 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4520 ELFRefKind = AE->getKind();
4521 Expr = AE->getSubExpr();
4522 }
4523
4524 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4525 if (SE) {
4526 // It's a simple symbol reference with no addend.
4527 DarwinRefKind = SE->getKind();
4528 return true;
4529 }
4530
4531 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4532 if (!BE)
4533 return false;
4534
4535 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4536 if (!SE)
4537 return false;
4538 DarwinRefKind = SE->getKind();
4539
4540 if (BE->getOpcode() != MCBinaryExpr::Add &&
4541 BE->getOpcode() != MCBinaryExpr::Sub)
4542 return false;
4543
4544 // See if the addend is is a constant, otherwise there's more going
4545 // on here than we can deal with.
4546 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4547 if (!AddendExpr)
4548 return false;
4549
4550 Addend = AddendExpr->getValue();
4551 if (BE->getOpcode() == MCBinaryExpr::Sub)
4552 Addend = -Addend;
4553
4554 // It's some symbol reference + a constant addend, but really
4555 // shouldn't use both Darwin and ELF syntax.
4556 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4557 DarwinRefKind == MCSymbolRefExpr::VK_None;
4558}
4559
4560/// Force static initialization.
4561extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004562 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4563 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4564 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004565}
4566
4567#define GET_REGISTER_MATCHER
4568#define GET_SUBTARGET_FEATURE_NAME
4569#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004570#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004571#include "AArch64GenAsmMatcher.inc"
4572
4573// Define this matcher function after the auto-generated include so we
4574// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004575unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004576 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004577 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004578 // If the kind is a token for a literal immediate, check if our asm
4579 // operand matches. This is for InstAliases which have a fixed-value
4580 // immediate in the syntax.
4581 int64_t ExpectedVal;
4582 switch (Kind) {
4583 default:
4584 return Match_InvalidOperand;
4585 case MCK__35_0:
4586 ExpectedVal = 0;
4587 break;
4588 case MCK__35_1:
4589 ExpectedVal = 1;
4590 break;
4591 case MCK__35_12:
4592 ExpectedVal = 12;
4593 break;
4594 case MCK__35_16:
4595 ExpectedVal = 16;
4596 break;
4597 case MCK__35_2:
4598 ExpectedVal = 2;
4599 break;
4600 case MCK__35_24:
4601 ExpectedVal = 24;
4602 break;
4603 case MCK__35_3:
4604 ExpectedVal = 3;
4605 break;
4606 case MCK__35_32:
4607 ExpectedVal = 32;
4608 break;
4609 case MCK__35_4:
4610 ExpectedVal = 4;
4611 break;
4612 case MCK__35_48:
4613 ExpectedVal = 48;
4614 break;
4615 case MCK__35_6:
4616 ExpectedVal = 6;
4617 break;
4618 case MCK__35_64:
4619 ExpectedVal = 64;
4620 break;
4621 case MCK__35_8:
4622 ExpectedVal = 8;
4623 break;
4624 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004625 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004626 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004627 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004628 if (!CE)
4629 return Match_InvalidOperand;
4630 if (CE->getValue() == ExpectedVal)
4631 return Match_Success;
4632 return Match_InvalidOperand;
4633}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004634
Alex Bradbury58eba092016-11-01 16:32:05 +00004635OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004636AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4637
4638 SMLoc S = getLoc();
4639
4640 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4641 Error(S, "expected register");
4642 return MatchOperand_ParseFail;
4643 }
4644
4645 int FirstReg = tryParseRegister();
4646 if (FirstReg == -1) {
4647 return MatchOperand_ParseFail;
4648 }
4649 const MCRegisterClass &WRegClass =
4650 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4651 const MCRegisterClass &XRegClass =
4652 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4653
4654 bool isXReg = XRegClass.contains(FirstReg),
4655 isWReg = WRegClass.contains(FirstReg);
4656 if (!isXReg && !isWReg) {
4657 Error(S, "expected first even register of a "
4658 "consecutive same-size even/odd register pair");
4659 return MatchOperand_ParseFail;
4660 }
4661
4662 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4663 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4664
4665 if (FirstEncoding & 0x1) {
4666 Error(S, "expected first even register of a "
4667 "consecutive same-size even/odd register pair");
4668 return MatchOperand_ParseFail;
4669 }
4670
4671 SMLoc M = getLoc();
4672 if (getParser().getTok().isNot(AsmToken::Comma)) {
4673 Error(M, "expected comma");
4674 return MatchOperand_ParseFail;
4675 }
4676 // Eat the comma
4677 getParser().Lex();
4678
4679 SMLoc E = getLoc();
4680 int SecondReg = tryParseRegister();
4681 if (SecondReg ==-1) {
4682 return MatchOperand_ParseFail;
4683 }
4684
Eugene Zelenko049b0172017-01-06 00:30:53 +00004685 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004686 (isXReg && !XRegClass.contains(SecondReg)) ||
4687 (isWReg && !WRegClass.contains(SecondReg))) {
4688 Error(E,"expected second odd register of a "
4689 "consecutive same-size even/odd register pair");
4690 return MatchOperand_ParseFail;
4691 }
Joel Jones504bf332016-10-24 13:37:13 +00004692
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004693 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004694 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004695 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4696 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4697 } else {
4698 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4699 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4700 }
4701
Florian Hahnc4422242017-11-07 13:07:50 +00004702 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4703 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004704
4705 return MatchOperand_Success;
4706}
Florian Hahn91f11e52017-11-07 16:45:48 +00004707
4708template <bool ParseSuffix>
4709OperandMatchResultTy
4710AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004711 const SMLoc S = getLoc();
4712 // Check for a SVE vector register specifier first.
Sander de Smalen8e607342017-11-15 15:44:43 +00004713 int RegNum = -1;
Florian Hahn91f11e52017-11-07 16:45:48 +00004714 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004715
Sander de Smalen8e607342017-11-15 15:44:43 +00004716 OperandMatchResultTy Res =
4717 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4718
4719 if (Res != MatchOperand_Success)
4720 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004721
4722 if (ParseSuffix && Kind.empty())
4723 return MatchOperand_NoMatch;
4724
4725 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
4726 .Case("", -1)
4727 .Case(".b", 8)
4728 .Case(".h", 16)
4729 .Case(".s", 32)
4730 .Case(".d", 64)
4731 .Case(".q", 128)
4732 .Default(0);
4733 if (!ElementWidth)
4734 return MatchOperand_NoMatch;
4735
4736 Operands.push_back(
4737 AArch64Operand::CreateReg(RegNum, RegKind::SVEDataVector, ElementWidth,
4738 S, S, getContext()));
4739
4740 return MatchOperand_Success;
4741}
Sander de Smalen245e0e62018-01-22 10:46:00 +00004742
4743OperandMatchResultTy
4744AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
4745 MCAsmParser &Parser = getParser();
4746
4747 SMLoc SS = getLoc();
4748 const AsmToken &TokE = Parser.getTok();
4749 bool IsHash = TokE.is(AsmToken::Hash);
4750
4751 if (!IsHash && TokE.isNot(AsmToken::Identifier))
4752 return MatchOperand_NoMatch;
4753
4754 int64_t Pattern;
4755 if (IsHash) {
4756 Parser.Lex(); // Eat hash
4757
4758 // Parse the immediate operand.
4759 const MCExpr *ImmVal;
4760 SS = getLoc();
4761 if (Parser.parseExpression(ImmVal))
4762 return MatchOperand_ParseFail;
4763
4764 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4765 if (!MCE)
4766 return MatchOperand_ParseFail;
4767
4768 Pattern = MCE->getValue();
4769 } else {
4770 // Parse the pattern
4771 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
4772 if (!Pat)
4773 return MatchOperand_NoMatch;
4774
4775 Parser.Lex();
4776 Pattern = Pat->Encoding;
4777 assert(Pattern >= 0 && Pattern < 32);
4778 }
4779
4780 Operands.push_back(
4781 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
4782 SS, getLoc(), getContext()));
4783
4784 return MatchOperand_Success;
4785}