blob: a04754bdda38251667fd2d70f3083f183c77c293 [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
Sander de Smalena1c259c2018-01-29 13:05:38 +0000558 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
559 // a logical immediate can always be represented when inverted.
560 template <typename T>
561 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000562 if (!isImm())
563 return false;
564 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
565 if (!MCE)
566 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000567
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000568 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000569 int64_t SVal = typename std::make_signed<T>::type(Val);
570 int64_t UVal = typename std::make_unsigned<T>::type(Val);
571 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000572 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000573
Sander de Smalena1c259c2018-01-29 13:05:38 +0000574 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000575 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000576
Tim Northover3b0846e2014-05-24 12:50:23 +0000577 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000578
Tim Northover3b0846e2014-05-24 12:50:23 +0000579 bool isAddSubImm() const {
580 if (!isShiftedImm() && !isImm())
581 return false;
582
583 const MCExpr *Expr;
584
585 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
586 if (isShiftedImm()) {
587 unsigned Shift = ShiftedImm.ShiftAmount;
588 Expr = ShiftedImm.Val;
589 if (Shift != 0 && Shift != 12)
590 return false;
591 } else {
592 Expr = getImm();
593 }
594
595 AArch64MCExpr::VariantKind ELFRefKind;
596 MCSymbolRefExpr::VariantKind DarwinRefKind;
597 int64_t Addend;
598 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
599 DarwinRefKind, Addend)) {
600 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
601 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
602 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
603 || ELFRefKind == AArch64MCExpr::VK_LO12
604 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
605 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
606 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
607 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
608 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
609 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
610 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12;
611 }
612
Diana Picusc93518d2016-10-11 09:17:47 +0000613 // If it's a constant, it should be a real immediate in range:
614 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
615 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
616
617 // If it's an expression, we hope for the best and let the fixup/relocation
618 // code deal with it.
619 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000620 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000621
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000622 bool isAddSubImmNeg() const {
623 if (!isShiftedImm() && !isImm())
624 return false;
625
626 const MCExpr *Expr;
627
628 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
629 if (isShiftedImm()) {
630 unsigned Shift = ShiftedImm.ShiftAmount;
631 Expr = ShiftedImm.Val;
632 if (Shift != 0 && Shift != 12)
633 return false;
634 } else
635 Expr = getImm();
636
637 // Otherwise it should be a real negative immediate in range:
638 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
639 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
640 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000641
Tim Northover3b0846e2014-05-24 12:50:23 +0000642 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000643
Tim Northover3b0846e2014-05-24 12:50:23 +0000644 bool isSIMDImmType10() const {
645 if (!isImm())
646 return false;
647 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
648 if (!MCE)
649 return false;
650 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
651 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000652
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000653 template<int N>
654 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000655 if (!isImm())
656 return false;
657 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
658 if (!MCE)
659 return true;
660 int64_t Val = MCE->getValue();
661 if (Val & 0x3)
662 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000663 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
664 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000665 }
666
667 bool
668 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
669 if (!isImm())
670 return false;
671
672 AArch64MCExpr::VariantKind ELFRefKind;
673 MCSymbolRefExpr::VariantKind DarwinRefKind;
674 int64_t Addend;
675 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
676 DarwinRefKind, Addend)) {
677 return false;
678 }
679 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
680 return false;
681
682 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
683 if (ELFRefKind == AllowedModifiers[i])
684 return Addend == 0;
685 }
686
687 return false;
688 }
689
690 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000691 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000692 }
693
694 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000695 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
696 AArch64MCExpr::VK_TPREL_G2,
697 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000698 }
699
700 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000701 return isMovWSymbol({
702 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000703 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
704 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000705 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000706 }
707
708 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000709 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
710 AArch64MCExpr::VK_TPREL_G0,
711 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000712 }
713
714 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000715 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000716 }
717
718 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000719 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000720 }
721
722 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000723 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
724 AArch64MCExpr::VK_TPREL_G1_NC,
725 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000726 }
727
728 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000729 return isMovWSymbol(
730 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
731 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000732 }
733
734 template<int RegWidth, int Shift>
735 bool isMOVZMovAlias() const {
736 if (!isImm()) return false;
737
738 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
739 if (!CE) return false;
740 uint64_t Value = CE->getValue();
741
Tim Northoverdaa1c012016-06-16 01:42:25 +0000742 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000743 }
744
745 template<int RegWidth, int Shift>
746 bool isMOVNMovAlias() const {
747 if (!isImm()) return false;
748
749 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
750 if (!CE) return false;
751 uint64_t Value = CE->getValue();
752
Tim Northoverdaa1c012016-06-16 01:42:25 +0000753 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000754 }
755
756 bool isFPImm() const { return Kind == k_FPImm; }
757 bool isBarrier() const { return Kind == k_Barrier; }
758 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000759
Tim Northover3b0846e2014-05-24 12:50:23 +0000760 bool isMRSSystemRegister() const {
761 if (!isSysReg()) return false;
762
Tim Northover7cd58932015-01-22 17:23:04 +0000763 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000764 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000765
Tim Northover3b0846e2014-05-24 12:50:23 +0000766 bool isMSRSystemRegister() const {
767 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000768 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000769 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000770
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000771 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000772 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000773 return (SysReg.PStateField == AArch64PState::PAN ||
774 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000775 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000776
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000777 bool isSystemPStateFieldWithImm0_15() const {
778 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000779 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000780 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000781
Florian Hahnc4422242017-11-07 13:07:50 +0000782 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000783 return Kind == k_Register;
784 }
785
786 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000787 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
788 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000789
Florian Hahnc4422242017-11-07 13:07:50 +0000790 bool isNeonVectorReg() const {
791 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
792 }
793
794 bool isNeonVectorRegLo() const {
795 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000796 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
797 Reg.RegNum);
798 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000799
Sander de Smalencd6be962017-12-20 11:02:42 +0000800 template <unsigned Class> bool isSVEVectorReg() const {
801 RegKind RK;
802 switch (Class) {
803 case AArch64::ZPRRegClassID:
804 RK = RegKind::SVEDataVector;
805 break;
806 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000807 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000808 RK = RegKind::SVEPredicateVector;
809 break;
810 default:
811 llvm_unreachable("Unsupport register class");
812 }
813
814 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000815 AArch64MCRegisterClasses[Class].contains(getReg());
816 }
817
Sander de Smalencd6be962017-12-20 11:02:42 +0000818 template <int ElementWidth, unsigned Class>
819 bool isSVEVectorRegOfWidth() const {
820 return isSVEVectorReg<Class>() &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000821 (ElementWidth == -1 || Reg.ElementWidth == ElementWidth);
822 }
823
Tim Northover3b0846e2014-05-24 12:50:23 +0000824 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000825 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000826 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
827 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000828
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000829 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000830 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000831 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
832 Reg.RegNum);
833 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000834
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000835 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000836 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000837 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
838 Reg.RegNum);
839 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000840
841 bool isGPR64sp0() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000842 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000843 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
844 }
845
Sam Parker5f934642017-08-31 09:27:04 +0000846 template<int64_t Angle, int64_t Remainder>
847 bool isComplexRotation() const {
848 if (!isImm()) return false;
849
850 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
851 if (!CE) return false;
852 uint64_t Value = CE->getValue();
853
854 return (Value % Angle == Remainder && Value <= 270);
855 }
856
Tim Northover3b0846e2014-05-24 12:50:23 +0000857 /// Is this a vector list with the type implicit (presumably attached to the
858 /// instruction itself)?
859 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
860 return Kind == k_VectorList && VectorList.Count == NumRegs &&
861 !VectorList.ElementKind;
862 }
863
864 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
865 bool isTypedVectorList() const {
866 if (Kind != k_VectorList)
867 return false;
868 if (VectorList.Count != NumRegs)
869 return false;
870 if (VectorList.ElementKind != ElementKind)
871 return false;
872 return VectorList.NumElements == NumElements;
873 }
874
875 bool isVectorIndex1() const {
876 return Kind == k_VectorIndex && VectorIndex.Val == 1;
877 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000878
Tim Northover3b0846e2014-05-24 12:50:23 +0000879 bool isVectorIndexB() const {
880 return Kind == k_VectorIndex && VectorIndex.Val < 16;
881 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000882
Tim Northover3b0846e2014-05-24 12:50:23 +0000883 bool isVectorIndexH() const {
884 return Kind == k_VectorIndex && VectorIndex.Val < 8;
885 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000886
Tim Northover3b0846e2014-05-24 12:50:23 +0000887 bool isVectorIndexS() const {
888 return Kind == k_VectorIndex && VectorIndex.Val < 4;
889 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000890
Tim Northover3b0846e2014-05-24 12:50:23 +0000891 bool isVectorIndexD() const {
892 return Kind == k_VectorIndex && VectorIndex.Val < 2;
893 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000894
Tim Northover3b0846e2014-05-24 12:50:23 +0000895 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000896
Tim Northover3b0846e2014-05-24 12:50:23 +0000897 bool isTokenEqual(StringRef Str) const {
898 return Kind == k_Token && getToken() == Str;
899 }
900 bool isSysCR() const { return Kind == k_SysCR; }
901 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000902 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000903 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
904 bool isShifter() const {
905 if (!isShiftExtend())
906 return false;
907
908 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
909 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
910 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
911 ST == AArch64_AM::MSL);
912 }
913 bool isExtend() const {
914 if (!isShiftExtend())
915 return false;
916
917 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
918 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
919 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
920 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
921 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
922 ET == AArch64_AM::LSL) &&
923 getShiftExtendAmount() <= 4;
924 }
925
926 bool isExtend64() const {
927 if (!isExtend())
928 return false;
929 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
930 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
931 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
932 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000933
Tim Northover3b0846e2014-05-24 12:50:23 +0000934 bool isExtendLSL64() const {
935 if (!isExtend())
936 return false;
937 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
938 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
939 ET == AArch64_AM::LSL) &&
940 getShiftExtendAmount() <= 4;
941 }
942
943 template<int Width> bool isMemXExtend() const {
944 if (!isExtend())
945 return false;
946 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
947 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
948 (getShiftExtendAmount() == Log2_32(Width / 8) ||
949 getShiftExtendAmount() == 0);
950 }
951
952 template<int Width> bool isMemWExtend() const {
953 if (!isExtend())
954 return false;
955 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
956 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
957 (getShiftExtendAmount() == Log2_32(Width / 8) ||
958 getShiftExtendAmount() == 0);
959 }
960
961 template <unsigned width>
962 bool isArithmeticShifter() const {
963 if (!isShifter())
964 return false;
965
966 // An arithmetic shifter is LSL, LSR, or ASR.
967 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
968 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
969 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
970 }
971
972 template <unsigned width>
973 bool isLogicalShifter() const {
974 if (!isShifter())
975 return false;
976
977 // A logical shifter is LSL, LSR, ASR or ROR.
978 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
979 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
980 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
981 getShiftExtendAmount() < width;
982 }
983
984 bool isMovImm32Shifter() const {
985 if (!isShifter())
986 return false;
987
988 // A MOVi shifter is LSL of 0, 16, 32, or 48.
989 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
990 if (ST != AArch64_AM::LSL)
991 return false;
992 uint64_t Val = getShiftExtendAmount();
993 return (Val == 0 || Val == 16);
994 }
995
996 bool isMovImm64Shifter() const {
997 if (!isShifter())
998 return false;
999
1000 // A MOVi shifter is LSL of 0 or 16.
1001 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1002 if (ST != AArch64_AM::LSL)
1003 return false;
1004 uint64_t Val = getShiftExtendAmount();
1005 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1006 }
1007
1008 bool isLogicalVecShifter() const {
1009 if (!isShifter())
1010 return false;
1011
1012 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1013 unsigned Shift = getShiftExtendAmount();
1014 return getShiftExtendType() == AArch64_AM::LSL &&
1015 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1016 }
1017
1018 bool isLogicalVecHalfWordShifter() const {
1019 if (!isLogicalVecShifter())
1020 return false;
1021
1022 // A logical vector shifter is a left shift by 0 or 8.
1023 unsigned Shift = getShiftExtendAmount();
1024 return getShiftExtendType() == AArch64_AM::LSL &&
1025 (Shift == 0 || Shift == 8);
1026 }
1027
1028 bool isMoveVecShifter() const {
1029 if (!isShiftExtend())
1030 return false;
1031
1032 // A logical vector shifter is a left shift by 8 or 16.
1033 unsigned Shift = getShiftExtendAmount();
1034 return getShiftExtendType() == AArch64_AM::MSL &&
1035 (Shift == 8 || Shift == 16);
1036 }
1037
1038 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1039 // to LDUR/STUR when the offset is not legal for the former but is for
1040 // the latter. As such, in addition to checking for being a legal unscaled
1041 // address, also check that it is not a legal scaled address. This avoids
1042 // ambiguity in the matcher.
1043 template<int Width>
1044 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001045 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001046 }
1047
1048 bool isAdrpLabel() const {
1049 // Validation was handled during parsing, so we just sanity check that
1050 // something didn't go haywire.
1051 if (!isImm())
1052 return false;
1053
1054 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1055 int64_t Val = CE->getValue();
1056 int64_t Min = - (4096 * (1LL << (21 - 1)));
1057 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1058 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1059 }
1060
1061 return true;
1062 }
1063
1064 bool isAdrLabel() const {
1065 // Validation was handled during parsing, so we just sanity check that
1066 // something didn't go haywire.
1067 if (!isImm())
1068 return false;
1069
1070 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1071 int64_t Val = CE->getValue();
1072 int64_t Min = - (1LL << (21 - 1));
1073 int64_t Max = ((1LL << (21 - 1)) - 1);
1074 return Val >= Min && Val <= Max;
1075 }
1076
1077 return true;
1078 }
1079
1080 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1081 // Add as immediates when possible. Null MCExpr = 0.
1082 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001083 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001084 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001085 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001086 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001087 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001088 }
1089
1090 void addRegOperands(MCInst &Inst, unsigned N) const {
1091 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001092 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001093 }
1094
1095 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1096 assert(N == 1 && "Invalid number of operands!");
1097 assert(
1098 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1099
1100 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1101 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1102 RI->getEncodingValue(getReg()));
1103
Jim Grosbache9119e42015-05-13 18:37:00 +00001104 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001105 }
1106
1107 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1108 assert(N == 1 && "Invalid number of operands!");
1109 assert(
1110 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001111 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001112 }
1113
1114 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1115 assert(N == 1 && "Invalid number of operands!");
1116 assert(
1117 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001118 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001119 }
1120
1121 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1122 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001123 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001124 }
1125
1126 template <unsigned NumRegs>
1127 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1128 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001129 static const unsigned FirstRegs[] = { AArch64::D0,
1130 AArch64::D0_D1,
1131 AArch64::D0_D1_D2,
1132 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001133 unsigned FirstReg = FirstRegs[NumRegs - 1];
1134
1135 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001136 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001137 }
1138
1139 template <unsigned NumRegs>
1140 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1141 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001142 static const unsigned FirstRegs[] = { AArch64::Q0,
1143 AArch64::Q0_Q1,
1144 AArch64::Q0_Q1_Q2,
1145 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001146 unsigned FirstReg = FirstRegs[NumRegs - 1];
1147
1148 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001149 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001150 }
1151
1152 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1153 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001154 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001155 }
1156
1157 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1158 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001159 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001160 }
1161
1162 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1163 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001164 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001165 }
1166
1167 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1168 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001169 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001170 }
1171
1172 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1173 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001174 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001175 }
1176
1177 void addImmOperands(MCInst &Inst, unsigned N) const {
1178 assert(N == 1 && "Invalid number of operands!");
1179 // If this is a pageoff symrefexpr with an addend, adjust the addend
1180 // to be only the page-offset portion. Otherwise, just add the expr
1181 // as-is.
1182 addExpr(Inst, getImm());
1183 }
1184
1185 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1186 assert(N == 2 && "Invalid number of operands!");
1187 if (isShiftedImm()) {
1188 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001189 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001190 } else {
1191 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001192 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001193 }
1194 }
1195
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001196 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1197 assert(N == 2 && "Invalid number of operands!");
1198
1199 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1200 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1201 int64_t Val = -CE->getValue();
1202 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1203
1204 Inst.addOperand(MCOperand::createImm(Val));
1205 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1206 }
1207
Tim Northover3b0846e2014-05-24 12:50:23 +00001208 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1209 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001210 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001211 }
1212
1213 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1214 assert(N == 1 && "Invalid number of operands!");
1215 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1216 if (!MCE)
1217 addExpr(Inst, getImm());
1218 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001219 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001220 }
1221
1222 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1223 addImmOperands(Inst, N);
1224 }
1225
1226 template<int Scale>
1227 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1228 assert(N == 1 && "Invalid number of operands!");
1229 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1230
1231 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001232 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001233 return;
1234 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001235 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001236 }
1237
1238 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1239 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001240 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001241 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001242 }
1243
Sam Parker6d42de72017-08-11 13:14:00 +00001244 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1245 assert(N == 1 && "Invalid number of operands!");
1246 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1247 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1248 }
1249
Tim Northover3b0846e2014-05-24 12:50:23 +00001250 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1251 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001252 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001253 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001254 }
1255
1256 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1257 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001258 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001259 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001260 }
1261
1262 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1263 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001264 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001265 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001266 }
1267
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001268 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1269 assert(N == 1 && "Invalid number of operands!");
1270 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1271 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1272 }
1273
Tim Northover3b0846e2014-05-24 12:50:23 +00001274 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1275 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001276 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001277 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001278 }
1279
1280 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1281 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001282 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001283 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001284 }
1285
1286 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1287 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001288 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001289 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001290 }
1291
1292 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1293 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001294 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001295 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001296 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001297 }
1298
1299 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1300 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001301 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001302 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001303 }
1304
1305 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1306 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001307 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001308 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001309 }
1310
1311 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1312 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001313 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001314 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001315 }
1316
1317 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1318 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001319 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001320 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001321 }
1322
1323 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1324 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001325 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001326 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001327 }
1328
1329 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1330 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001331 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001332 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001333 }
1334
1335 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1336 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001337 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001338 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001339 }
1340
1341 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1342 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001343 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001344 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001345 }
1346
1347 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1348 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001349 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001350 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001351 }
1352
1353 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1354 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001355 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001356 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001357 }
1358
Sander de Smalena1c259c2018-01-29 13:05:38 +00001359 template <typename T>
1360 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001361 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001362 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001363 typename std::make_unsigned<T>::type Val = MCE->getValue();
1364 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001365 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001366 }
1367
Sander de Smalena1c259c2018-01-29 13:05:38 +00001368 template <typename T>
1369 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001370 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001371 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001372 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1373 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001374 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001375 }
1376
Tim Northover3b0846e2014-05-24 12:50:23 +00001377 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1378 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001379 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001380 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001381 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001382 }
1383
1384 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1385 // Branch operands don't encode the low bits, so shift them off
1386 // here. If it's a label, however, just put it on directly as there's
1387 // not enough information now to do anything.
1388 assert(N == 1 && "Invalid number of operands!");
1389 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1390 if (!MCE) {
1391 addExpr(Inst, getImm());
1392 return;
1393 }
1394 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001395 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001396 }
1397
1398 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1399 // Branch operands don't encode the low bits, so shift them off
1400 // here. If it's a label, however, just put it on directly as there's
1401 // not enough information now to do anything.
1402 assert(N == 1 && "Invalid number of operands!");
1403 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1404 if (!MCE) {
1405 addExpr(Inst, getImm());
1406 return;
1407 }
1408 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001409 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001410 }
1411
1412 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1413 // Branch operands don't encode the low bits, so shift them off
1414 // here. If it's a label, however, just put it on directly as there's
1415 // not enough information now to do anything.
1416 assert(N == 1 && "Invalid number of operands!");
1417 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1418 if (!MCE) {
1419 addExpr(Inst, getImm());
1420 return;
1421 }
1422 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001423 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001424 }
1425
1426 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1427 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001428 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001429 }
1430
1431 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1432 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001433 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 }
1435
1436 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1437 assert(N == 1 && "Invalid number of operands!");
1438
Jim Grosbache9119e42015-05-13 18:37:00 +00001439 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001440 }
1441
1442 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1443 assert(N == 1 && "Invalid number of operands!");
1444
Jim Grosbache9119e42015-05-13 18:37:00 +00001445 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001446 }
1447
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001448 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1449 assert(N == 1 && "Invalid number of operands!");
1450
1451 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1452 }
1453
1454 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001455 assert(N == 1 && "Invalid number of operands!");
1456
Jim Grosbache9119e42015-05-13 18:37:00 +00001457 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001458 }
1459
1460 void addSysCROperands(MCInst &Inst, unsigned N) const {
1461 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001462 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001463 }
1464
1465 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1466 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001467 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001468 }
1469
Oliver Stannarda34e4702015-12-01 10:48:51 +00001470 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1471 assert(N == 1 && "Invalid number of operands!");
1472 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1473 }
1474
Tim Northover3b0846e2014-05-24 12:50:23 +00001475 void addShifterOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 1 && "Invalid number of operands!");
1477 unsigned Imm =
1478 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001479 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001480 }
1481
1482 void addExtendOperands(MCInst &Inst, unsigned N) const {
1483 assert(N == 1 && "Invalid number of operands!");
1484 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1485 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1486 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001487 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001488 }
1489
1490 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1491 assert(N == 1 && "Invalid number of operands!");
1492 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1493 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1494 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001495 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001496 }
1497
1498 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1499 assert(N == 2 && "Invalid number of operands!");
1500 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1501 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001502 Inst.addOperand(MCOperand::createImm(IsSigned));
1503 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001504 }
1505
1506 // For 8-bit load/store instructions with a register offset, both the
1507 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1508 // they're disambiguated by whether the shift was explicit or implicit rather
1509 // than its size.
1510 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1511 assert(N == 2 && "Invalid number of operands!");
1512 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1513 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001514 Inst.addOperand(MCOperand::createImm(IsSigned));
1515 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001516 }
1517
1518 template<int Shift>
1519 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1520 assert(N == 1 && "Invalid number of operands!");
1521
1522 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1523 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001524 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001525 }
1526
1527 template<int Shift>
1528 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1529 assert(N == 1 && "Invalid number of operands!");
1530
1531 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1532 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001533 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001534 }
1535
Sam Parker5f934642017-08-31 09:27:04 +00001536 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1537 assert(N == 1 && "Invalid number of operands!");
1538 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1539 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1540 }
1541
1542 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1543 assert(N == 1 && "Invalid number of operands!");
1544 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1545 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1546 }
1547
Tim Northover3b0846e2014-05-24 12:50:23 +00001548 void print(raw_ostream &OS) const override;
1549
David Blaikie960ea3f2014-06-08 16:18:35 +00001550 static std::unique_ptr<AArch64Operand>
1551 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1552 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001553 Op->Tok.Data = Str.data();
1554 Op->Tok.Length = Str.size();
1555 Op->Tok.IsSuffix = IsSuffix;
1556 Op->StartLoc = S;
1557 Op->EndLoc = S;
1558 return Op;
1559 }
1560
David Blaikie960ea3f2014-06-08 16:18:35 +00001561 static std::unique_ptr<AArch64Operand>
Florian Hahnc4422242017-11-07 13:07:50 +00001562 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001563 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001564 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001565 Op->Reg.Kind = Kind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001566 Op->StartLoc = S;
1567 Op->EndLoc = E;
1568 return Op;
1569 }
1570
David Blaikie960ea3f2014-06-08 16:18:35 +00001571 static std::unique_ptr<AArch64Operand>
Florian Hahn91f11e52017-11-07 16:45:48 +00001572 CreateReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1573 SMLoc S, SMLoc E, MCContext &Ctx) {
1574 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1575 Op->Reg.RegNum = RegNum;
1576 Op->Reg.ElementWidth = ElementWidth;
1577 Op->Reg.Kind = Kind;
1578 Op->StartLoc = S;
1579 Op->EndLoc = E;
1580 return Op;
1581 }
1582
1583 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001584 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1585 char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1586 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001587 Op->VectorList.RegNum = RegNum;
1588 Op->VectorList.Count = Count;
1589 Op->VectorList.NumElements = NumElements;
1590 Op->VectorList.ElementKind = ElementKind;
1591 Op->StartLoc = S;
1592 Op->EndLoc = E;
1593 return Op;
1594 }
1595
David Blaikie960ea3f2014-06-08 16:18:35 +00001596 static std::unique_ptr<AArch64Operand>
1597 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1598 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001599 Op->VectorIndex.Val = Idx;
1600 Op->StartLoc = S;
1601 Op->EndLoc = E;
1602 return Op;
1603 }
1604
David Blaikie960ea3f2014-06-08 16:18:35 +00001605 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1606 SMLoc E, MCContext &Ctx) {
1607 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001608 Op->Imm.Val = Val;
1609 Op->StartLoc = S;
1610 Op->EndLoc = E;
1611 return Op;
1612 }
1613
David Blaikie960ea3f2014-06-08 16:18:35 +00001614 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1615 unsigned ShiftAmount,
1616 SMLoc S, SMLoc E,
1617 MCContext &Ctx) {
1618 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001619 Op->ShiftedImm .Val = Val;
1620 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1621 Op->StartLoc = S;
1622 Op->EndLoc = E;
1623 return Op;
1624 }
1625
David Blaikie960ea3f2014-06-08 16:18:35 +00001626 static std::unique_ptr<AArch64Operand>
1627 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1628 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001629 Op->CondCode.Code = Code;
1630 Op->StartLoc = S;
1631 Op->EndLoc = E;
1632 return Op;
1633 }
1634
David Blaikie960ea3f2014-06-08 16:18:35 +00001635 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1636 MCContext &Ctx) {
1637 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001638 Op->FPImm.Val = Val;
1639 Op->StartLoc = S;
1640 Op->EndLoc = S;
1641 return Op;
1642 }
1643
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001644 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1645 StringRef Str,
1646 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001647 MCContext &Ctx) {
1648 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001649 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001650 Op->Barrier.Data = Str.data();
1651 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001652 Op->StartLoc = S;
1653 Op->EndLoc = S;
1654 return Op;
1655 }
1656
Tim Northover7cd58932015-01-22 17:23:04 +00001657 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1658 uint32_t MRSReg,
1659 uint32_t MSRReg,
1660 uint32_t PStateField,
1661 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001662 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001663 Op->SysReg.Data = Str.data();
1664 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001665 Op->SysReg.MRSReg = MRSReg;
1666 Op->SysReg.MSRReg = MSRReg;
1667 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001668 Op->StartLoc = S;
1669 Op->EndLoc = S;
1670 return Op;
1671 }
1672
David Blaikie960ea3f2014-06-08 16:18:35 +00001673 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1674 SMLoc E, MCContext &Ctx) {
1675 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001676 Op->SysCRImm.Val = Val;
1677 Op->StartLoc = S;
1678 Op->EndLoc = E;
1679 return Op;
1680 }
1681
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001682 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1683 StringRef Str,
1684 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001685 MCContext &Ctx) {
1686 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001687 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001688 Op->Barrier.Data = Str.data();
1689 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001690 Op->StartLoc = S;
1691 Op->EndLoc = S;
1692 return Op;
1693 }
1694
Oliver Stannarda34e4702015-12-01 10:48:51 +00001695 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1696 StringRef Str,
1697 SMLoc S,
1698 MCContext &Ctx) {
1699 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1700 Op->PSBHint.Val = Val;
1701 Op->PSBHint.Data = Str.data();
1702 Op->PSBHint.Length = Str.size();
1703 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>
1709 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1710 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1711 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001712 Op->ShiftExtend.Type = ShOp;
1713 Op->ShiftExtend.Amount = Val;
1714 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1715 Op->StartLoc = S;
1716 Op->EndLoc = E;
1717 return Op;
1718 }
1719};
1720
1721} // end anonymous namespace.
1722
1723void AArch64Operand::print(raw_ostream &OS) const {
1724 switch (Kind) {
1725 case k_FPImm:
1726 OS << "<fpimm " << getFPImm() << "("
1727 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1728 break;
1729 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001730 StringRef Name = getBarrierName();
1731 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001732 OS << "<barrier " << Name << ">";
1733 else
1734 OS << "<barrier invalid #" << getBarrier() << ">";
1735 break;
1736 }
1737 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001738 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001739 break;
1740 case k_ShiftedImm: {
1741 unsigned Shift = getShiftedImmShift();
1742 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001743 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001744 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1745 break;
1746 }
1747 case k_CondCode:
1748 OS << "<condcode " << getCondCode() << ">";
1749 break;
1750 case k_Register:
1751 OS << "<register " << getReg() << ">";
1752 break;
1753 case k_VectorList: {
1754 OS << "<vectorlist ";
1755 unsigned Reg = getVectorListStart();
1756 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1757 OS << Reg + i << " ";
1758 OS << ">";
1759 break;
1760 }
1761 case k_VectorIndex:
1762 OS << "<vectorindex " << getVectorIndex() << ">";
1763 break;
1764 case k_SysReg:
1765 OS << "<sysreg: " << getSysReg() << '>';
1766 break;
1767 case k_Token:
1768 OS << "'" << getToken() << "'";
1769 break;
1770 case k_SysCR:
1771 OS << "c" << getSysCR();
1772 break;
1773 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001774 StringRef Name = getPrefetchName();
1775 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001776 OS << "<prfop " << Name << ">";
1777 else
1778 OS << "<prfop invalid #" << getPrefetch() << ">";
1779 break;
1780 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001781 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001782 OS << getPSBHintName();
1783 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001784 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001785 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1786 << getShiftExtendAmount();
1787 if (!hasShiftExtendAmount())
1788 OS << "<imp>";
1789 OS << '>';
1790 break;
1791 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001792}
1793
1794/// @name Auto-generated Match Functions
1795/// {
1796
1797static unsigned MatchRegisterName(StringRef Name);
1798
1799/// }
1800
Florian Hahnc4422242017-11-07 13:07:50 +00001801static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001802 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001803 .Case("v0", AArch64::Q0)
1804 .Case("v1", AArch64::Q1)
1805 .Case("v2", AArch64::Q2)
1806 .Case("v3", AArch64::Q3)
1807 .Case("v4", AArch64::Q4)
1808 .Case("v5", AArch64::Q5)
1809 .Case("v6", AArch64::Q6)
1810 .Case("v7", AArch64::Q7)
1811 .Case("v8", AArch64::Q8)
1812 .Case("v9", AArch64::Q9)
1813 .Case("v10", AArch64::Q10)
1814 .Case("v11", AArch64::Q11)
1815 .Case("v12", AArch64::Q12)
1816 .Case("v13", AArch64::Q13)
1817 .Case("v14", AArch64::Q14)
1818 .Case("v15", AArch64::Q15)
1819 .Case("v16", AArch64::Q16)
1820 .Case("v17", AArch64::Q17)
1821 .Case("v18", AArch64::Q18)
1822 .Case("v19", AArch64::Q19)
1823 .Case("v20", AArch64::Q20)
1824 .Case("v21", AArch64::Q21)
1825 .Case("v22", AArch64::Q22)
1826 .Case("v23", AArch64::Q23)
1827 .Case("v24", AArch64::Q24)
1828 .Case("v25", AArch64::Q25)
1829 .Case("v26", AArch64::Q26)
1830 .Case("v27", AArch64::Q27)
1831 .Case("v28", AArch64::Q28)
1832 .Case("v29", AArch64::Q29)
1833 .Case("v30", AArch64::Q30)
1834 .Case("v31", AArch64::Q31)
1835 .Default(0);
1836}
1837
1838static bool isValidVectorKind(StringRef Name) {
1839 return StringSwitch<bool>(Name.lower())
1840 .Case(".8b", true)
1841 .Case(".16b", true)
1842 .Case(".4h", true)
1843 .Case(".8h", true)
1844 .Case(".2s", true)
1845 .Case(".4s", true)
1846 .Case(".1d", true)
1847 .Case(".2d", true)
1848 .Case(".1q", true)
1849 // Accept the width neutral ones, too, for verbose syntax. If those
1850 // aren't used in the right places, the token operand won't match so
1851 // all will work out.
1852 .Case(".b", true)
1853 .Case(".h", true)
1854 .Case(".s", true)
1855 .Case(".d", true)
Oliver Stannarde4c3d212015-12-08 12:16:10 +00001856 // Needed for fp16 scalar pairwise reductions
1857 .Case(".2h", true)
Sjoerd Meijer79876332017-08-09 14:59:54 +00001858 // another special case for the ARMv8.2a dot product operand
1859 .Case(".4b", true)
Tim Northover3b0846e2014-05-24 12:50:23 +00001860 .Default(false);
1861}
1862
Florian Hahn91f11e52017-11-07 16:45:48 +00001863static unsigned matchSVEDataVectorRegName(StringRef Name) {
1864 return StringSwitch<unsigned>(Name.lower())
1865 .Case("z0", AArch64::Z0)
1866 .Case("z1", AArch64::Z1)
1867 .Case("z2", AArch64::Z2)
1868 .Case("z3", AArch64::Z3)
1869 .Case("z4", AArch64::Z4)
1870 .Case("z5", AArch64::Z5)
1871 .Case("z6", AArch64::Z6)
1872 .Case("z7", AArch64::Z7)
1873 .Case("z8", AArch64::Z8)
1874 .Case("z9", AArch64::Z9)
1875 .Case("z10", AArch64::Z10)
1876 .Case("z11", AArch64::Z11)
1877 .Case("z12", AArch64::Z12)
1878 .Case("z13", AArch64::Z13)
1879 .Case("z14", AArch64::Z14)
1880 .Case("z15", AArch64::Z15)
1881 .Case("z16", AArch64::Z16)
1882 .Case("z17", AArch64::Z17)
1883 .Case("z18", AArch64::Z18)
1884 .Case("z19", AArch64::Z19)
1885 .Case("z20", AArch64::Z20)
1886 .Case("z21", AArch64::Z21)
1887 .Case("z22", AArch64::Z22)
1888 .Case("z23", AArch64::Z23)
1889 .Case("z24", AArch64::Z24)
1890 .Case("z25", AArch64::Z25)
1891 .Case("z26", AArch64::Z26)
1892 .Case("z27", AArch64::Z27)
1893 .Case("z28", AArch64::Z28)
1894 .Case("z29", AArch64::Z29)
1895 .Case("z30", AArch64::Z30)
1896 .Case("z31", AArch64::Z31)
1897 .Default(0);
1898}
1899
Sander de Smalencd6be962017-12-20 11:02:42 +00001900static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1901 return StringSwitch<unsigned>(Name.lower())
1902 .Case("p0", AArch64::P0)
1903 .Case("p1", AArch64::P1)
1904 .Case("p2", AArch64::P2)
1905 .Case("p3", AArch64::P3)
1906 .Case("p4", AArch64::P4)
1907 .Case("p5", AArch64::P5)
1908 .Case("p6", AArch64::P6)
1909 .Case("p7", AArch64::P7)
1910 .Case("p8", AArch64::P8)
1911 .Case("p9", AArch64::P9)
1912 .Case("p10", AArch64::P10)
1913 .Case("p11", AArch64::P11)
1914 .Case("p12", AArch64::P12)
1915 .Case("p13", AArch64::P13)
1916 .Case("p14", AArch64::P14)
1917 .Case("p15", AArch64::P15)
1918 .Default(0);
1919}
1920
Florian Hahn91f11e52017-11-07 16:45:48 +00001921static bool isValidSVEKind(StringRef Name) {
1922 return StringSwitch<bool>(Name.lower())
1923 .Case(".b", true)
1924 .Case(".h", true)
1925 .Case(".s", true)
1926 .Case(".d", true)
1927 .Case(".q", true)
1928 .Default(false);
1929}
1930
Tim Northover3b0846e2014-05-24 12:50:23 +00001931static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1932 char &ElementKind) {
1933 assert(isValidVectorKind(Name));
1934
1935 ElementKind = Name.lower()[Name.size() - 1];
1936 NumElements = 0;
1937
1938 if (Name.size() == 2)
1939 return;
1940
1941 // Parse the lane count
1942 Name = Name.drop_front();
1943 while (isdigit(Name.front())) {
1944 NumElements = 10 * NumElements + (Name.front() - '0');
1945 Name = Name.drop_front();
1946 }
1947}
1948
1949bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1950 SMLoc &EndLoc) {
1951 StartLoc = getLoc();
1952 RegNo = tryParseRegister();
1953 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1954 return (RegNo == (unsigned)-1);
1955}
1956
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001957// Matches a register name or register alias previously defined by '.req'
1958unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001959 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001960 unsigned RegNum = 0;
1961 if ((RegNum = matchSVEDataVectorRegName(Name)))
1962 return Kind == RegKind::SVEDataVector ? RegNum : 0;
1963
Sander de Smalencd6be962017-12-20 11:02:42 +00001964 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
1965 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
1966
Sander de Smalenc067c302017-12-20 09:45:45 +00001967 if ((RegNum = MatchNeonVectorRegName(Name)))
1968 return Kind == RegKind::NeonVector ? RegNum : 0;
1969
1970 // The parsed register must be of RegKind Scalar
1971 if ((RegNum = MatchRegisterName(Name)))
1972 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001973
Florian Hahnc4422242017-11-07 13:07:50 +00001974 if (!RegNum) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001975 // Check for aliases registered via .req. Canonicalize to lower case.
1976 // That's more consistent since register names are case insensitive, and
1977 // it's how the original entry was passed in from MC/MCParser/AsmParser.
1978 auto Entry = RegisterReqs.find(Name.lower());
1979 if (Entry == RegisterReqs.end())
1980 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00001981
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001982 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00001983 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001984 RegNum = Entry->getValue().second;
1985 }
1986 return RegNum;
1987}
1988
Tim Northover3b0846e2014-05-24 12:50:23 +00001989/// tryParseRegister - Try to parse a register name. The token must be an
1990/// Identifier when called, and if it is a register name the token is eaten and
1991/// the register is added to the operand list.
1992int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00001993 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001994 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00001995 if (Tok.isNot(AsmToken::Identifier))
1996 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00001997
1998 std::string lowerCase = Tok.getString().lower();
Florian Hahnc4422242017-11-07 13:07:50 +00001999 unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
Sander de Smalenc067c302017-12-20 09:45:45 +00002000
Tim Northover3b0846e2014-05-24 12:50:23 +00002001 // Also handle a few aliases of registers.
2002 if (RegNum == 0)
2003 RegNum = StringSwitch<unsigned>(lowerCase)
2004 .Case("fp", AArch64::FP)
2005 .Case("lr", AArch64::LR)
2006 .Case("x31", AArch64::XZR)
2007 .Case("w31", AArch64::WZR)
2008 .Default(0);
2009
2010 if (RegNum == 0)
2011 return -1;
2012
2013 Parser.Lex(); // Eat identifier token.
2014 return RegNum;
2015}
2016
2017/// tryMatchVectorRegister - Try to parse a vector register name with optional
2018/// kind specifier. If it is a register specifier, eat the token and return it.
2019int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002020 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002021 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2022 TokError("vector register expected");
2023 return -1;
2024 }
2025
2026 StringRef Name = Parser.getTok().getString();
2027 // If there is a kind specifier, it's separated from the register name by
2028 // a '.'.
2029 size_t Start = 0, Next = Name.find('.');
2030 StringRef Head = Name.slice(Start, Next);
Florian Hahnc4422242017-11-07 13:07:50 +00002031 unsigned RegNum = matchRegisterNameAlias(Head, RegKind::NeonVector);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002032
Tim Northover3b0846e2014-05-24 12:50:23 +00002033 if (RegNum) {
2034 if (Next != StringRef::npos) {
2035 Kind = Name.slice(Next, StringRef::npos);
2036 if (!isValidVectorKind(Kind)) {
2037 TokError("invalid vector kind qualifier");
2038 return -1;
2039 }
2040 }
2041 Parser.Lex(); // Eat the register token.
2042 return RegNum;
2043 }
2044
2045 if (expected)
2046 TokError("vector register expected");
2047 return -1;
2048}
2049
2050/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002051OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002052AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002053 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002054 SMLoc S = getLoc();
2055
2056 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2057 Error(S, "Expected cN operand where 0 <= N <= 15");
2058 return MatchOperand_ParseFail;
2059 }
2060
2061 StringRef Tok = Parser.getTok().getIdentifier();
2062 if (Tok[0] != 'c' && Tok[0] != 'C') {
2063 Error(S, "Expected cN operand where 0 <= N <= 15");
2064 return MatchOperand_ParseFail;
2065 }
2066
2067 uint32_t CRNum;
2068 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2069 if (BadNum || CRNum > 15) {
2070 Error(S, "Expected cN operand where 0 <= N <= 15");
2071 return MatchOperand_ParseFail;
2072 }
2073
2074 Parser.Lex(); // Eat identifier token.
2075 Operands.push_back(
2076 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2077 return MatchOperand_Success;
2078}
2079
2080/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002081OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002082AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002083 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002084 SMLoc S = getLoc();
2085 const AsmToken &Tok = Parser.getTok();
2086 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002087 // Eat optional hash.
2088 if (parseOptionalToken(AsmToken::Hash) ||
2089 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002090 const MCExpr *ImmVal;
2091 if (getParser().parseExpression(ImmVal))
2092 return MatchOperand_ParseFail;
2093
2094 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2095 if (!MCE) {
2096 TokError("immediate value expected for prefetch operand");
2097 return MatchOperand_ParseFail;
2098 }
2099 unsigned prfop = MCE->getValue();
2100 if (prfop > 31) {
2101 TokError("prefetch operand out of range, [0,31] expected");
2102 return MatchOperand_ParseFail;
2103 }
2104
Tim Northovere6ae6762016-07-05 21:23:04 +00002105 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2106 Operands.push_back(AArch64Operand::CreatePrefetch(
2107 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002108 return MatchOperand_Success;
2109 }
2110
2111 if (Tok.isNot(AsmToken::Identifier)) {
2112 TokError("pre-fetch hint expected");
2113 return MatchOperand_ParseFail;
2114 }
2115
Tim Northovere6ae6762016-07-05 21:23:04 +00002116 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2117 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002118 TokError("pre-fetch hint expected");
2119 return MatchOperand_ParseFail;
2120 }
2121
2122 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002123 Operands.push_back(AArch64Operand::CreatePrefetch(
2124 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002125 return MatchOperand_Success;
2126}
2127
Oliver Stannarda34e4702015-12-01 10:48:51 +00002128/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002129OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002130AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2131 MCAsmParser &Parser = getParser();
2132 SMLoc S = getLoc();
2133 const AsmToken &Tok = Parser.getTok();
2134 if (Tok.isNot(AsmToken::Identifier)) {
2135 TokError("invalid operand for instruction");
2136 return MatchOperand_ParseFail;
2137 }
2138
Tim Northovere6ae6762016-07-05 21:23:04 +00002139 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2140 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002141 TokError("invalid operand for instruction");
2142 return MatchOperand_ParseFail;
2143 }
2144
2145 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002146 Operands.push_back(AArch64Operand::CreatePSBHint(
2147 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002148 return MatchOperand_Success;
2149}
2150
Tim Northover3b0846e2014-05-24 12:50:23 +00002151/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2152/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002153OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002154AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002155 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002156 SMLoc S = getLoc();
2157 const MCExpr *Expr;
2158
2159 if (Parser.getTok().is(AsmToken::Hash)) {
2160 Parser.Lex(); // Eat hash token.
2161 }
2162
2163 if (parseSymbolicImmVal(Expr))
2164 return MatchOperand_ParseFail;
2165
2166 AArch64MCExpr::VariantKind ELFRefKind;
2167 MCSymbolRefExpr::VariantKind DarwinRefKind;
2168 int64_t Addend;
2169 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2170 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2171 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2172 // No modifier was specified at all; this is the syntax for an ELF basic
2173 // ADRP relocation (unfortunately).
2174 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002175 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002176 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2177 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2178 Addend != 0) {
2179 Error(S, "gotpage label reference not allowed an addend");
2180 return MatchOperand_ParseFail;
2181 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2182 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2183 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2184 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2185 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2186 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2187 // The operand must be an @page or @gotpage qualified symbolref.
2188 Error(S, "page or gotpage label reference expected");
2189 return MatchOperand_ParseFail;
2190 }
2191 }
2192
2193 // We have either a label reference possibly with addend or an immediate. The
2194 // addend is a raw value here. The linker will adjust it to only reference the
2195 // page.
2196 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2197 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2198
2199 return MatchOperand_Success;
2200}
2201
2202/// tryParseAdrLabel - Parse and validate a source label for the ADR
2203/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002204OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002205AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2206 SMLoc S = getLoc();
2207 const MCExpr *Expr;
2208
Nirav Davee833c6c2016-11-08 18:31:04 +00002209 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002210 if (getParser().parseExpression(Expr))
2211 return MatchOperand_ParseFail;
2212
2213 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2214 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2215
2216 return MatchOperand_Success;
2217}
2218
2219/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002220OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002221AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002222 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002223 SMLoc S = getLoc();
2224
Nirav Davee833c6c2016-11-08 18:31:04 +00002225 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002226
2227 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002228 bool isNegative = parseOptionalToken(AsmToken::Minus);
2229
Tim Northover3b0846e2014-05-24 12:50:23 +00002230 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002231 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002232 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002233 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002234 Val = Tok.getIntVal();
2235 if (Val > 255 || Val < 0) {
2236 TokError("encoded floating point value out of range");
2237 return MatchOperand_ParseFail;
2238 }
2239 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002240 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002241 if (isNegative)
2242 RealVal.changeSign();
2243
Tim Northover3b0846e2014-05-24 12:50:23 +00002244 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002245 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002246
John Brawn5ca5daa2017-04-20 10:13:54 +00002247 // Check for out of range values. As an exception we let Zero through,
2248 // but as tokens instead of an FPImm so that it can be matched by the
2249 // appropriate alias if one exists.
2250 if (RealVal.isPosZero()) {
2251 Parser.Lex(); // Eat the token.
2252 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2253 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2254 return MatchOperand_Success;
2255 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002256 TokError("expected compatible register or floating-point constant");
2257 return MatchOperand_ParseFail;
2258 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002259 }
2260 Parser.Lex(); // Eat the token.
2261 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2262 return MatchOperand_Success;
2263 }
2264
2265 if (!Hash)
2266 return MatchOperand_NoMatch;
2267
2268 TokError("invalid floating point immediate");
2269 return MatchOperand_ParseFail;
2270}
2271
2272/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002273OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002274AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002275 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002276 SMLoc S = getLoc();
2277
2278 if (Parser.getTok().is(AsmToken::Hash))
2279 Parser.Lex(); // Eat '#'
2280 else if (Parser.getTok().isNot(AsmToken::Integer))
2281 // Operand should start from # or should be integer, emit error otherwise.
2282 return MatchOperand_NoMatch;
2283
2284 const MCExpr *Imm;
2285 if (parseSymbolicImmVal(Imm))
2286 return MatchOperand_ParseFail;
2287 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2288 uint64_t ShiftAmount = 0;
2289 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2290 if (MCE) {
2291 int64_t Val = MCE->getValue();
2292 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002293 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002294 ShiftAmount = 12;
2295 }
2296 }
2297 SMLoc E = Parser.getTok().getLoc();
2298 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2299 getContext()));
2300 return MatchOperand_Success;
2301 }
2302
2303 // Eat ','
2304 Parser.Lex();
2305
2306 // The optional operand must be "lsl #N" where N is non-negative.
2307 if (!Parser.getTok().is(AsmToken::Identifier) ||
2308 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2309 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2310 return MatchOperand_ParseFail;
2311 }
2312
2313 // Eat 'lsl'
2314 Parser.Lex();
2315
Nirav Davee833c6c2016-11-08 18:31:04 +00002316 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002317
2318 if (Parser.getTok().isNot(AsmToken::Integer)) {
2319 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2320 return MatchOperand_ParseFail;
2321 }
2322
2323 int64_t ShiftAmount = Parser.getTok().getIntVal();
2324
2325 if (ShiftAmount < 0) {
2326 Error(Parser.getTok().getLoc(), "positive shift amount required");
2327 return MatchOperand_ParseFail;
2328 }
2329 Parser.Lex(); // Eat the number
2330
2331 SMLoc E = Parser.getTok().getLoc();
2332 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2333 S, E, getContext()));
2334 return MatchOperand_Success;
2335}
2336
2337/// parseCondCodeString - Parse a Condition Code string.
2338AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2339 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2340 .Case("eq", AArch64CC::EQ)
2341 .Case("ne", AArch64CC::NE)
2342 .Case("cs", AArch64CC::HS)
2343 .Case("hs", AArch64CC::HS)
2344 .Case("cc", AArch64CC::LO)
2345 .Case("lo", AArch64CC::LO)
2346 .Case("mi", AArch64CC::MI)
2347 .Case("pl", AArch64CC::PL)
2348 .Case("vs", AArch64CC::VS)
2349 .Case("vc", AArch64CC::VC)
2350 .Case("hi", AArch64CC::HI)
2351 .Case("ls", AArch64CC::LS)
2352 .Case("ge", AArch64CC::GE)
2353 .Case("lt", AArch64CC::LT)
2354 .Case("gt", AArch64CC::GT)
2355 .Case("le", AArch64CC::LE)
2356 .Case("al", AArch64CC::AL)
2357 .Case("nv", AArch64CC::NV)
2358 .Default(AArch64CC::Invalid);
2359 return CC;
2360}
2361
2362/// parseCondCode - Parse a Condition Code operand.
2363bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2364 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002365 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002366 SMLoc S = getLoc();
2367 const AsmToken &Tok = Parser.getTok();
2368 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2369
2370 StringRef Cond = Tok.getString();
2371 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2372 if (CC == AArch64CC::Invalid)
2373 return TokError("invalid condition code");
2374 Parser.Lex(); // Eat identifier token.
2375
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002376 if (invertCondCode) {
2377 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2378 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002379 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002380 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002381
2382 Operands.push_back(
2383 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2384 return false;
2385}
2386
2387/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2388/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002389OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002390AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002391 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002392 const AsmToken &Tok = Parser.getTok();
2393 std::string LowerID = Tok.getString().lower();
2394 AArch64_AM::ShiftExtendType ShOp =
2395 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2396 .Case("lsl", AArch64_AM::LSL)
2397 .Case("lsr", AArch64_AM::LSR)
2398 .Case("asr", AArch64_AM::ASR)
2399 .Case("ror", AArch64_AM::ROR)
2400 .Case("msl", AArch64_AM::MSL)
2401 .Case("uxtb", AArch64_AM::UXTB)
2402 .Case("uxth", AArch64_AM::UXTH)
2403 .Case("uxtw", AArch64_AM::UXTW)
2404 .Case("uxtx", AArch64_AM::UXTX)
2405 .Case("sxtb", AArch64_AM::SXTB)
2406 .Case("sxth", AArch64_AM::SXTH)
2407 .Case("sxtw", AArch64_AM::SXTW)
2408 .Case("sxtx", AArch64_AM::SXTX)
2409 .Default(AArch64_AM::InvalidShiftExtend);
2410
2411 if (ShOp == AArch64_AM::InvalidShiftExtend)
2412 return MatchOperand_NoMatch;
2413
2414 SMLoc S = Tok.getLoc();
2415 Parser.Lex();
2416
Nirav Davee833c6c2016-11-08 18:31:04 +00002417 bool Hash = parseOptionalToken(AsmToken::Hash);
2418
Tim Northover3b0846e2014-05-24 12:50:23 +00002419 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2420 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2421 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2422 ShOp == AArch64_AM::MSL) {
2423 // We expect a number here.
2424 TokError("expected #imm after shift specifier");
2425 return MatchOperand_ParseFail;
2426 }
2427
Chad Rosier2ff37b82016-12-27 16:58:09 +00002428 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002429 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2430 Operands.push_back(
2431 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2432 return MatchOperand_Success;
2433 }
2434
Chad Rosier2ff37b82016-12-27 16:58:09 +00002435 // Make sure we do actually have a number, identifier or a parenthesized
2436 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002437 SMLoc E = Parser.getTok().getLoc();
2438 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002439 !Parser.getTok().is(AsmToken::LParen) &&
2440 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002441 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002442 return MatchOperand_ParseFail;
2443 }
2444
2445 const MCExpr *ImmVal;
2446 if (getParser().parseExpression(ImmVal))
2447 return MatchOperand_ParseFail;
2448
2449 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2450 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002451 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002452 return MatchOperand_ParseFail;
2453 }
2454
Jim Grosbach57fd2622014-09-23 22:16:02 +00002455 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002456 Operands.push_back(AArch64Operand::CreateShiftExtend(
2457 ShOp, MCE->getValue(), true, S, E, getContext()));
2458 return MatchOperand_Success;
2459}
2460
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002461static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2462 if (FBS[AArch64::HasV8_1aOps])
2463 Str += "ARMv8.1a";
2464 else if (FBS[AArch64::HasV8_2aOps])
2465 Str += "ARMv8.2a";
2466 else
2467 Str += "(unknown)";
2468}
2469
2470void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2471 SMLoc S) {
2472 const uint16_t Op2 = Encoding & 7;
2473 const uint16_t Cm = (Encoding & 0x78) >> 3;
2474 const uint16_t Cn = (Encoding & 0x780) >> 7;
2475 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2476
2477 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2478
2479 Operands.push_back(
2480 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2481 Operands.push_back(
2482 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2483 Operands.push_back(
2484 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2485 Expr = MCConstantExpr::create(Op2, getContext());
2486 Operands.push_back(
2487 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2488}
2489
Tim Northover3b0846e2014-05-24 12:50:23 +00002490/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2491/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2492bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2493 OperandVector &Operands) {
2494 if (Name.find('.') != StringRef::npos)
2495 return TokError("invalid operand");
2496
2497 Mnemonic = Name;
2498 Operands.push_back(
2499 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2500
Rafael Espindola961d4692014-11-11 05:18:41 +00002501 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002502 const AsmToken &Tok = Parser.getTok();
2503 StringRef Op = Tok.getString();
2504 SMLoc S = Tok.getLoc();
2505
Tim Northover3b0846e2014-05-24 12:50:23 +00002506 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002507 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2508 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002509 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002510 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2511 std::string Str("IC " + std::string(IC->Name) + " requires ");
2512 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2513 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002514 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002515 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002516 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002517 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2518 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002519 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002520 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2521 std::string Str("DC " + std::string(DC->Name) + " requires ");
2522 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2523 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002524 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002525 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002526 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002527 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2528 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002529 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002530 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2531 std::string Str("AT " + std::string(AT->Name) + " requires ");
2532 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2533 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002534 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002535 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002536 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002537 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2538 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002539 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002540 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2541 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2542 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2543 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002544 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002545 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002546 }
2547
Tim Northover3b0846e2014-05-24 12:50:23 +00002548 Parser.Lex(); // Eat operand.
2549
2550 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2551 bool HasRegister = false;
2552
2553 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002554 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002555 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2556 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002557 HasRegister = true;
2558 }
2559
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002560 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002561 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002562 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002563 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002564
Nirav Davee833c6c2016-11-08 18:31:04 +00002565 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2566 return true;
2567
Tim Northover3b0846e2014-05-24 12:50:23 +00002568 return false;
2569}
2570
Alex Bradbury58eba092016-11-01 16:32:05 +00002571OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002572AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002573 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002574 const AsmToken &Tok = Parser.getTok();
2575
2576 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002577 if (parseOptionalToken(AsmToken::Hash) ||
2578 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002579 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002580 const MCExpr *ImmVal;
2581 SMLoc ExprLoc = getLoc();
2582 if (getParser().parseExpression(ImmVal))
2583 return MatchOperand_ParseFail;
2584 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2585 if (!MCE) {
2586 Error(ExprLoc, "immediate value expected for barrier operand");
2587 return MatchOperand_ParseFail;
2588 }
2589 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2590 Error(ExprLoc, "barrier operand out of range");
2591 return MatchOperand_ParseFail;
2592 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002593 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2594 Operands.push_back(AArch64Operand::CreateBarrier(
2595 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002596 return MatchOperand_Success;
2597 }
2598
2599 if (Tok.isNot(AsmToken::Identifier)) {
2600 TokError("invalid operand for instruction");
2601 return MatchOperand_ParseFail;
2602 }
2603
Tim Northover3b0846e2014-05-24 12:50:23 +00002604 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002605 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2606 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002607 TokError("'sy' or #imm operand expected");
2608 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002609 } else if (!DB) {
2610 TokError("invalid barrier option name");
2611 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002612 }
2613
Tim Northovere6ae6762016-07-05 21:23:04 +00002614 Operands.push_back(AArch64Operand::CreateBarrier(
2615 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002616 Parser.Lex(); // Consume the option
2617
2618 return MatchOperand_Success;
2619}
2620
Alex Bradbury58eba092016-11-01 16:32:05 +00002621OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002622AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002623 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002624 const AsmToken &Tok = Parser.getTok();
2625
2626 if (Tok.isNot(AsmToken::Identifier))
2627 return MatchOperand_NoMatch;
2628
Tim Northovere6ae6762016-07-05 21:23:04 +00002629 int MRSReg, MSRReg;
2630 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2631 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2632 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2633 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2634 } else
2635 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002636
Tim Northovere6ae6762016-07-05 21:23:04 +00002637 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2638 unsigned PStateImm = -1;
2639 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2640 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002641
Tim Northovere6ae6762016-07-05 21:23:04 +00002642 Operands.push_back(
2643 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2644 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002645 Parser.Lex(); // Eat identifier
2646
2647 return MatchOperand_Success;
2648}
2649
Florian Hahnc4422242017-11-07 13:07:50 +00002650/// tryParseNeonVectorRegister - Parse a vector register operand.
2651bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002652 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002653 if (Parser.getTok().isNot(AsmToken::Identifier))
2654 return true;
2655
2656 SMLoc S = getLoc();
2657 // Check for a vector register specifier first.
2658 StringRef Kind;
2659 int64_t Reg = tryMatchVectorRegister(Kind, false);
2660 if (Reg == -1)
2661 return true;
2662 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00002663 AArch64Operand::CreateReg(Reg, RegKind::NeonVector, S, getLoc(),
2664 getContext()));
2665
Tim Northover3b0846e2014-05-24 12:50:23 +00002666 // If there was an explicit qualifier, that goes on as a literal text
2667 // operand.
2668 if (!Kind.empty())
2669 Operands.push_back(
2670 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2671
2672 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002673 SMLoc SIdx = getLoc();
2674 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002675 const MCExpr *ImmVal;
2676 if (getParser().parseExpression(ImmVal))
2677 return false;
2678 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2679 if (!MCE) {
2680 TokError("immediate value expected for vector index");
2681 return false;
2682 }
2683
2684 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002685
Nirav Davee833c6c2016-11-08 18:31:04 +00002686 if (parseToken(AsmToken::RBrac, "']' expected"))
2687 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002688
2689 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2690 E, getContext()));
2691 }
2692
2693 return false;
2694}
2695
Florian Hahn91f11e52017-11-07 16:45:48 +00002696// tryParseSVEDataVectorRegister - Try to parse a SVE vector register name with
2697// optional kind specifier. If it is a register specifier, eat the token
2698// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002699OperandMatchResultTy
2700AArch64AsmParser::tryParseSVERegister(int &Reg, StringRef &Kind,
2701 RegKind MatchKind) {
2702 MCAsmParser &Parser = getParser();
2703 const AsmToken &Tok = Parser.getTok();
2704
Florian Hahn91f11e52017-11-07 16:45:48 +00002705 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002706 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002707
2708 StringRef Name = Tok.getString();
2709 // If there is a kind specifier, it's separated from the register name by
2710 // a '.'.
2711 size_t Start = 0, Next = Name.find('.');
2712 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002713 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002714
2715 if (RegNum) {
2716 if (Next != StringRef::npos) {
2717 Kind = Name.slice(Next, StringRef::npos);
2718 if (!isValidSVEKind(Kind)) {
2719 TokError("invalid sve vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002720 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002721 }
2722 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002723 Parser.Lex(); // Eat the register token.
2724
2725 Reg = RegNum;
2726 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002727 }
2728
Sander de Smalen8e607342017-11-15 15:44:43 +00002729 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002730}
2731
Sander de Smalencd6be962017-12-20 11:02:42 +00002732/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2733OperandMatchResultTy
2734AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2735 // Check for a SVE predicate register specifier first.
2736 const SMLoc S = getLoc();
2737 StringRef Kind;
2738 int RegNum = -1;
2739 auto Res = tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
2740 if (Res != MatchOperand_Success)
2741 return Res;
2742
2743 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
2744 .Case("", -1)
2745 .Case(".b", 8)
2746 .Case(".h", 16)
2747 .Case(".s", 32)
2748 .Case(".d", 64)
2749 .Case(".q", 128)
2750 .Default(0);
2751
2752 if (!ElementWidth)
2753 return MatchOperand_NoMatch;
2754
2755 Operands.push_back(
2756 AArch64Operand::CreateReg(RegNum, RegKind::SVEPredicateVector,
2757 ElementWidth, S, getLoc(), getContext()));
2758
Sander de Smalen7868e742018-01-09 11:17:06 +00002759 // Not all predicates are followed by a '/m' or '/z'.
2760 MCAsmParser &Parser = getParser();
2761 if (Parser.getTok().isNot(AsmToken::Slash))
2762 return MatchOperand_Success;
2763
2764 // But when they do they shouldn't have an element type suffix.
2765 if (!Kind.empty()) {
2766 Error(S, "not expecting size suffix");
2767 return MatchOperand_ParseFail;
2768 }
2769
2770 // Add a literal slash as operand
2771 Operands.push_back(
2772 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2773
2774 Parser.Lex(); // Eat the slash.
2775
2776 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002777 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002778 if (Pred != "z" && Pred != "m") {
2779 Error(getLoc(), "expecting 'm' or 'z' predication");
2780 return MatchOperand_ParseFail;
2781 }
2782
2783 // Add zero/merge token.
2784 const char *ZM = Pred == "z" ? "z" : "m";
2785 Operands.push_back(
2786 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2787
2788 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002789 return MatchOperand_Success;
2790}
2791
Tim Northover3b0846e2014-05-24 12:50:23 +00002792/// parseRegister - Parse a non-vector register operand.
2793bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2794 SMLoc S = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00002795 // Try for a vector (neon) register.
2796 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002797 return false;
2798
2799 // Try for a scalar register.
2800 int64_t Reg = tryParseRegister();
2801 if (Reg == -1)
2802 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002803 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2804 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002805
Tim Northover3b0846e2014-05-24 12:50:23 +00002806 return false;
2807}
2808
2809bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002810 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002811 bool HasELFModifier = false;
2812 AArch64MCExpr::VariantKind RefKind;
2813
Nirav Davee833c6c2016-11-08 18:31:04 +00002814 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002815 HasELFModifier = true;
2816
Nirav Davee833c6c2016-11-08 18:31:04 +00002817 if (Parser.getTok().isNot(AsmToken::Identifier))
2818 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002819
2820 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2821 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2822 .Case("lo12", AArch64MCExpr::VK_LO12)
2823 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2824 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2825 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2826 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2827 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2828 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2829 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2830 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2831 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2832 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2833 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2834 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2835 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2836 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2837 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2838 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2839 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2840 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2841 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2842 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2843 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2844 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2845 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2846 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2847 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2848 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2849 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2850 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2851 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2852 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2853 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2854 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2855 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2856 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2857 .Default(AArch64MCExpr::VK_INVALID);
2858
Nirav Davee833c6c2016-11-08 18:31:04 +00002859 if (RefKind == AArch64MCExpr::VK_INVALID)
2860 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002861
2862 Parser.Lex(); // Eat identifier
2863
Nirav Davee833c6c2016-11-08 18:31:04 +00002864 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002865 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002866 }
2867
2868 if (getParser().parseExpression(ImmVal))
2869 return true;
2870
2871 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002872 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002873
2874 return false;
2875}
2876
2877/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2878bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002879 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002880 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2881 SMLoc S = getLoc();
2882 Parser.Lex(); // Eat left bracket token.
2883 StringRef Kind;
2884 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2885 if (FirstReg == -1)
2886 return true;
2887 int64_t PrevReg = FirstReg;
2888 unsigned Count = 1;
2889
Nirav Davee833c6c2016-11-08 18:31:04 +00002890 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002891 SMLoc Loc = getLoc();
2892 StringRef NextKind;
2893 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2894 if (Reg == -1)
2895 return true;
2896 // Any Kind suffices must match on all regs in the list.
2897 if (Kind != NextKind)
2898 return Error(Loc, "mismatched register size suffix");
2899
2900 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2901
2902 if (Space == 0 || Space > 3) {
2903 return Error(Loc, "invalid number of vectors");
2904 }
2905
2906 Count += Space;
2907 }
2908 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002909 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002910 SMLoc Loc = getLoc();
2911 StringRef NextKind;
2912 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2913 if (Reg == -1)
2914 return true;
2915 // Any Kind suffices must match on all regs in the list.
2916 if (Kind != NextKind)
2917 return Error(Loc, "mismatched register size suffix");
2918
2919 // Registers must be incremental (with wraparound at 31)
2920 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2921 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2922 return Error(Loc, "registers must be sequential");
2923
2924 PrevReg = Reg;
2925 ++Count;
2926 }
2927 }
2928
Nirav Davee833c6c2016-11-08 18:31:04 +00002929 if (parseToken(AsmToken::RCurly, "'}' expected"))
2930 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002931
2932 if (Count > 4)
2933 return Error(S, "invalid number of vectors");
2934
2935 unsigned NumElements = 0;
2936 char ElementKind = 0;
2937 if (!Kind.empty())
2938 parseValidVectorKind(Kind, NumElements, ElementKind);
2939
2940 Operands.push_back(AArch64Operand::CreateVectorList(
2941 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
2942
2943 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002944 SMLoc SIdx = getLoc();
2945 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002946 const MCExpr *ImmVal;
2947 if (getParser().parseExpression(ImmVal))
2948 return false;
2949 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2950 if (!MCE) {
2951 TokError("immediate value expected for vector index");
2952 return false;
2953 }
2954
2955 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002956 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002957 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002958
2959 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2960 E, getContext()));
2961 }
2962 return false;
2963}
2964
Alex Bradbury58eba092016-11-01 16:32:05 +00002965OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002966AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002967 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002968 const AsmToken &Tok = Parser.getTok();
2969 if (!Tok.is(AsmToken::Identifier))
2970 return MatchOperand_NoMatch;
2971
Florian Hahnc4422242017-11-07 13:07:50 +00002972 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00002973
2974 MCContext &Ctx = getContext();
2975 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
2976 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
2977 return MatchOperand_NoMatch;
2978
2979 SMLoc S = getLoc();
2980 Parser.Lex(); // Eat register
2981
Nirav Davee833c6c2016-11-08 18:31:04 +00002982 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002983 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00002984 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00002985 return MatchOperand_Success;
2986 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002987
Nirav Davee833c6c2016-11-08 18:31:04 +00002988 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002989
2990 if (Parser.getTok().isNot(AsmToken::Integer)) {
2991 Error(getLoc(), "index must be absent or #0");
2992 return MatchOperand_ParseFail;
2993 }
2994
2995 const MCExpr *ImmVal;
2996 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
2997 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
2998 Error(getLoc(), "index must be absent or #0");
2999 return MatchOperand_ParseFail;
3000 }
3001
3002 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003003 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003004 return MatchOperand_Success;
3005}
3006
3007/// parseOperand - Parse a arm instruction operand. For now this parses the
3008/// operand regardless of the mnemonic.
3009bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3010 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003011 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003012
3013 OperandMatchResultTy ResTy =
3014 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3015
Tim Northover3b0846e2014-05-24 12:50:23 +00003016 // Check if the current operand has a custom associated parser, if so, try to
3017 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003018 if (ResTy == MatchOperand_Success)
3019 return false;
3020 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3021 // there was a match, but an error occurred, in which case, just return that
3022 // the operand parsing failed.
3023 if (ResTy == MatchOperand_ParseFail)
3024 return true;
3025
3026 // Nothing custom, so do general case parsing.
3027 SMLoc S, E;
3028 switch (getLexer().getKind()) {
3029 default: {
3030 SMLoc S = getLoc();
3031 const MCExpr *Expr;
3032 if (parseSymbolicImmVal(Expr))
3033 return Error(S, "invalid operand");
3034
3035 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3036 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3037 return false;
3038 }
3039 case AsmToken::LBrac: {
3040 SMLoc Loc = Parser.getTok().getLoc();
3041 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3042 getContext()));
3043 Parser.Lex(); // Eat '['
3044
3045 // There's no comma after a '[', so we can parse the next operand
3046 // immediately.
3047 return parseOperand(Operands, false, false);
3048 }
3049 case AsmToken::LCurly:
3050 return parseVectorList(Operands);
3051 case AsmToken::Identifier: {
3052 // If we're expecting a Condition Code operand, then just parse that.
3053 if (isCondCode)
3054 return parseCondCode(Operands, invertCondCode);
3055
3056 // If it's a register name, parse it.
3057 if (!parseRegister(Operands))
3058 return false;
3059
3060 // This could be an optional "shift" or "extend" operand.
3061 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3062 // We can only continue if no tokens were eaten.
3063 if (GotShift != MatchOperand_NoMatch)
3064 return GotShift;
3065
3066 // This was not a register so parse other operands that start with an
3067 // identifier (like labels) as expressions and create them as immediates.
3068 const MCExpr *IdVal;
3069 S = getLoc();
3070 if (getParser().parseExpression(IdVal))
3071 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003072 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3073 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3074 return false;
3075 }
3076 case AsmToken::Integer:
3077 case AsmToken::Real:
3078 case AsmToken::Hash: {
3079 // #42 -> immediate.
3080 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003081
3082 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003083
3084 // Parse a negative sign
3085 bool isNegative = false;
3086 if (Parser.getTok().is(AsmToken::Minus)) {
3087 isNegative = true;
3088 // We need to consume this token only when we have a Real, otherwise
3089 // we let parseSymbolicImmVal take care of it
3090 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3091 Parser.Lex();
3092 }
3093
3094 // The only Real that should come through here is a literal #0.0 for
3095 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3096 // so convert the value.
3097 const AsmToken &Tok = Parser.getTok();
3098 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003099 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003100 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3101 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3102 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3103 Mnemonic != "fcmlt")
3104 return TokError("unexpected floating point literal");
3105 else if (IntVal != 0 || isNegative)
3106 return TokError("expected floating-point constant #0.0");
3107 Parser.Lex(); // Eat the token.
3108
3109 Operands.push_back(
3110 AArch64Operand::CreateToken("#0", false, S, getContext()));
3111 Operands.push_back(
3112 AArch64Operand::CreateToken(".0", false, S, getContext()));
3113 return false;
3114 }
3115
3116 const MCExpr *ImmVal;
3117 if (parseSymbolicImmVal(ImmVal))
3118 return true;
3119
3120 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3121 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3122 return false;
3123 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003124 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003125 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003126 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003127 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003128 Parser.Lex(); // Eat '='
3129 const MCExpr *SubExprVal;
3130 if (getParser().parseExpression(SubExprVal))
3131 return true;
3132
David Peixottoae5ba762014-07-18 16:05:14 +00003133 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003134 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003135 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003136
3137 bool IsXReg =
3138 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3139 Operands[1]->getReg());
3140
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003141 MCContext& Ctx = getContext();
3142 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3143 // 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 +00003144 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003145 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3146 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3147 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3148 ShiftAmt += 16;
3149 Imm >>= 16;
3150 }
3151 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3152 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3153 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003154 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003155 if (ShiftAmt)
3156 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3157 ShiftAmt, true, S, E, Ctx));
3158 return false;
3159 }
David Peixottoae5ba762014-07-18 16:05:14 +00003160 APInt Simm = APInt(64, Imm << ShiftAmt);
3161 // check if the immediate is an unsigned or signed 32-bit int for W regs
3162 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3163 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003164 }
3165 // 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 +00003166 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003167 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003168 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3169 return false;
3170 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003171 }
3172}
3173
3174/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3175/// operands.
3176bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3177 StringRef Name, SMLoc NameLoc,
3178 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003179 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003180 Name = StringSwitch<StringRef>(Name.lower())
3181 .Case("beq", "b.eq")
3182 .Case("bne", "b.ne")
3183 .Case("bhs", "b.hs")
3184 .Case("bcs", "b.cs")
3185 .Case("blo", "b.lo")
3186 .Case("bcc", "b.cc")
3187 .Case("bmi", "b.mi")
3188 .Case("bpl", "b.pl")
3189 .Case("bvs", "b.vs")
3190 .Case("bvc", "b.vc")
3191 .Case("bhi", "b.hi")
3192 .Case("bls", "b.ls")
3193 .Case("bge", "b.ge")
3194 .Case("blt", "b.lt")
3195 .Case("bgt", "b.gt")
3196 .Case("ble", "b.le")
3197 .Case("bal", "b.al")
3198 .Case("bnv", "b.nv")
3199 .Default(Name);
3200
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003201 // First check for the AArch64-specific .req directive.
3202 if (Parser.getTok().is(AsmToken::Identifier) &&
3203 Parser.getTok().getIdentifier() == ".req") {
3204 parseDirectiveReq(Name, NameLoc);
3205 // We always return 'error' for this, as we're done with this
3206 // statement and don't need to match the 'instruction."
3207 return true;
3208 }
3209
Tim Northover3b0846e2014-05-24 12:50:23 +00003210 // Create the leading tokens for the mnemonic, split by '.' characters.
3211 size_t Start = 0, Next = Name.find('.');
3212 StringRef Head = Name.slice(Start, Next);
3213
3214 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003215 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3216 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003217
3218 Operands.push_back(
3219 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3220 Mnemonic = Head;
3221
3222 // Handle condition codes for a branch mnemonic
3223 if (Head == "b" && Next != StringRef::npos) {
3224 Start = Next;
3225 Next = Name.find('.', Start + 1);
3226 Head = Name.slice(Start + 1, Next);
3227
3228 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3229 (Head.data() - Name.data()));
3230 AArch64CC::CondCode CC = parseCondCodeString(Head);
3231 if (CC == AArch64CC::Invalid)
3232 return Error(SuffixLoc, "invalid condition code");
3233 Operands.push_back(
3234 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3235 Operands.push_back(
3236 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3237 }
3238
3239 // Add the remaining tokens in the mnemonic.
3240 while (Next != StringRef::npos) {
3241 Start = Next;
3242 Next = Name.find('.', Start + 1);
3243 Head = Name.slice(Start, Next);
3244 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3245 (Head.data() - Name.data()) + 1);
3246 Operands.push_back(
3247 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3248 }
3249
3250 // Conditional compare instructions have a Condition Code operand, which needs
3251 // to be parsed and an immediate operand created.
3252 bool condCodeFourthOperand =
3253 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3254 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3255 Head == "csinc" || Head == "csinv" || Head == "csneg");
3256
3257 // These instructions are aliases to some of the conditional select
3258 // instructions. However, the condition code is inverted in the aliased
3259 // instruction.
3260 //
3261 // FIXME: Is this the correct way to handle these? Or should the parser
3262 // generate the aliased instructions directly?
3263 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3264 bool condCodeThirdOperand =
3265 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3266
3267 // Read the remaining operands.
3268 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3269 // Read the first operand.
3270 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003271 return true;
3272 }
3273
3274 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003275 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003276 // Parse and remember the operand.
3277 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3278 (N == 3 && condCodeThirdOperand) ||
3279 (N == 2 && condCodeSecondOperand),
3280 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003281 return true;
3282 }
3283
3284 // After successfully parsing some operands there are two special cases to
3285 // consider (i.e. notional operands not separated by commas). Both are due
3286 // to memory specifiers:
3287 // + An RBrac will end an address for load/store/prefetch
3288 // + An '!' will indicate a pre-indexed operation.
3289 //
3290 // It's someone else's responsibility to make sure these tokens are sane
3291 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003292
Nirav Davee833c6c2016-11-08 18:31:04 +00003293 SMLoc RLoc = Parser.getTok().getLoc();
3294 if (parseOptionalToken(AsmToken::RBrac))
3295 Operands.push_back(
3296 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3297 SMLoc ELoc = Parser.getTok().getLoc();
3298 if (parseOptionalToken(AsmToken::Exclaim))
3299 Operands.push_back(
3300 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003301
3302 ++N;
3303 }
3304 }
3305
Nirav Davee833c6c2016-11-08 18:31:04 +00003306 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3307 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003308
Tim Northover3b0846e2014-05-24 12:50:23 +00003309 return false;
3310}
3311
3312// FIXME: This entire function is a giant hack to provide us with decent
3313// operand range validation/diagnostics until TableGen/MC can be extended
3314// to support autogeneration of this kind of validation.
3315bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3316 SmallVectorImpl<SMLoc> &Loc) {
3317 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3318 // Check for indexed addressing modes w/ the base register being the
3319 // same as a destination/source register or pair load where
3320 // the Rt == Rt2. All of those are undefined behaviour.
3321 switch (Inst.getOpcode()) {
3322 case AArch64::LDPSWpre:
3323 case AArch64::LDPWpost:
3324 case AArch64::LDPWpre:
3325 case AArch64::LDPXpost:
3326 case AArch64::LDPXpre: {
3327 unsigned Rt = Inst.getOperand(1).getReg();
3328 unsigned Rt2 = Inst.getOperand(2).getReg();
3329 unsigned Rn = Inst.getOperand(3).getReg();
3330 if (RI->isSubRegisterEq(Rn, Rt))
3331 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3332 "is also a destination");
3333 if (RI->isSubRegisterEq(Rn, Rt2))
3334 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3335 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003336 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003337 }
3338 case AArch64::LDPDi:
3339 case AArch64::LDPQi:
3340 case AArch64::LDPSi:
3341 case AArch64::LDPSWi:
3342 case AArch64::LDPWi:
3343 case AArch64::LDPXi: {
3344 unsigned Rt = Inst.getOperand(0).getReg();
3345 unsigned Rt2 = Inst.getOperand(1).getReg();
3346 if (Rt == Rt2)
3347 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3348 break;
3349 }
3350 case AArch64::LDPDpost:
3351 case AArch64::LDPDpre:
3352 case AArch64::LDPQpost:
3353 case AArch64::LDPQpre:
3354 case AArch64::LDPSpost:
3355 case AArch64::LDPSpre:
3356 case AArch64::LDPSWpost: {
3357 unsigned Rt = Inst.getOperand(1).getReg();
3358 unsigned Rt2 = Inst.getOperand(2).getReg();
3359 if (Rt == Rt2)
3360 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3361 break;
3362 }
3363 case AArch64::STPDpost:
3364 case AArch64::STPDpre:
3365 case AArch64::STPQpost:
3366 case AArch64::STPQpre:
3367 case AArch64::STPSpost:
3368 case AArch64::STPSpre:
3369 case AArch64::STPWpost:
3370 case AArch64::STPWpre:
3371 case AArch64::STPXpost:
3372 case AArch64::STPXpre: {
3373 unsigned Rt = Inst.getOperand(1).getReg();
3374 unsigned Rt2 = Inst.getOperand(2).getReg();
3375 unsigned Rn = Inst.getOperand(3).getReg();
3376 if (RI->isSubRegisterEq(Rn, Rt))
3377 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3378 "is also a source");
3379 if (RI->isSubRegisterEq(Rn, Rt2))
3380 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3381 "is also a source");
3382 break;
3383 }
3384 case AArch64::LDRBBpre:
3385 case AArch64::LDRBpre:
3386 case AArch64::LDRHHpre:
3387 case AArch64::LDRHpre:
3388 case AArch64::LDRSBWpre:
3389 case AArch64::LDRSBXpre:
3390 case AArch64::LDRSHWpre:
3391 case AArch64::LDRSHXpre:
3392 case AArch64::LDRSWpre:
3393 case AArch64::LDRWpre:
3394 case AArch64::LDRXpre:
3395 case AArch64::LDRBBpost:
3396 case AArch64::LDRBpost:
3397 case AArch64::LDRHHpost:
3398 case AArch64::LDRHpost:
3399 case AArch64::LDRSBWpost:
3400 case AArch64::LDRSBXpost:
3401 case AArch64::LDRSHWpost:
3402 case AArch64::LDRSHXpost:
3403 case AArch64::LDRSWpost:
3404 case AArch64::LDRWpost:
3405 case AArch64::LDRXpost: {
3406 unsigned Rt = Inst.getOperand(1).getReg();
3407 unsigned Rn = Inst.getOperand(2).getReg();
3408 if (RI->isSubRegisterEq(Rn, Rt))
3409 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3410 "is also a source");
3411 break;
3412 }
3413 case AArch64::STRBBpost:
3414 case AArch64::STRBpost:
3415 case AArch64::STRHHpost:
3416 case AArch64::STRHpost:
3417 case AArch64::STRWpost:
3418 case AArch64::STRXpost:
3419 case AArch64::STRBBpre:
3420 case AArch64::STRBpre:
3421 case AArch64::STRHHpre:
3422 case AArch64::STRHpre:
3423 case AArch64::STRWpre:
3424 case AArch64::STRXpre: {
3425 unsigned Rt = Inst.getOperand(1).getReg();
3426 unsigned Rn = Inst.getOperand(2).getReg();
3427 if (RI->isSubRegisterEq(Rn, Rt))
3428 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3429 "is also a source");
3430 break;
3431 }
3432 }
3433
3434 // Now check immediate ranges. Separate from the above as there is overlap
3435 // in the instructions being checked and this keeps the nested conditionals
3436 // to a minimum.
3437 switch (Inst.getOpcode()) {
3438 case AArch64::ADDSWri:
3439 case AArch64::ADDSXri:
3440 case AArch64::ADDWri:
3441 case AArch64::ADDXri:
3442 case AArch64::SUBSWri:
3443 case AArch64::SUBSXri:
3444 case AArch64::SUBWri:
3445 case AArch64::SUBXri: {
3446 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3447 // some slight duplication here.
3448 if (Inst.getOperand(2).isExpr()) {
3449 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3450 AArch64MCExpr::VariantKind ELFRefKind;
3451 MCSymbolRefExpr::VariantKind DarwinRefKind;
3452 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003453 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3454
3455 // Only allow these with ADDXri.
3456 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3457 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3458 Inst.getOpcode() == AArch64::ADDXri)
3459 return false;
3460
3461 // Only allow these with ADDXri/ADDWri
3462 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3463 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3464 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3465 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3466 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3467 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3468 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3469 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3470 (Inst.getOpcode() == AArch64::ADDXri ||
3471 Inst.getOpcode() == AArch64::ADDWri))
3472 return false;
3473
3474 // Don't allow symbol refs in the immediate field otherwise
3475 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3476 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3477 // 'cmp w0, 'borked')
3478 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003479 }
Diana Picusc93518d2016-10-11 09:17:47 +00003480 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003481 }
3482 return false;
3483 }
3484 default:
3485 return false;
3486 }
3487}
3488
Craig Topper05515562017-10-26 06:46:41 +00003489static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3490 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003491
3492bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3493 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003494 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003495 case Match_InvalidTiedOperand:
3496 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003497 case Match_MissingFeature:
3498 return Error(Loc,
3499 "instruction requires a CPU feature not currently enabled");
3500 case Match_InvalidOperand:
3501 return Error(Loc, "invalid operand for instruction");
3502 case Match_InvalidSuffix:
3503 return Error(Loc, "invalid type suffix for instruction");
3504 case Match_InvalidCondCode:
3505 return Error(Loc, "expected AArch64 condition code");
3506 case Match_AddSubRegExtendSmall:
3507 return Error(Loc,
3508 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3509 case Match_AddSubRegExtendLarge:
3510 return Error(Loc,
3511 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3512 case Match_AddSubSecondSource:
3513 return Error(Loc,
3514 "expected compatible register, symbol or integer in range [0, 4095]");
3515 case Match_LogicalSecondSource:
3516 return Error(Loc, "expected compatible register or logical immediate");
3517 case Match_InvalidMovImm32Shift:
3518 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3519 case Match_InvalidMovImm64Shift:
3520 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3521 case Match_AddSubRegShift32:
3522 return Error(Loc,
3523 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3524 case Match_AddSubRegShift64:
3525 return Error(Loc,
3526 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3527 case Match_InvalidFPImm:
3528 return Error(Loc,
3529 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003530 case Match_InvalidMemoryIndexedSImm6:
3531 return Error(Loc, "index must be an integer in range [-32, 31].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003532 case Match_InvalidMemoryIndexedSImm9:
3533 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003534 case Match_InvalidMemoryIndexedSImm10:
3535 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003536 case Match_InvalidMemoryIndexed4SImm7:
3537 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3538 case Match_InvalidMemoryIndexed8SImm7:
3539 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3540 case Match_InvalidMemoryIndexed16SImm7:
3541 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3542 case Match_InvalidMemoryWExtend8:
3543 return Error(Loc,
3544 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3545 case Match_InvalidMemoryWExtend16:
3546 return Error(Loc,
3547 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3548 case Match_InvalidMemoryWExtend32:
3549 return Error(Loc,
3550 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3551 case Match_InvalidMemoryWExtend64:
3552 return Error(Loc,
3553 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3554 case Match_InvalidMemoryWExtend128:
3555 return Error(Loc,
3556 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3557 case Match_InvalidMemoryXExtend8:
3558 return Error(Loc,
3559 "expected 'lsl' or 'sxtx' with optional shift of #0");
3560 case Match_InvalidMemoryXExtend16:
3561 return Error(Loc,
3562 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3563 case Match_InvalidMemoryXExtend32:
3564 return Error(Loc,
3565 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3566 case Match_InvalidMemoryXExtend64:
3567 return Error(Loc,
3568 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3569 case Match_InvalidMemoryXExtend128:
3570 return Error(Loc,
3571 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3572 case Match_InvalidMemoryIndexed1:
3573 return Error(Loc, "index must be an integer in range [0, 4095].");
3574 case Match_InvalidMemoryIndexed2:
3575 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3576 case Match_InvalidMemoryIndexed4:
3577 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3578 case Match_InvalidMemoryIndexed8:
3579 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3580 case Match_InvalidMemoryIndexed16:
3581 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003582 case Match_InvalidImm0_1:
3583 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003584 case Match_InvalidImm0_7:
3585 return Error(Loc, "immediate must be an integer in range [0, 7].");
3586 case Match_InvalidImm0_15:
3587 return Error(Loc, "immediate must be an integer in range [0, 15].");
3588 case Match_InvalidImm0_31:
3589 return Error(Loc, "immediate must be an integer in range [0, 31].");
3590 case Match_InvalidImm0_63:
3591 return Error(Loc, "immediate must be an integer in range [0, 63].");
3592 case Match_InvalidImm0_127:
3593 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003594 case Match_InvalidImm0_255:
3595 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003596 case Match_InvalidImm0_65535:
3597 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3598 case Match_InvalidImm1_8:
3599 return Error(Loc, "immediate must be an integer in range [1, 8].");
3600 case Match_InvalidImm1_16:
3601 return Error(Loc, "immediate must be an integer in range [1, 16].");
3602 case Match_InvalidImm1_32:
3603 return Error(Loc, "immediate must be an integer in range [1, 32].");
3604 case Match_InvalidImm1_64:
3605 return Error(Loc, "immediate must be an integer in range [1, 64].");
3606 case Match_InvalidIndex1:
3607 return Error(Loc, "expected lane specifier '[1]'");
3608 case Match_InvalidIndexB:
3609 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3610 case Match_InvalidIndexH:
3611 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3612 case Match_InvalidIndexS:
3613 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3614 case Match_InvalidIndexD:
3615 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3616 case Match_InvalidLabel:
3617 return Error(Loc, "expected label or encodable integer pc offset");
3618 case Match_MRS:
3619 return Error(Loc, "expected readable system register");
3620 case Match_MSR:
3621 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003622 case Match_InvalidComplexRotationEven:
3623 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3624 case Match_InvalidComplexRotationOdd:
3625 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003626 case Match_MnemonicFail: {
3627 std::string Suggestion = AArch64MnemonicSpellCheck(
3628 ((AArch64Operand &)*Operands[0]).getToken(),
3629 ComputeAvailableFeatures(STI->getFeatureBits()));
3630 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3631 }
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003632 case Match_InvalidSVEPattern:
3633 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003634 case Match_InvalidSVEPredicateAnyReg:
3635 case Match_InvalidSVEPredicateBReg:
3636 case Match_InvalidSVEPredicateHReg:
3637 case Match_InvalidSVEPredicateSReg:
3638 case Match_InvalidSVEPredicateDReg:
3639 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003640 case Match_InvalidSVEPredicate3bAnyReg:
3641 case Match_InvalidSVEPredicate3bBReg:
3642 case Match_InvalidSVEPredicate3bHReg:
3643 case Match_InvalidSVEPredicate3bSReg:
3644 case Match_InvalidSVEPredicate3bDReg:
3645 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003646 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003647 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003648 }
3649}
3650
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003651static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003652
3653bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3654 OperandVector &Operands,
3655 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003656 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003657 bool MatchingInlineAsm) {
3658 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003659 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3660 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003661
David Blaikie960ea3f2014-06-08 16:18:35 +00003662 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003663 unsigned NumOperands = Operands.size();
3664
3665 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003666 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3667 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003668 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003669 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003670 if (Op3CE) {
3671 uint64_t Op3Val = Op3CE->getValue();
3672 uint64_t NewOp3Val = 0;
3673 uint64_t NewOp4Val = 0;
3674 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003675 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003676 NewOp3Val = (32 - Op3Val) & 0x1f;
3677 NewOp4Val = 31 - Op3Val;
3678 } else {
3679 NewOp3Val = (64 - Op3Val) & 0x3f;
3680 NewOp4Val = 63 - Op3Val;
3681 }
3682
Jim Grosbach13760bd2015-05-30 01:25:56 +00003683 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3684 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003685
3686 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003687 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003688 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003689 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3690 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3691 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003692 }
3693 }
Tim Northover03b99f62015-04-30 18:28:58 +00003694 } else if (NumOperands == 4 && Tok == "bfc") {
3695 // FIXME: Horrible hack to handle BFC->BFM alias.
3696 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3697 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3698 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3699
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003700 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003701 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3702 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3703
3704 if (LSBCE && WidthCE) {
3705 uint64_t LSB = LSBCE->getValue();
3706 uint64_t Width = WidthCE->getValue();
3707
3708 uint64_t RegWidth = 0;
3709 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3710 Op1.getReg()))
3711 RegWidth = 64;
3712 else
3713 RegWidth = 32;
3714
3715 if (LSB >= RegWidth)
3716 return Error(LSBOp.getStartLoc(),
3717 "expected integer in range [0, 31]");
3718 if (Width < 1 || Width > RegWidth)
3719 return Error(WidthOp.getStartLoc(),
3720 "expected integer in range [1, 32]");
3721
3722 uint64_t ImmR = 0;
3723 if (RegWidth == 32)
3724 ImmR = (32 - LSB) & 0x1f;
3725 else
3726 ImmR = (64 - LSB) & 0x3f;
3727
3728 uint64_t ImmS = Width - 1;
3729
3730 if (ImmR != 0 && ImmS >= ImmR)
3731 return Error(WidthOp.getStartLoc(),
3732 "requested insert overflows register");
3733
Jim Grosbach13760bd2015-05-30 01:25:56 +00003734 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3735 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003736 Operands[0] = AArch64Operand::CreateToken(
3737 "bfm", false, Op.getStartLoc(), getContext());
3738 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003739 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3740 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003741 Operands[3] = AArch64Operand::CreateImm(
3742 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3743 Operands.emplace_back(
3744 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3745 WidthOp.getEndLoc(), getContext()));
3746 }
3747 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003748 } else if (NumOperands == 5) {
3749 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3750 // UBFIZ -> UBFM aliases.
3751 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003752 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3753 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3754 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003755
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003756 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003757 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3758 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003759
3760 if (Op3CE && Op4CE) {
3761 uint64_t Op3Val = Op3CE->getValue();
3762 uint64_t Op4Val = Op4CE->getValue();
3763
3764 uint64_t RegWidth = 0;
3765 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003766 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003767 RegWidth = 64;
3768 else
3769 RegWidth = 32;
3770
3771 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003772 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003773 "expected integer in range [0, 31]");
3774 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003775 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003776 "expected integer in range [1, 32]");
3777
3778 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003779 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003780 NewOp3Val = (32 - Op3Val) & 0x1f;
3781 else
3782 NewOp3Val = (64 - Op3Val) & 0x3f;
3783
3784 uint64_t NewOp4Val = Op4Val - 1;
3785
3786 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003787 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003788 "requested insert overflows register");
3789
3790 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003791 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003792 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003793 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003794 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003795 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003796 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003797 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003798 if (Tok == "bfi")
3799 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003800 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003801 else if (Tok == "sbfiz")
3802 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003803 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003804 else if (Tok == "ubfiz")
3805 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003806 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003807 else
3808 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003809 }
3810 }
3811
3812 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3813 // UBFX -> UBFM aliases.
3814 } else if (NumOperands == 5 &&
3815 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003816 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3817 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3818 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003819
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003820 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003821 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3822 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003823
3824 if (Op3CE && Op4CE) {
3825 uint64_t Op3Val = Op3CE->getValue();
3826 uint64_t Op4Val = Op4CE->getValue();
3827
3828 uint64_t RegWidth = 0;
3829 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003830 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003831 RegWidth = 64;
3832 else
3833 RegWidth = 32;
3834
3835 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003836 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003837 "expected integer in range [0, 31]");
3838 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003839 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003840 "expected integer in range [1, 32]");
3841
3842 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3843
3844 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003845 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003846 "requested extract overflows register");
3847
3848 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003849 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003850 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003851 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003852 if (Tok == "bfxil")
3853 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003854 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003855 else if (Tok == "sbfx")
3856 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003857 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003858 else if (Tok == "ubfx")
3859 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003860 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003861 else
3862 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003863 }
3864 }
3865 }
3866 }
Tim Northover9097a072017-12-18 10:36:00 +00003867
3868 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
3869 // instruction for FP registers correctly in some rare circumstances. Convert
3870 // it to a safe instruction and warn (because silently changing someone's
3871 // assembly is rude).
3872 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
3873 NumOperands == 4 && Tok == "movi") {
3874 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3875 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3876 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3877 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
3878 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
3879 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
3880 if (Suffix.lower() == ".2d" &&
3881 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
3882 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
3883 " correctly on this CPU, converting to equivalent movi.16b");
3884 // Switch the suffix to .16b.
3885 unsigned Idx = Op1.isToken() ? 1 : 2;
3886 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
3887 getContext());
3888 }
3889 }
3890 }
3891
Tim Northover3b0846e2014-05-24 12:50:23 +00003892 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3893 // InstAlias can't quite handle this since the reg classes aren't
3894 // subclasses.
3895 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3896 // The source register can be Wn here, but the matcher expects a
3897 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003898 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003899 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003900 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003901 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3902 Op.getStartLoc(), Op.getEndLoc(),
3903 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003904 }
3905 }
3906 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3907 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003908 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003909 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003910 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003911 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003912 // The source register can be Wn here, but the matcher expects a
3913 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003914 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003915 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003916 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003917 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3918 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003919 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003920 }
3921 }
3922 }
3923 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3924 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003925 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003926 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003927 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003928 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003929 // The source register can be Wn here, but the matcher expects a
3930 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003931 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003932 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003933 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003934 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3935 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003936 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003937 }
3938 }
3939 }
3940
Tim Northover3b0846e2014-05-24 12:50:23 +00003941 MCInst Inst;
3942 // First try to match against the secondary set of tables containing the
3943 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3944 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003945 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003946
3947 // If that fails, try against the alternate table containing long-form NEON:
3948 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003949 if (MatchResult != Match_Success) {
3950 // But first, save the short-form match result: we can use it in case the
3951 // long-form match also fails.
3952 auto ShortFormNEONErrorInfo = ErrorInfo;
3953 auto ShortFormNEONMatchResult = MatchResult;
3954
Tim Northover3b0846e2014-05-24 12:50:23 +00003955 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003956 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003957
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003958 // Now, both matches failed, and the long-form match failed on the mnemonic
3959 // suffix token operand. The short-form match failure is probably more
3960 // relevant: use it instead.
3961 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003962 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003963 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3964 MatchResult = ShortFormNEONMatchResult;
3965 ErrorInfo = ShortFormNEONErrorInfo;
3966 }
3967 }
3968
Tim Northover3b0846e2014-05-24 12:50:23 +00003969 switch (MatchResult) {
3970 case Match_Success: {
3971 // Perform range checking and other semantic validations
3972 SmallVector<SMLoc, 8> OperandLocs;
3973 NumOperands = Operands.size();
3974 for (unsigned i = 1; i < NumOperands; ++i)
3975 OperandLocs.push_back(Operands[i]->getStartLoc());
3976 if (validateInstruction(Inst, OperandLocs))
3977 return true;
3978
3979 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003980 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00003981 return false;
3982 }
3983 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003984 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003985 // Special case the error message for the very common case where only
3986 // a single subtarget feature is missing (neon, e.g.).
3987 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003988 uint64_t Mask = 1;
3989 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
3990 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003991 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003992 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00003993 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003994 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00003995 }
3996 return Error(IDLoc, Msg);
3997 }
3998 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003999 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004000 case Match_InvalidOperand: {
4001 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004002
Tim Northover26bb14e2014-08-18 11:49:42 +00004003 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004004 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004005 return Error(IDLoc, "too few operands for instruction",
4006 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004007
David Blaikie960ea3f2014-06-08 16:18:35 +00004008 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004009 if (ErrorLoc == SMLoc())
4010 ErrorLoc = IDLoc;
4011 }
4012 // If the match failed on a suffix token operand, tweak the diagnostic
4013 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004014 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4015 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004016 MatchResult = Match_InvalidSuffix;
4017
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004018 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004019 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004020 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004021 case Match_InvalidMemoryIndexed1:
4022 case Match_InvalidMemoryIndexed2:
4023 case Match_InvalidMemoryIndexed4:
4024 case Match_InvalidMemoryIndexed8:
4025 case Match_InvalidMemoryIndexed16:
4026 case Match_InvalidCondCode:
4027 case Match_AddSubRegExtendSmall:
4028 case Match_AddSubRegExtendLarge:
4029 case Match_AddSubSecondSource:
4030 case Match_LogicalSecondSource:
4031 case Match_AddSubRegShift32:
4032 case Match_AddSubRegShift64:
4033 case Match_InvalidMovImm32Shift:
4034 case Match_InvalidMovImm64Shift:
4035 case Match_InvalidFPImm:
4036 case Match_InvalidMemoryWExtend8:
4037 case Match_InvalidMemoryWExtend16:
4038 case Match_InvalidMemoryWExtend32:
4039 case Match_InvalidMemoryWExtend64:
4040 case Match_InvalidMemoryWExtend128:
4041 case Match_InvalidMemoryXExtend8:
4042 case Match_InvalidMemoryXExtend16:
4043 case Match_InvalidMemoryXExtend32:
4044 case Match_InvalidMemoryXExtend64:
4045 case Match_InvalidMemoryXExtend128:
Sander de Smalen909cf952018-01-19 15:22:00 +00004046 case Match_InvalidMemoryIndexedSImm6:
Tim Northover3b0846e2014-05-24 12:50:23 +00004047 case Match_InvalidMemoryIndexed4SImm7:
4048 case Match_InvalidMemoryIndexed8SImm7:
4049 case Match_InvalidMemoryIndexed16SImm7:
4050 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004051 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004052 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004053 case Match_InvalidImm0_7:
4054 case Match_InvalidImm0_15:
4055 case Match_InvalidImm0_31:
4056 case Match_InvalidImm0_63:
4057 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004058 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004059 case Match_InvalidImm0_65535:
4060 case Match_InvalidImm1_8:
4061 case Match_InvalidImm1_16:
4062 case Match_InvalidImm1_32:
4063 case Match_InvalidImm1_64:
4064 case Match_InvalidIndex1:
4065 case Match_InvalidIndexB:
4066 case Match_InvalidIndexH:
4067 case Match_InvalidIndexS:
4068 case Match_InvalidIndexD:
4069 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004070 case Match_InvalidComplexRotationEven:
4071 case Match_InvalidComplexRotationOdd:
Sander de Smalencd6be962017-12-20 11:02:42 +00004072 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004073 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004074 case Match_InvalidSVEPredicateBReg:
4075 case Match_InvalidSVEPredicateHReg:
4076 case Match_InvalidSVEPredicateSReg:
4077 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004078 case Match_InvalidSVEPredicate3bAnyReg:
4079 case Match_InvalidSVEPredicate3bBReg:
4080 case Match_InvalidSVEPredicate3bHReg:
4081 case Match_InvalidSVEPredicate3bSReg:
4082 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004083 case Match_MSR:
4084 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004085 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004086 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004087 // Any time we get here, there's nothing fancy to do. Just get the
4088 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004089 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004090 if (ErrorLoc == SMLoc())
4091 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004092 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004093 }
4094 }
4095
4096 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004097}
4098
4099/// ParseDirective parses the arm specific directives
4100bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004101 const MCObjectFileInfo::Environment Format =
4102 getContext().getObjectFileInfo()->getObjectFileType();
4103 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4104 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004105
Tim Northover3b0846e2014-05-24 12:50:23 +00004106 StringRef IDVal = DirectiveID.getIdentifier();
4107 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004108 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004109 parseDirectiveArch(Loc);
4110 else if (IDVal == ".cpu")
4111 parseDirectiveCPU(Loc);
4112 else if (IDVal == ".hword")
4113 parseDirectiveWord(2, Loc);
4114 else if (IDVal == ".word")
4115 parseDirectiveWord(4, Loc);
4116 else if (IDVal == ".xword")
4117 parseDirectiveWord(8, Loc);
4118 else if (IDVal == ".tlsdesccall")
4119 parseDirectiveTLSDescCall(Loc);
4120 else if (IDVal == ".ltorg" || IDVal == ".pool")
4121 parseDirectiveLtorg(Loc);
4122 else if (IDVal == ".unreq")
4123 parseDirectiveUnreq(Loc);
4124 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004125 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004126 parseDirectiveInst(Loc);
4127 else
4128 return true;
4129 } else if (IDVal == MCLOHDirectiveName())
4130 parseDirectiveLOH(IDVal, Loc);
4131 else
4132 return true;
4133 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004134}
4135
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004136static const struct {
4137 const char *Name;
4138 const FeatureBitset Features;
4139} ExtensionMap[] = {
4140 { "crc", {AArch64::FeatureCRC} },
4141 { "crypto", {AArch64::FeatureCrypto} },
4142 { "fp", {AArch64::FeatureFPARMv8} },
4143 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004144 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004145 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004146
4147 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004148 { "pan", {} },
4149 { "lor", {} },
4150 { "rdma", {} },
4151 { "profile", {} },
4152};
4153
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004154/// parseDirectiveArch
4155/// ::= .arch token
4156bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4157 SMLoc ArchLoc = getLoc();
4158
4159 StringRef Arch, ExtensionString;
4160 std::tie(Arch, ExtensionString) =
4161 getParser().parseStringToEndOfStatement().trim().split('+');
4162
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004163 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4164 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004165 return Error(ArchLoc, "unknown arch name");
4166
4167 if (parseToken(AsmToken::EndOfStatement))
4168 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004169
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004170 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004171 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004172 AArch64::getArchFeatures(ID, AArch64Features);
4173 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4174 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004175
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004176 MCSubtargetInfo &STI = copySTI();
4177 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4178 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4179
4180 SmallVector<StringRef, 4> RequestedExtensions;
4181 if (!ExtensionString.empty())
4182 ExtensionString.split(RequestedExtensions, '+');
4183
4184 FeatureBitset Features = STI.getFeatureBits();
4185 for (auto Name : RequestedExtensions) {
4186 bool EnableFeature = true;
4187
4188 if (Name.startswith_lower("no")) {
4189 EnableFeature = false;
4190 Name = Name.substr(2);
4191 }
4192
4193 for (const auto &Extension : ExtensionMap) {
4194 if (Extension.Name != Name)
4195 continue;
4196
4197 if (Extension.Features.none())
4198 report_fatal_error("unsupported architectural extension: " + Name);
4199
4200 FeatureBitset ToggleFeatures = EnableFeature
4201 ? (~Features & Extension.Features)
4202 : ( Features & Extension.Features);
4203 uint64_t Features =
4204 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4205 setAvailableFeatures(Features);
4206 break;
4207 }
4208 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004209 return false;
4210}
4211
Tim Northover8b96c7e2017-05-15 19:42:15 +00004212static SMLoc incrementLoc(SMLoc L, int Offset) {
4213 return SMLoc::getFromPointer(L.getPointer() + Offset);
4214}
4215
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004216/// parseDirectiveCPU
4217/// ::= .cpu id
4218bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004219 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004220
4221 StringRef CPU, ExtensionString;
4222 std::tie(CPU, ExtensionString) =
4223 getParser().parseStringToEndOfStatement().trim().split('+');
4224
Nirav Davee833c6c2016-11-08 18:31:04 +00004225 if (parseToken(AsmToken::EndOfStatement))
4226 return true;
4227
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004228 SmallVector<StringRef, 4> RequestedExtensions;
4229 if (!ExtensionString.empty())
4230 ExtensionString.split(RequestedExtensions, '+');
4231
4232 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4233 // once that is tablegen'ed
4234 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004235 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004236 return false;
4237 }
4238
4239 MCSubtargetInfo &STI = copySTI();
4240 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004241 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004242
4243 FeatureBitset Features = STI.getFeatureBits();
4244 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004245 // Advance source location past '+'.
4246 CurLoc = incrementLoc(CurLoc, 1);
4247
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004248 bool EnableFeature = true;
4249
4250 if (Name.startswith_lower("no")) {
4251 EnableFeature = false;
4252 Name = Name.substr(2);
4253 }
4254
Tim Northover8b96c7e2017-05-15 19:42:15 +00004255 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004256 for (const auto &Extension : ExtensionMap) {
4257 if (Extension.Name != Name)
4258 continue;
4259
4260 if (Extension.Features.none())
4261 report_fatal_error("unsupported architectural extension: " + Name);
4262
4263 FeatureBitset ToggleFeatures = EnableFeature
4264 ? (~Features & Extension.Features)
4265 : ( Features & Extension.Features);
4266 uint64_t Features =
4267 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4268 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004269 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004270
4271 break;
4272 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004273
4274 if (!FoundExtension)
4275 Error(CurLoc, "unsupported architectural extension");
4276
4277 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004278 }
4279 return false;
4280}
4281
Tim Northover3b0846e2014-05-24 12:50:23 +00004282/// parseDirectiveWord
4283/// ::= .word [ expression (, expression)* ]
4284bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004285 auto parseOp = [&]() -> bool {
4286 const MCExpr *Value;
4287 if (getParser().parseExpression(Value))
4288 return true;
4289 getParser().getStreamer().EmitValue(Value, Size, L);
4290 return false;
4291 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004292
Nirav Davee833c6c2016-11-08 18:31:04 +00004293 if (parseMany(parseOp))
4294 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004295 return false;
4296}
4297
Chad Rosierdcd2a302014-10-22 20:35:57 +00004298/// parseDirectiveInst
4299/// ::= .inst opcode [, ...]
4300bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004301 if (getLexer().is(AsmToken::EndOfStatement))
4302 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004303
Nirav Davee833c6c2016-11-08 18:31:04 +00004304 auto parseOp = [&]() -> bool {
4305 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004306 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004307 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4308 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004309 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004310 if (check(!Value, L, "expected constant expression"))
4311 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004312 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004313 return false;
4314 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004315
Nirav Davee833c6c2016-11-08 18:31:04 +00004316 if (parseMany(parseOp))
4317 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004318 return false;
4319}
4320
Tim Northover3b0846e2014-05-24 12:50:23 +00004321// parseDirectiveTLSDescCall:
4322// ::= .tlsdesccall symbol
4323bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4324 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004325 if (check(getParser().parseIdentifier(Name), L,
4326 "expected symbol after directive") ||
4327 parseToken(AsmToken::EndOfStatement))
4328 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004329
Jim Grosbach6f482002015-05-18 18:43:14 +00004330 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004331 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4332 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004333
4334 MCInst Inst;
4335 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004336 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004337
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004338 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004339 return false;
4340}
4341
4342/// ::= .loh <lohName | lohId> label1, ..., labelN
4343/// The number of arguments depends on the loh identifier.
4344bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004345 MCLOHType Kind;
4346 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4347 if (getParser().getTok().isNot(AsmToken::Integer))
4348 return TokError("expected an identifier or a number in directive");
4349 // We successfully get a numeric value for the identifier.
4350 // Check if it is valid.
4351 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004352 if (Id <= -1U && !isValidMCLOHType(Id))
4353 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004354 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004355 } else {
4356 StringRef Name = getTok().getIdentifier();
4357 // We successfully parse an identifier.
4358 // Check if it is a recognized one.
4359 int Id = MCLOHNameToId(Name);
4360
4361 if (Id == -1)
4362 return TokError("invalid identifier in directive");
4363 Kind = (MCLOHType)Id;
4364 }
4365 // Consume the identifier.
4366 Lex();
4367 // Get the number of arguments of this LOH.
4368 int NbArgs = MCLOHIdToNbArgs(Kind);
4369
4370 assert(NbArgs != -1 && "Invalid number of arguments");
4371
4372 SmallVector<MCSymbol *, 3> Args;
4373 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4374 StringRef Name;
4375 if (getParser().parseIdentifier(Name))
4376 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004377 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004378
4379 if (Idx + 1 == NbArgs)
4380 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004381 if (parseToken(AsmToken::Comma,
4382 "unexpected token in '" + Twine(IDVal) + "' directive"))
4383 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004384 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004385 if (parseToken(AsmToken::EndOfStatement,
4386 "unexpected token in '" + Twine(IDVal) + "' directive"))
4387 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004388
4389 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4390 return false;
4391}
4392
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004393/// parseDirectiveLtorg
4394/// ::= .ltorg | .pool
4395bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004396 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4397 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004398 getTargetStreamer().emitCurrentConstantPool();
4399 return false;
4400}
4401
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004402/// parseDirectiveReq
4403/// ::= name .req registername
4404bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004405 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004406 Parser.Lex(); // Eat the '.req' token.
4407 SMLoc SRegLoc = getLoc();
Sander de Smalen8e607342017-11-15 15:44:43 +00004408 int RegNum = tryParseRegister();
Florian Hahnc4422242017-11-07 13:07:50 +00004409 RegKind RegisterKind = RegKind::Scalar;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004410
Sander de Smalen8e607342017-11-15 15:44:43 +00004411 if (RegNum == -1) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004412 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004413 RegisterKind = RegKind::NeonVector;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004414 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004415 if (!Kind.empty())
4416 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004417 }
4418
Sander de Smalen8e607342017-11-15 15:44:43 +00004419 if (RegNum == -1) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004420 StringRef Kind;
4421 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen8e607342017-11-15 15:44:43 +00004422 OperandMatchResultTy Res =
4423 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4424
4425 if (Res == MatchOperand_ParseFail)
4426 return true;
4427
4428 if (Res == MatchOperand_Success && !Kind.empty())
4429 return Error(SRegLoc,
4430 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004431 }
4432
Sander de Smalencd6be962017-12-20 11:02:42 +00004433 if (RegNum == -1) {
4434 StringRef Kind;
4435 RegisterKind = RegKind::SVEPredicateVector;
4436 OperandMatchResultTy Res =
4437 tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
4438
4439 if (Res == MatchOperand_ParseFail)
4440 return true;
4441
4442 if (Res == MatchOperand_Success && !Kind.empty())
4443 return Error(SRegLoc,
4444 "sve predicate register without type specifier expected");
4445 }
4446
Sander de Smalen8e607342017-11-15 15:44:43 +00004447 if (RegNum == -1)
Nirav Dave2364748a2016-09-16 18:30:20 +00004448 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004449
4450 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004451 if (parseToken(AsmToken::EndOfStatement,
4452 "unexpected input in .req directive"))
4453 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004454
Sander de Smalen8e607342017-11-15 15:44:43 +00004455 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004456 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004457 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4458
Nirav Dave2364748a2016-09-16 18:30:20 +00004459 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004460}
4461
4462/// parseDirectiveUneq
4463/// ::= .unreq registername
4464bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004465 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004466 if (getTok().isNot(AsmToken::Identifier))
4467 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004468 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4469 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004470 if (parseToken(AsmToken::EndOfStatement))
4471 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004472 return false;
4473}
4474
Tim Northover3b0846e2014-05-24 12:50:23 +00004475bool
4476AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4477 AArch64MCExpr::VariantKind &ELFRefKind,
4478 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4479 int64_t &Addend) {
4480 ELFRefKind = AArch64MCExpr::VK_INVALID;
4481 DarwinRefKind = MCSymbolRefExpr::VK_None;
4482 Addend = 0;
4483
4484 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4485 ELFRefKind = AE->getKind();
4486 Expr = AE->getSubExpr();
4487 }
4488
4489 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4490 if (SE) {
4491 // It's a simple symbol reference with no addend.
4492 DarwinRefKind = SE->getKind();
4493 return true;
4494 }
4495
4496 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4497 if (!BE)
4498 return false;
4499
4500 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4501 if (!SE)
4502 return false;
4503 DarwinRefKind = SE->getKind();
4504
4505 if (BE->getOpcode() != MCBinaryExpr::Add &&
4506 BE->getOpcode() != MCBinaryExpr::Sub)
4507 return false;
4508
4509 // See if the addend is is a constant, otherwise there's more going
4510 // on here than we can deal with.
4511 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4512 if (!AddendExpr)
4513 return false;
4514
4515 Addend = AddendExpr->getValue();
4516 if (BE->getOpcode() == MCBinaryExpr::Sub)
4517 Addend = -Addend;
4518
4519 // It's some symbol reference + a constant addend, but really
4520 // shouldn't use both Darwin and ELF syntax.
4521 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4522 DarwinRefKind == MCSymbolRefExpr::VK_None;
4523}
4524
4525/// Force static initialization.
4526extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004527 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4528 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4529 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004530}
4531
4532#define GET_REGISTER_MATCHER
4533#define GET_SUBTARGET_FEATURE_NAME
4534#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004535#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004536#include "AArch64GenAsmMatcher.inc"
4537
4538// Define this matcher function after the auto-generated include so we
4539// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004540unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004541 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004542 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004543 // If the kind is a token for a literal immediate, check if our asm
4544 // operand matches. This is for InstAliases which have a fixed-value
4545 // immediate in the syntax.
4546 int64_t ExpectedVal;
4547 switch (Kind) {
4548 default:
4549 return Match_InvalidOperand;
4550 case MCK__35_0:
4551 ExpectedVal = 0;
4552 break;
4553 case MCK__35_1:
4554 ExpectedVal = 1;
4555 break;
4556 case MCK__35_12:
4557 ExpectedVal = 12;
4558 break;
4559 case MCK__35_16:
4560 ExpectedVal = 16;
4561 break;
4562 case MCK__35_2:
4563 ExpectedVal = 2;
4564 break;
4565 case MCK__35_24:
4566 ExpectedVal = 24;
4567 break;
4568 case MCK__35_3:
4569 ExpectedVal = 3;
4570 break;
4571 case MCK__35_32:
4572 ExpectedVal = 32;
4573 break;
4574 case MCK__35_4:
4575 ExpectedVal = 4;
4576 break;
4577 case MCK__35_48:
4578 ExpectedVal = 48;
4579 break;
4580 case MCK__35_6:
4581 ExpectedVal = 6;
4582 break;
4583 case MCK__35_64:
4584 ExpectedVal = 64;
4585 break;
4586 case MCK__35_8:
4587 ExpectedVal = 8;
4588 break;
4589 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004590 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004591 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004592 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004593 if (!CE)
4594 return Match_InvalidOperand;
4595 if (CE->getValue() == ExpectedVal)
4596 return Match_Success;
4597 return Match_InvalidOperand;
4598}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004599
Alex Bradbury58eba092016-11-01 16:32:05 +00004600OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004601AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4602
4603 SMLoc S = getLoc();
4604
4605 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4606 Error(S, "expected register");
4607 return MatchOperand_ParseFail;
4608 }
4609
4610 int FirstReg = tryParseRegister();
4611 if (FirstReg == -1) {
4612 return MatchOperand_ParseFail;
4613 }
4614 const MCRegisterClass &WRegClass =
4615 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4616 const MCRegisterClass &XRegClass =
4617 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4618
4619 bool isXReg = XRegClass.contains(FirstReg),
4620 isWReg = WRegClass.contains(FirstReg);
4621 if (!isXReg && !isWReg) {
4622 Error(S, "expected first even register of a "
4623 "consecutive same-size even/odd register pair");
4624 return MatchOperand_ParseFail;
4625 }
4626
4627 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4628 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4629
4630 if (FirstEncoding & 0x1) {
4631 Error(S, "expected first even register of a "
4632 "consecutive same-size even/odd register pair");
4633 return MatchOperand_ParseFail;
4634 }
4635
4636 SMLoc M = getLoc();
4637 if (getParser().getTok().isNot(AsmToken::Comma)) {
4638 Error(M, "expected comma");
4639 return MatchOperand_ParseFail;
4640 }
4641 // Eat the comma
4642 getParser().Lex();
4643
4644 SMLoc E = getLoc();
4645 int SecondReg = tryParseRegister();
4646 if (SecondReg ==-1) {
4647 return MatchOperand_ParseFail;
4648 }
4649
Eugene Zelenko049b0172017-01-06 00:30:53 +00004650 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004651 (isXReg && !XRegClass.contains(SecondReg)) ||
4652 (isWReg && !WRegClass.contains(SecondReg))) {
4653 Error(E,"expected second odd register of a "
4654 "consecutive same-size even/odd register pair");
4655 return MatchOperand_ParseFail;
4656 }
Joel Jones504bf332016-10-24 13:37:13 +00004657
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004658 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004659 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004660 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4661 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4662 } else {
4663 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4664 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4665 }
4666
Florian Hahnc4422242017-11-07 13:07:50 +00004667 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4668 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004669
4670 return MatchOperand_Success;
4671}
Florian Hahn91f11e52017-11-07 16:45:48 +00004672
4673template <bool ParseSuffix>
4674OperandMatchResultTy
4675AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004676 const SMLoc S = getLoc();
4677 // Check for a SVE vector register specifier first.
Sander de Smalen8e607342017-11-15 15:44:43 +00004678 int RegNum = -1;
Florian Hahn91f11e52017-11-07 16:45:48 +00004679 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004680
Sander de Smalen8e607342017-11-15 15:44:43 +00004681 OperandMatchResultTy Res =
4682 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4683
4684 if (Res != MatchOperand_Success)
4685 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004686
4687 if (ParseSuffix && Kind.empty())
4688 return MatchOperand_NoMatch;
4689
4690 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
4691 .Case("", -1)
4692 .Case(".b", 8)
4693 .Case(".h", 16)
4694 .Case(".s", 32)
4695 .Case(".d", 64)
4696 .Case(".q", 128)
4697 .Default(0);
4698 if (!ElementWidth)
4699 return MatchOperand_NoMatch;
4700
4701 Operands.push_back(
4702 AArch64Operand::CreateReg(RegNum, RegKind::SVEDataVector, ElementWidth,
4703 S, S, getContext()));
4704
4705 return MatchOperand_Success;
4706}
Sander de Smalen245e0e62018-01-22 10:46:00 +00004707
4708OperandMatchResultTy
4709AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
4710 MCAsmParser &Parser = getParser();
4711
4712 SMLoc SS = getLoc();
4713 const AsmToken &TokE = Parser.getTok();
4714 bool IsHash = TokE.is(AsmToken::Hash);
4715
4716 if (!IsHash && TokE.isNot(AsmToken::Identifier))
4717 return MatchOperand_NoMatch;
4718
4719 int64_t Pattern;
4720 if (IsHash) {
4721 Parser.Lex(); // Eat hash
4722
4723 // Parse the immediate operand.
4724 const MCExpr *ImmVal;
4725 SS = getLoc();
4726 if (Parser.parseExpression(ImmVal))
4727 return MatchOperand_ParseFail;
4728
4729 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4730 if (!MCE)
4731 return MatchOperand_ParseFail;
4732
4733 Pattern = MCE->getValue();
4734 } else {
4735 // Parse the pattern
4736 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
4737 if (!Pat)
4738 return MatchOperand_NoMatch;
4739
4740 Parser.Lex();
4741 Pattern = Pat->Encoding;
4742 assert(Pattern >= 0 && Pattern < 32);
4743 }
4744
4745 Operands.push_back(
4746 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
4747 SS, getLoc(), getContext()));
4748
4749 return MatchOperand_Success;
4750}