blob: 83764aab90556a88102b349c86fe9633d03b6294 [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
Reid Kleckner37517a22017-12-18 20:58:25 +000062enum class RegKind {Scalar, NeonVector, SVEDataVector};
Florian Hahnc4422242017-11-07 13:07:50 +000063
Tim Northover3b0846e2014-05-24 12:50:23 +000064class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000065private:
66 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000067
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000068 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000069 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000070
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000071 AArch64TargetStreamer &getTargetStreamer() {
72 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
73 return static_cast<AArch64TargetStreamer &>(TS);
74 }
75
Rafael Espindola961d4692014-11-11 05:18:41 +000076 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000077
78 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +000079 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +000080 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
81 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +000082 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +000083 int tryParseRegister();
84 int tryMatchVectorRegister(StringRef &Kind, bool expected);
85 bool parseRegister(OperandVector &Operands);
86 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
87 bool parseVectorList(OperandVector &Operands);
88 bool parseOperand(OperandVector &Operands, bool isCondCode,
89 bool invertCondCode);
90
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +000091 bool showMatchError(SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000092
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000093 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000094 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +000095 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +000096 bool parseDirectiveInst(SMLoc L);
97
Tim Northover3b0846e2014-05-24 12:50:23 +000098 bool parseDirectiveTLSDescCall(SMLoc L);
99
100 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000101 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000102
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000103 bool parseDirectiveReq(StringRef Name, SMLoc L);
104 bool parseDirectiveUnreq(SMLoc L);
105
Tim Northover3b0846e2014-05-24 12:50:23 +0000106 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
107 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
108 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000109 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000110 bool MatchingInlineAsm) override;
111/// @name Auto-generated Match Functions
112/// {
113
114#define GET_ASSEMBLER_HEADER
115#include "AArch64GenAsmMatcher.inc"
116
117 /// }
118
Sander de Smalen8e607342017-11-15 15:44:43 +0000119 OperandMatchResultTy tryParseSVERegister(int &Reg, StringRef &Kind,
120 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000121 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
122 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
123 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
124 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
125 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
126 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000127 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000128 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
129 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
130 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
131 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
132 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000133 bool tryParseNeonVectorRegister(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000134 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Florian Hahn91f11e52017-11-07 16:45:48 +0000135 template <bool ParseSuffix>
136 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000137
138public:
139 enum AArch64MatchResultTy {
140 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
141#define GET_OPERAND_DIAGNOSTIC_TYPES
142#include "AArch64GenAsmMatcher.inc"
143 };
Joel Jones504bf332016-10-24 13:37:13 +0000144 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000145
Akira Hatanakab11ef082015-11-14 06:35:56 +0000146 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000147 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000148 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000149 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000150 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000151 MCStreamer &S = getParser().getStreamer();
152 if (S.getTargetStreamer() == nullptr)
153 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000154
155 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000156 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000157 }
158
159 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
160 SMLoc NameLoc, OperandVector &Operands) override;
161 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
162 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000163 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000164 unsigned Kind) override;
165
166 static bool classifySymbolRef(const MCExpr *Expr,
167 AArch64MCExpr::VariantKind &ELFRefKind,
168 MCSymbolRefExpr::VariantKind &DarwinRefKind,
169 int64_t &Addend);
170};
Tim Northover3b0846e2014-05-24 12:50:23 +0000171
172/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
173/// instruction.
174class AArch64Operand : public MCParsedAsmOperand {
175private:
176 enum KindTy {
177 k_Immediate,
178 k_ShiftedImm,
179 k_CondCode,
180 k_Register,
181 k_VectorList,
182 k_VectorIndex,
183 k_Token,
184 k_SysReg,
185 k_SysCR,
186 k_Prefetch,
187 k_ShiftExtend,
188 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000189 k_Barrier,
190 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000191 } Kind;
192
193 SMLoc StartLoc, EndLoc;
194
195 struct TokOp {
196 const char *Data;
197 unsigned Length;
198 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
199 };
200
201 struct RegOp {
202 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000203 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000204
205 int ElementWidth;
Tim Northover3b0846e2014-05-24 12:50:23 +0000206 };
207
208 struct VectorListOp {
209 unsigned RegNum;
210 unsigned Count;
211 unsigned NumElements;
212 unsigned ElementKind;
213 };
214
215 struct VectorIndexOp {
216 unsigned Val;
217 };
218
219 struct ImmOp {
220 const MCExpr *Val;
221 };
222
223 struct ShiftedImmOp {
224 const MCExpr *Val;
225 unsigned ShiftAmount;
226 };
227
228 struct CondCodeOp {
229 AArch64CC::CondCode Code;
230 };
231
232 struct FPImmOp {
233 unsigned Val; // Encoded 8-bit representation.
234 };
235
236 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000237 const char *Data;
238 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000239 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000240 };
241
242 struct SysRegOp {
243 const char *Data;
244 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000245 uint32_t MRSReg;
246 uint32_t MSRReg;
247 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000248 };
249
250 struct SysCRImmOp {
251 unsigned Val;
252 };
253
254 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000255 const char *Data;
256 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000257 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000258 };
259
Oliver Stannarda34e4702015-12-01 10:48:51 +0000260 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000261 const char *Data;
262 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000263 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000264 };
265
Tim Northover3b0846e2014-05-24 12:50:23 +0000266 struct ShiftExtendOp {
267 AArch64_AM::ShiftExtendType Type;
268 unsigned Amount;
269 bool HasExplicitAmount;
270 };
271
272 struct ExtendOp {
273 unsigned Val;
274 };
275
276 union {
277 struct TokOp Tok;
278 struct RegOp Reg;
279 struct VectorListOp VectorList;
280 struct VectorIndexOp VectorIndex;
281 struct ImmOp Imm;
282 struct ShiftedImmOp ShiftedImm;
283 struct CondCodeOp CondCode;
284 struct FPImmOp FPImm;
285 struct BarrierOp Barrier;
286 struct SysRegOp SysReg;
287 struct SysCRImmOp SysCRImm;
288 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000289 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000290 struct ShiftExtendOp ShiftExtend;
291 };
292
293 // Keep the MCContext around as the MCExprs may need manipulated during
294 // the add<>Operands() calls.
295 MCContext &Ctx;
296
David Blaikie960ea3f2014-06-08 16:18:35 +0000297public:
David Blaikie9f380a32015-03-16 18:06:57 +0000298 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000299
Tim Northover3b0846e2014-05-24 12:50:23 +0000300 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
301 Kind = o.Kind;
302 StartLoc = o.StartLoc;
303 EndLoc = o.EndLoc;
304 switch (Kind) {
305 case k_Token:
306 Tok = o.Tok;
307 break;
308 case k_Immediate:
309 Imm = o.Imm;
310 break;
311 case k_ShiftedImm:
312 ShiftedImm = o.ShiftedImm;
313 break;
314 case k_CondCode:
315 CondCode = o.CondCode;
316 break;
317 case k_FPImm:
318 FPImm = o.FPImm;
319 break;
320 case k_Barrier:
321 Barrier = o.Barrier;
322 break;
323 case k_Register:
324 Reg = o.Reg;
325 break;
326 case k_VectorList:
327 VectorList = o.VectorList;
328 break;
329 case k_VectorIndex:
330 VectorIndex = o.VectorIndex;
331 break;
332 case k_SysReg:
333 SysReg = o.SysReg;
334 break;
335 case k_SysCR:
336 SysCRImm = o.SysCRImm;
337 break;
338 case k_Prefetch:
339 Prefetch = o.Prefetch;
340 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000341 case k_PSBHint:
342 PSBHint = o.PSBHint;
343 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000344 case k_ShiftExtend:
345 ShiftExtend = o.ShiftExtend;
346 break;
347 }
348 }
349
350 /// getStartLoc - Get the location of the first token of this operand.
351 SMLoc getStartLoc() const override { return StartLoc; }
352 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000353 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000354
355 StringRef getToken() const {
356 assert(Kind == k_Token && "Invalid access!");
357 return StringRef(Tok.Data, Tok.Length);
358 }
359
360 bool isTokenSuffix() const {
361 assert(Kind == k_Token && "Invalid access!");
362 return Tok.IsSuffix;
363 }
364
365 const MCExpr *getImm() const {
366 assert(Kind == k_Immediate && "Invalid access!");
367 return Imm.Val;
368 }
369
370 const MCExpr *getShiftedImmVal() const {
371 assert(Kind == k_ShiftedImm && "Invalid access!");
372 return ShiftedImm.Val;
373 }
374
375 unsigned getShiftedImmShift() const {
376 assert(Kind == k_ShiftedImm && "Invalid access!");
377 return ShiftedImm.ShiftAmount;
378 }
379
380 AArch64CC::CondCode getCondCode() const {
381 assert(Kind == k_CondCode && "Invalid access!");
382 return CondCode.Code;
383 }
384
385 unsigned getFPImm() const {
386 assert(Kind == k_FPImm && "Invalid access!");
387 return FPImm.Val;
388 }
389
390 unsigned getBarrier() const {
391 assert(Kind == k_Barrier && "Invalid access!");
392 return Barrier.Val;
393 }
394
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000395 StringRef getBarrierName() const {
396 assert(Kind == k_Barrier && "Invalid access!");
397 return StringRef(Barrier.Data, Barrier.Length);
398 }
399
Tim Northover3b0846e2014-05-24 12:50:23 +0000400 unsigned getReg() const override {
401 assert(Kind == k_Register && "Invalid access!");
402 return Reg.RegNum;
403 }
404
405 unsigned getVectorListStart() const {
406 assert(Kind == k_VectorList && "Invalid access!");
407 return VectorList.RegNum;
408 }
409
410 unsigned getVectorListCount() const {
411 assert(Kind == k_VectorList && "Invalid access!");
412 return VectorList.Count;
413 }
414
415 unsigned getVectorIndex() const {
416 assert(Kind == k_VectorIndex && "Invalid access!");
417 return VectorIndex.Val;
418 }
419
420 StringRef getSysReg() const {
421 assert(Kind == k_SysReg && "Invalid access!");
422 return StringRef(SysReg.Data, SysReg.Length);
423 }
424
Tim Northover3b0846e2014-05-24 12:50:23 +0000425 unsigned getSysCR() const {
426 assert(Kind == k_SysCR && "Invalid access!");
427 return SysCRImm.Val;
428 }
429
430 unsigned getPrefetch() const {
431 assert(Kind == k_Prefetch && "Invalid access!");
432 return Prefetch.Val;
433 }
434
Oliver Stannarda34e4702015-12-01 10:48:51 +0000435 unsigned getPSBHint() const {
436 assert(Kind == k_PSBHint && "Invalid access!");
437 return PSBHint.Val;
438 }
439
440 StringRef getPSBHintName() const {
441 assert(Kind == k_PSBHint && "Invalid access!");
442 return StringRef(PSBHint.Data, PSBHint.Length);
443 }
444
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000445 StringRef getPrefetchName() const {
446 assert(Kind == k_Prefetch && "Invalid access!");
447 return StringRef(Prefetch.Data, Prefetch.Length);
448 }
449
Tim Northover3b0846e2014-05-24 12:50:23 +0000450 AArch64_AM::ShiftExtendType getShiftExtendType() const {
451 assert(Kind == k_ShiftExtend && "Invalid access!");
452 return ShiftExtend.Type;
453 }
454
455 unsigned getShiftExtendAmount() const {
456 assert(Kind == k_ShiftExtend && "Invalid access!");
457 return ShiftExtend.Amount;
458 }
459
460 bool hasShiftExtendAmount() const {
461 assert(Kind == k_ShiftExtend && "Invalid access!");
462 return ShiftExtend.HasExplicitAmount;
463 }
464
465 bool isImm() const override { return Kind == k_Immediate; }
466 bool isMem() const override { return false; }
467 bool isSImm9() const {
468 if (!isImm())
469 return false;
470 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
471 if (!MCE)
472 return false;
473 int64_t Val = MCE->getValue();
474 return (Val >= -256 && Val < 256);
475 }
Sam Parker6d42de72017-08-11 13:14:00 +0000476 bool isSImm10s8() const {
477 if (!isImm())
478 return false;
479 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
480 if (!MCE)
481 return false;
482 int64_t Val = MCE->getValue();
483 return (Val >= -4096 && Val < 4089 && (Val & 7) == 0);
484 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000485 bool isSImm7s4() const {
486 if (!isImm())
487 return false;
488 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
489 if (!MCE)
490 return false;
491 int64_t Val = MCE->getValue();
492 return (Val >= -256 && Val <= 252 && (Val & 3) == 0);
493 }
494 bool isSImm7s8() const {
495 if (!isImm())
496 return false;
497 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
498 if (!MCE)
499 return false;
500 int64_t Val = MCE->getValue();
501 return (Val >= -512 && Val <= 504 && (Val & 7) == 0);
502 }
503 bool isSImm7s16() const {
504 if (!isImm())
505 return false;
506 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
507 if (!MCE)
508 return false;
509 int64_t Val = MCE->getValue();
510 return (Val >= -1024 && Val <= 1008 && (Val & 15) == 0);
511 }
512
513 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
514 AArch64MCExpr::VariantKind ELFRefKind;
515 MCSymbolRefExpr::VariantKind DarwinRefKind;
516 int64_t Addend;
517 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
518 Addend)) {
519 // If we don't understand the expression, assume the best and
520 // let the fixup and relocation code deal with it.
521 return true;
522 }
523
524 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
525 ELFRefKind == AArch64MCExpr::VK_LO12 ||
526 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
527 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
528 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
529 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
530 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
531 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
532 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) {
533 // Note that we don't range-check the addend. It's adjusted modulo page
534 // size when converted, so there is no "out of range" condition when using
535 // @pageoff.
536 return Addend >= 0 && (Addend % Scale) == 0;
537 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
538 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
539 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
540 return Addend == 0;
541 }
542
543 return false;
544 }
545
546 template <int Scale> bool isUImm12Offset() const {
547 if (!isImm())
548 return false;
549
550 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
551 if (!MCE)
552 return isSymbolicUImm12Offset(getImm(), Scale);
553
554 int64_t Val = MCE->getValue();
555 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
556 }
557
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000558 template <int N, int M>
559 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000560 if (!isImm())
561 return false;
562 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
563 if (!MCE)
564 return false;
565 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000566 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000567 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000568
Tim Northover3b0846e2014-05-24 12:50:23 +0000569 bool isLogicalImm32() const {
570 if (!isImm())
571 return false;
572 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
573 if (!MCE)
574 return false;
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000575 int64_t Val = MCE->getValue();
576 if (Val >> 32 != 0 && Val >> 32 != ~0LL)
577 return false;
578 Val &= 0xFFFFFFFF;
579 return AArch64_AM::isLogicalImmediate(Val, 32);
Tim Northover3b0846e2014-05-24 12:50:23 +0000580 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000581
Tim Northover3b0846e2014-05-24 12:50:23 +0000582 bool isLogicalImm64() const {
583 if (!isImm())
584 return false;
585 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
586 if (!MCE)
587 return false;
588 return AArch64_AM::isLogicalImmediate(MCE->getValue(), 64);
589 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000590
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000591 bool isLogicalImm32Not() const {
592 if (!isImm())
593 return false;
594 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
595 if (!MCE)
596 return false;
597 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
598 return AArch64_AM::isLogicalImmediate(Val, 32);
599 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000600
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000601 bool isLogicalImm64Not() const {
602 if (!isImm())
603 return false;
604 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
605 if (!MCE)
606 return false;
607 return AArch64_AM::isLogicalImmediate(~MCE->getValue(), 64);
608 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000609
Tim Northover3b0846e2014-05-24 12:50:23 +0000610 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000611
Tim Northover3b0846e2014-05-24 12:50:23 +0000612 bool isAddSubImm() const {
613 if (!isShiftedImm() && !isImm())
614 return false;
615
616 const MCExpr *Expr;
617
618 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
619 if (isShiftedImm()) {
620 unsigned Shift = ShiftedImm.ShiftAmount;
621 Expr = ShiftedImm.Val;
622 if (Shift != 0 && Shift != 12)
623 return false;
624 } else {
625 Expr = getImm();
626 }
627
628 AArch64MCExpr::VariantKind ELFRefKind;
629 MCSymbolRefExpr::VariantKind DarwinRefKind;
630 int64_t Addend;
631 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
632 DarwinRefKind, Addend)) {
633 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
634 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
635 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
636 || ELFRefKind == AArch64MCExpr::VK_LO12
637 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
638 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
639 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
640 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
641 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
642 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
643 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12;
644 }
645
Diana Picusc93518d2016-10-11 09:17:47 +0000646 // If it's a constant, it should be a real immediate in range:
647 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
648 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
649
650 // If it's an expression, we hope for the best and let the fixup/relocation
651 // code deal with it.
652 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000653 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000654
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000655 bool isAddSubImmNeg() const {
656 if (!isShiftedImm() && !isImm())
657 return false;
658
659 const MCExpr *Expr;
660
661 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
662 if (isShiftedImm()) {
663 unsigned Shift = ShiftedImm.ShiftAmount;
664 Expr = ShiftedImm.Val;
665 if (Shift != 0 && Shift != 12)
666 return false;
667 } else
668 Expr = getImm();
669
670 // Otherwise it should be a real negative immediate in range:
671 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
672 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
673 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000674
Tim Northover3b0846e2014-05-24 12:50:23 +0000675 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000676
Tim Northover3b0846e2014-05-24 12:50:23 +0000677 bool isSIMDImmType10() const {
678 if (!isImm())
679 return false;
680 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
681 if (!MCE)
682 return false;
683 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
684 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000685
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000686 template<int N>
687 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000688 if (!isImm())
689 return false;
690 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
691 if (!MCE)
692 return true;
693 int64_t Val = MCE->getValue();
694 if (Val & 0x3)
695 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000696 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
697 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000698 }
699
700 bool
701 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
702 if (!isImm())
703 return false;
704
705 AArch64MCExpr::VariantKind ELFRefKind;
706 MCSymbolRefExpr::VariantKind DarwinRefKind;
707 int64_t Addend;
708 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
709 DarwinRefKind, Addend)) {
710 return false;
711 }
712 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
713 return false;
714
715 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
716 if (ELFRefKind == AllowedModifiers[i])
717 return Addend == 0;
718 }
719
720 return false;
721 }
722
723 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000724 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000725 }
726
727 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000728 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
729 AArch64MCExpr::VK_TPREL_G2,
730 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000731 }
732
733 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000734 return isMovWSymbol({
735 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000736 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
737 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000738 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000739 }
740
741 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000742 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
743 AArch64MCExpr::VK_TPREL_G0,
744 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000745 }
746
747 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000748 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000749 }
750
751 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000752 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000753 }
754
755 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000756 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
757 AArch64MCExpr::VK_TPREL_G1_NC,
758 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000759 }
760
761 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000762 return isMovWSymbol(
763 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
764 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000765 }
766
767 template<int RegWidth, int Shift>
768 bool isMOVZMovAlias() const {
769 if (!isImm()) return false;
770
771 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
772 if (!CE) return false;
773 uint64_t Value = CE->getValue();
774
Tim Northoverdaa1c012016-06-16 01:42:25 +0000775 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000776 }
777
778 template<int RegWidth, int Shift>
779 bool isMOVNMovAlias() const {
780 if (!isImm()) return false;
781
782 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
783 if (!CE) return false;
784 uint64_t Value = CE->getValue();
785
Tim Northoverdaa1c012016-06-16 01:42:25 +0000786 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000787 }
788
789 bool isFPImm() const { return Kind == k_FPImm; }
790 bool isBarrier() const { return Kind == k_Barrier; }
791 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000792
Tim Northover3b0846e2014-05-24 12:50:23 +0000793 bool isMRSSystemRegister() const {
794 if (!isSysReg()) return false;
795
Tim Northover7cd58932015-01-22 17:23:04 +0000796 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000797 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000798
Tim Northover3b0846e2014-05-24 12:50:23 +0000799 bool isMSRSystemRegister() const {
800 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000801 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000802 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000803
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000804 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000805 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000806 return (SysReg.PStateField == AArch64PState::PAN ||
807 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000808 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000809
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000810 bool isSystemPStateFieldWithImm0_15() const {
811 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000812 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000813 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000814
Florian Hahnc4422242017-11-07 13:07:50 +0000815 bool isReg() const override {
816 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
817 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000818
Florian Hahnc4422242017-11-07 13:07:50 +0000819 bool isNeonVectorReg() const {
820 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
821 }
822
823 bool isNeonVectorRegLo() const {
824 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000825 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
826 Reg.RegNum);
827 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000828
Reid Kleckner37517a22017-12-18 20:58:25 +0000829 template <unsigned Class = AArch64::ZPRRegClassID>
830 bool isSVEDataVectorReg() const {
831 return (Kind == k_Register && Reg.Kind == RegKind::SVEDataVector) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000832 AArch64MCRegisterClasses[Class].contains(getReg());
833 }
834
Reid Kleckner37517a22017-12-18 20:58:25 +0000835 template <int ElementWidth> bool isSVEDataVectorRegOfWidth() const {
836 return isSVEDataVectorReg() &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000837 (ElementWidth == -1 || Reg.ElementWidth == ElementWidth);
838 }
839
Tim Northover3b0846e2014-05-24 12:50:23 +0000840 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000841 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000842 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
843 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000844
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000845 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000846 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000847 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
848 Reg.RegNum);
849 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000850
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000851 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000852 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000853 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
854 Reg.RegNum);
855 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000856
857 bool isGPR64sp0() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000858 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000859 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
860 }
861
Sam Parker5f934642017-08-31 09:27:04 +0000862 template<int64_t Angle, int64_t Remainder>
863 bool isComplexRotation() const {
864 if (!isImm()) return false;
865
866 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
867 if (!CE) return false;
868 uint64_t Value = CE->getValue();
869
870 return (Value % Angle == Remainder && Value <= 270);
871 }
872
Tim Northover3b0846e2014-05-24 12:50:23 +0000873 /// Is this a vector list with the type implicit (presumably attached to the
874 /// instruction itself)?
875 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
876 return Kind == k_VectorList && VectorList.Count == NumRegs &&
877 !VectorList.ElementKind;
878 }
879
880 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
881 bool isTypedVectorList() const {
882 if (Kind != k_VectorList)
883 return false;
884 if (VectorList.Count != NumRegs)
885 return false;
886 if (VectorList.ElementKind != ElementKind)
887 return false;
888 return VectorList.NumElements == NumElements;
889 }
890
891 bool isVectorIndex1() const {
892 return Kind == k_VectorIndex && VectorIndex.Val == 1;
893 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000894
Tim Northover3b0846e2014-05-24 12:50:23 +0000895 bool isVectorIndexB() const {
896 return Kind == k_VectorIndex && VectorIndex.Val < 16;
897 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000898
Tim Northover3b0846e2014-05-24 12:50:23 +0000899 bool isVectorIndexH() const {
900 return Kind == k_VectorIndex && VectorIndex.Val < 8;
901 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000902
Tim Northover3b0846e2014-05-24 12:50:23 +0000903 bool isVectorIndexS() const {
904 return Kind == k_VectorIndex && VectorIndex.Val < 4;
905 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000906
Tim Northover3b0846e2014-05-24 12:50:23 +0000907 bool isVectorIndexD() const {
908 return Kind == k_VectorIndex && VectorIndex.Val < 2;
909 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000910
Tim Northover3b0846e2014-05-24 12:50:23 +0000911 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000912
Tim Northover3b0846e2014-05-24 12:50:23 +0000913 bool isTokenEqual(StringRef Str) const {
914 return Kind == k_Token && getToken() == Str;
915 }
916 bool isSysCR() const { return Kind == k_SysCR; }
917 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000918 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000919 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
920 bool isShifter() const {
921 if (!isShiftExtend())
922 return false;
923
924 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
925 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
926 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
927 ST == AArch64_AM::MSL);
928 }
929 bool isExtend() const {
930 if (!isShiftExtend())
931 return false;
932
933 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
934 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
935 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
936 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
937 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
938 ET == AArch64_AM::LSL) &&
939 getShiftExtendAmount() <= 4;
940 }
941
942 bool isExtend64() const {
943 if (!isExtend())
944 return false;
945 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
946 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
947 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
948 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000949
Tim Northover3b0846e2014-05-24 12:50:23 +0000950 bool isExtendLSL64() const {
951 if (!isExtend())
952 return false;
953 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
954 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
955 ET == AArch64_AM::LSL) &&
956 getShiftExtendAmount() <= 4;
957 }
958
959 template<int Width> bool isMemXExtend() const {
960 if (!isExtend())
961 return false;
962 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
963 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
964 (getShiftExtendAmount() == Log2_32(Width / 8) ||
965 getShiftExtendAmount() == 0);
966 }
967
968 template<int Width> bool isMemWExtend() const {
969 if (!isExtend())
970 return false;
971 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
972 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
973 (getShiftExtendAmount() == Log2_32(Width / 8) ||
974 getShiftExtendAmount() == 0);
975 }
976
977 template <unsigned width>
978 bool isArithmeticShifter() const {
979 if (!isShifter())
980 return false;
981
982 // An arithmetic shifter is LSL, LSR, or ASR.
983 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
984 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
985 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
986 }
987
988 template <unsigned width>
989 bool isLogicalShifter() const {
990 if (!isShifter())
991 return false;
992
993 // A logical shifter is LSL, LSR, ASR or ROR.
994 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
995 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
996 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
997 getShiftExtendAmount() < width;
998 }
999
1000 bool isMovImm32Shifter() const {
1001 if (!isShifter())
1002 return false;
1003
1004 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1005 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1006 if (ST != AArch64_AM::LSL)
1007 return false;
1008 uint64_t Val = getShiftExtendAmount();
1009 return (Val == 0 || Val == 16);
1010 }
1011
1012 bool isMovImm64Shifter() const {
1013 if (!isShifter())
1014 return false;
1015
1016 // A MOVi shifter is LSL of 0 or 16.
1017 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1018 if (ST != AArch64_AM::LSL)
1019 return false;
1020 uint64_t Val = getShiftExtendAmount();
1021 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1022 }
1023
1024 bool isLogicalVecShifter() const {
1025 if (!isShifter())
1026 return false;
1027
1028 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1029 unsigned Shift = getShiftExtendAmount();
1030 return getShiftExtendType() == AArch64_AM::LSL &&
1031 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1032 }
1033
1034 bool isLogicalVecHalfWordShifter() const {
1035 if (!isLogicalVecShifter())
1036 return false;
1037
1038 // A logical vector shifter is a left shift by 0 or 8.
1039 unsigned Shift = getShiftExtendAmount();
1040 return getShiftExtendType() == AArch64_AM::LSL &&
1041 (Shift == 0 || Shift == 8);
1042 }
1043
1044 bool isMoveVecShifter() const {
1045 if (!isShiftExtend())
1046 return false;
1047
1048 // A logical vector shifter is a left shift by 8 or 16.
1049 unsigned Shift = getShiftExtendAmount();
1050 return getShiftExtendType() == AArch64_AM::MSL &&
1051 (Shift == 8 || Shift == 16);
1052 }
1053
1054 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1055 // to LDUR/STUR when the offset is not legal for the former but is for
1056 // the latter. As such, in addition to checking for being a legal unscaled
1057 // address, also check that it is not a legal scaled address. This avoids
1058 // ambiguity in the matcher.
1059 template<int Width>
1060 bool isSImm9OffsetFB() const {
1061 return isSImm9() && !isUImm12Offset<Width / 8>();
1062 }
1063
1064 bool isAdrpLabel() 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 = - (4096 * (1LL << (21 - 1)));
1073 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1074 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1075 }
1076
1077 return true;
1078 }
1079
1080 bool isAdrLabel() const {
1081 // Validation was handled during parsing, so we just sanity check that
1082 // something didn't go haywire.
1083 if (!isImm())
1084 return false;
1085
1086 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1087 int64_t Val = CE->getValue();
1088 int64_t Min = - (1LL << (21 - 1));
1089 int64_t Max = ((1LL << (21 - 1)) - 1);
1090 return Val >= Min && Val <= Max;
1091 }
1092
1093 return true;
1094 }
1095
1096 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1097 // Add as immediates when possible. Null MCExpr = 0.
1098 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001099 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001100 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001101 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001102 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001103 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001104 }
1105
1106 void addRegOperands(MCInst &Inst, unsigned N) const {
1107 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001108 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001109 }
1110
1111 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1112 assert(N == 1 && "Invalid number of operands!");
1113 assert(
1114 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1115
1116 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1117 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1118 RI->getEncodingValue(getReg()));
1119
Jim Grosbache9119e42015-05-13 18:37:00 +00001120 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001121 }
1122
1123 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1124 assert(N == 1 && "Invalid number of operands!");
1125 assert(
1126 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001127 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001128 }
1129
1130 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1131 assert(N == 1 && "Invalid number of operands!");
1132 assert(
1133 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001134 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001135 }
1136
1137 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1138 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001139 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001140 }
1141
1142 template <unsigned NumRegs>
1143 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1144 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001145 static const unsigned FirstRegs[] = { AArch64::D0,
1146 AArch64::D0_D1,
1147 AArch64::D0_D1_D2,
1148 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001149 unsigned FirstReg = FirstRegs[NumRegs - 1];
1150
1151 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001152 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001153 }
1154
1155 template <unsigned NumRegs>
1156 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1157 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001158 static const unsigned FirstRegs[] = { AArch64::Q0,
1159 AArch64::Q0_Q1,
1160 AArch64::Q0_Q1_Q2,
1161 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001162 unsigned FirstReg = FirstRegs[NumRegs - 1];
1163
1164 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001165 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001166 }
1167
1168 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1169 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001170 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001171 }
1172
1173 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1174 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001175 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001176 }
1177
1178 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1179 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001180 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001181 }
1182
1183 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1184 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001185 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001186 }
1187
1188 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1189 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001190 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001191 }
1192
1193 void addImmOperands(MCInst &Inst, unsigned N) const {
1194 assert(N == 1 && "Invalid number of operands!");
1195 // If this is a pageoff symrefexpr with an addend, adjust the addend
1196 // to be only the page-offset portion. Otherwise, just add the expr
1197 // as-is.
1198 addExpr(Inst, getImm());
1199 }
1200
1201 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1202 assert(N == 2 && "Invalid number of operands!");
1203 if (isShiftedImm()) {
1204 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001205 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001206 } else {
1207 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001208 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001209 }
1210 }
1211
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001212 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1213 assert(N == 2 && "Invalid number of operands!");
1214
1215 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1216 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1217 int64_t Val = -CE->getValue();
1218 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1219
1220 Inst.addOperand(MCOperand::createImm(Val));
1221 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1222 }
1223
Tim Northover3b0846e2014-05-24 12:50:23 +00001224 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1225 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001226 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001227 }
1228
1229 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1230 assert(N == 1 && "Invalid number of operands!");
1231 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1232 if (!MCE)
1233 addExpr(Inst, getImm());
1234 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001235 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001236 }
1237
1238 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1239 addImmOperands(Inst, N);
1240 }
1241
1242 template<int Scale>
1243 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1244 assert(N == 1 && "Invalid number of operands!");
1245 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1246
1247 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001248 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001249 return;
1250 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001251 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001252 }
1253
1254 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1255 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001256 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001257 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001258 }
1259
Sam Parker6d42de72017-08-11 13:14:00 +00001260 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1261 assert(N == 1 && "Invalid number of operands!");
1262 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1263 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1264 }
1265
Tim Northover3b0846e2014-05-24 12:50:23 +00001266 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1267 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001268 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001269 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001270 }
1271
1272 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1273 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001274 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001275 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001276 }
1277
1278 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1279 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001280 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001281 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001282 }
1283
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001284 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1285 assert(N == 1 && "Invalid number of operands!");
1286 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1287 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1288 }
1289
Tim Northover3b0846e2014-05-24 12:50:23 +00001290 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1291 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001292 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001293 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001294 }
1295
1296 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1297 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001298 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001299 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001300 }
1301
1302 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1303 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001304 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001305 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001306 }
1307
1308 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1309 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001310 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001311 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001312 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001313 }
1314
1315 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1316 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001317 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001318 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001319 }
1320
1321 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1322 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001323 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001324 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001325 }
1326
1327 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1328 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001329 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001330 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001331 }
1332
1333 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1334 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001335 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001336 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001337 }
1338
1339 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1340 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001341 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001342 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001343 }
1344
1345 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1346 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001347 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001348 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001349 }
1350
1351 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1352 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001353 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001354 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001355 }
1356
1357 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1358 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001359 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001360 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001361 }
1362
1363 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1364 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001365 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001366 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001367 }
1368
1369 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1370 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001371 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001372 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001373 }
1374
1375 void addLogicalImm32Operands(MCInst &Inst, unsigned N) const {
1376 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001377 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +00001378 uint64_t encoding =
1379 AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001380 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001381 }
1382
1383 void addLogicalImm64Operands(MCInst &Inst, unsigned N) const {
1384 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001385 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001386 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001387 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001388 }
1389
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001390 void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
1391 assert(N == 1 && "Invalid number of operands!");
1392 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1393 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
1394 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001395 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001396 }
1397
1398 void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
1399 assert(N == 1 && "Invalid number of operands!");
1400 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1401 uint64_t encoding =
1402 AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001403 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001404 }
1405
Tim Northover3b0846e2014-05-24 12:50:23 +00001406 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1407 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001408 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001409 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001410 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001411 }
1412
1413 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1414 // Branch operands don't encode the low bits, so shift them off
1415 // here. If it's a label, however, just put it on directly as there's
1416 // not enough information now to do anything.
1417 assert(N == 1 && "Invalid number of operands!");
1418 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1419 if (!MCE) {
1420 addExpr(Inst, getImm());
1421 return;
1422 }
1423 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001424 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001425 }
1426
1427 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1428 // Branch operands don't encode the low bits, so shift them off
1429 // here. If it's a label, however, just put it on directly as there's
1430 // not enough information now to do anything.
1431 assert(N == 1 && "Invalid number of operands!");
1432 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1433 if (!MCE) {
1434 addExpr(Inst, getImm());
1435 return;
1436 }
1437 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001438 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001439 }
1440
1441 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1442 // Branch operands don't encode the low bits, so shift them off
1443 // here. If it's a label, however, just put it on directly as there's
1444 // not enough information now to do anything.
1445 assert(N == 1 && "Invalid number of operands!");
1446 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1447 if (!MCE) {
1448 addExpr(Inst, getImm());
1449 return;
1450 }
1451 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001452 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001453 }
1454
1455 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1456 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001457 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001458 }
1459
1460 void addBarrierOperands(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(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001463 }
1464
1465 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1466 assert(N == 1 && "Invalid number of operands!");
1467
Jim Grosbache9119e42015-05-13 18:37:00 +00001468 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001469 }
1470
1471 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1472 assert(N == 1 && "Invalid number of operands!");
1473
Jim Grosbache9119e42015-05-13 18:37:00 +00001474 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001475 }
1476
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001477 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1478 assert(N == 1 && "Invalid number of operands!");
1479
1480 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1481 }
1482
1483 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001484 assert(N == 1 && "Invalid number of operands!");
1485
Jim Grosbache9119e42015-05-13 18:37:00 +00001486 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001487 }
1488
1489 void addSysCROperands(MCInst &Inst, unsigned N) const {
1490 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001491 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001492 }
1493
1494 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1495 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001496 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001497 }
1498
Oliver Stannarda34e4702015-12-01 10:48:51 +00001499 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1500 assert(N == 1 && "Invalid number of operands!");
1501 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1502 }
1503
Tim Northover3b0846e2014-05-24 12:50:23 +00001504 void addShifterOperands(MCInst &Inst, unsigned N) const {
1505 assert(N == 1 && "Invalid number of operands!");
1506 unsigned Imm =
1507 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001508 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001509 }
1510
1511 void addExtendOperands(MCInst &Inst, unsigned N) const {
1512 assert(N == 1 && "Invalid number of operands!");
1513 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1514 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1515 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001516 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001517 }
1518
1519 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1520 assert(N == 1 && "Invalid number of operands!");
1521 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1522 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1523 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001524 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001525 }
1526
1527 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1528 assert(N == 2 && "Invalid number of operands!");
1529 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1530 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001531 Inst.addOperand(MCOperand::createImm(IsSigned));
1532 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001533 }
1534
1535 // For 8-bit load/store instructions with a register offset, both the
1536 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1537 // they're disambiguated by whether the shift was explicit or implicit rather
1538 // than its size.
1539 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1540 assert(N == 2 && "Invalid number of operands!");
1541 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1542 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001543 Inst.addOperand(MCOperand::createImm(IsSigned));
1544 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001545 }
1546
1547 template<int Shift>
1548 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1549 assert(N == 1 && "Invalid number of operands!");
1550
1551 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1552 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001553 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001554 }
1555
1556 template<int Shift>
1557 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1558 assert(N == 1 && "Invalid number of operands!");
1559
1560 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1561 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001562 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001563 }
1564
Sam Parker5f934642017-08-31 09:27:04 +00001565 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1566 assert(N == 1 && "Invalid number of operands!");
1567 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1568 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1569 }
1570
1571 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1572 assert(N == 1 && "Invalid number of operands!");
1573 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1574 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1575 }
1576
Tim Northover3b0846e2014-05-24 12:50:23 +00001577 void print(raw_ostream &OS) const override;
1578
David Blaikie960ea3f2014-06-08 16:18:35 +00001579 static std::unique_ptr<AArch64Operand>
1580 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1581 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001582 Op->Tok.Data = Str.data();
1583 Op->Tok.Length = Str.size();
1584 Op->Tok.IsSuffix = IsSuffix;
1585 Op->StartLoc = S;
1586 Op->EndLoc = S;
1587 return Op;
1588 }
1589
David Blaikie960ea3f2014-06-08 16:18:35 +00001590 static std::unique_ptr<AArch64Operand>
Florian Hahnc4422242017-11-07 13:07:50 +00001591 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001592 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001593 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001594 Op->Reg.Kind = Kind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001595 Op->StartLoc = S;
1596 Op->EndLoc = E;
1597 return Op;
1598 }
1599
David Blaikie960ea3f2014-06-08 16:18:35 +00001600 static std::unique_ptr<AArch64Operand>
Florian Hahn91f11e52017-11-07 16:45:48 +00001601 CreateReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1602 SMLoc S, SMLoc E, MCContext &Ctx) {
1603 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1604 Op->Reg.RegNum = RegNum;
1605 Op->Reg.ElementWidth = ElementWidth;
1606 Op->Reg.Kind = Kind;
1607 Op->StartLoc = S;
1608 Op->EndLoc = E;
1609 return Op;
1610 }
1611
1612 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001613 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1614 char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1615 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001616 Op->VectorList.RegNum = RegNum;
1617 Op->VectorList.Count = Count;
1618 Op->VectorList.NumElements = NumElements;
1619 Op->VectorList.ElementKind = ElementKind;
1620 Op->StartLoc = S;
1621 Op->EndLoc = E;
1622 return Op;
1623 }
1624
David Blaikie960ea3f2014-06-08 16:18:35 +00001625 static std::unique_ptr<AArch64Operand>
1626 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1627 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001628 Op->VectorIndex.Val = Idx;
1629 Op->StartLoc = S;
1630 Op->EndLoc = E;
1631 return Op;
1632 }
1633
David Blaikie960ea3f2014-06-08 16:18:35 +00001634 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1635 SMLoc E, MCContext &Ctx) {
1636 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001637 Op->Imm.Val = Val;
1638 Op->StartLoc = S;
1639 Op->EndLoc = E;
1640 return Op;
1641 }
1642
David Blaikie960ea3f2014-06-08 16:18:35 +00001643 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1644 unsigned ShiftAmount,
1645 SMLoc S, SMLoc E,
1646 MCContext &Ctx) {
1647 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001648 Op->ShiftedImm .Val = Val;
1649 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1650 Op->StartLoc = S;
1651 Op->EndLoc = E;
1652 return Op;
1653 }
1654
David Blaikie960ea3f2014-06-08 16:18:35 +00001655 static std::unique_ptr<AArch64Operand>
1656 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1657 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001658 Op->CondCode.Code = Code;
1659 Op->StartLoc = S;
1660 Op->EndLoc = E;
1661 return Op;
1662 }
1663
David Blaikie960ea3f2014-06-08 16:18:35 +00001664 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1665 MCContext &Ctx) {
1666 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001667 Op->FPImm.Val = Val;
1668 Op->StartLoc = S;
1669 Op->EndLoc = S;
1670 return Op;
1671 }
1672
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001673 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1674 StringRef Str,
1675 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001676 MCContext &Ctx) {
1677 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001678 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001679 Op->Barrier.Data = Str.data();
1680 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001681 Op->StartLoc = S;
1682 Op->EndLoc = S;
1683 return Op;
1684 }
1685
Tim Northover7cd58932015-01-22 17:23:04 +00001686 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1687 uint32_t MRSReg,
1688 uint32_t MSRReg,
1689 uint32_t PStateField,
1690 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001691 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001692 Op->SysReg.Data = Str.data();
1693 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001694 Op->SysReg.MRSReg = MRSReg;
1695 Op->SysReg.MSRReg = MSRReg;
1696 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001697 Op->StartLoc = S;
1698 Op->EndLoc = S;
1699 return Op;
1700 }
1701
David Blaikie960ea3f2014-06-08 16:18:35 +00001702 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1703 SMLoc E, MCContext &Ctx) {
1704 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001705 Op->SysCRImm.Val = Val;
1706 Op->StartLoc = S;
1707 Op->EndLoc = E;
1708 return Op;
1709 }
1710
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001711 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1712 StringRef Str,
1713 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001714 MCContext &Ctx) {
1715 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001716 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001717 Op->Barrier.Data = Str.data();
1718 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001719 Op->StartLoc = S;
1720 Op->EndLoc = S;
1721 return Op;
1722 }
1723
Oliver Stannarda34e4702015-12-01 10:48:51 +00001724 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1725 StringRef Str,
1726 SMLoc S,
1727 MCContext &Ctx) {
1728 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1729 Op->PSBHint.Val = Val;
1730 Op->PSBHint.Data = Str.data();
1731 Op->PSBHint.Length = Str.size();
1732 Op->StartLoc = S;
1733 Op->EndLoc = S;
1734 return Op;
1735 }
1736
David Blaikie960ea3f2014-06-08 16:18:35 +00001737 static std::unique_ptr<AArch64Operand>
1738 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1739 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1740 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001741 Op->ShiftExtend.Type = ShOp;
1742 Op->ShiftExtend.Amount = Val;
1743 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1744 Op->StartLoc = S;
1745 Op->EndLoc = E;
1746 return Op;
1747 }
1748};
1749
1750} // end anonymous namespace.
1751
1752void AArch64Operand::print(raw_ostream &OS) const {
1753 switch (Kind) {
1754 case k_FPImm:
1755 OS << "<fpimm " << getFPImm() << "("
1756 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1757 break;
1758 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001759 StringRef Name = getBarrierName();
1760 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001761 OS << "<barrier " << Name << ">";
1762 else
1763 OS << "<barrier invalid #" << getBarrier() << ">";
1764 break;
1765 }
1766 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001767 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001768 break;
1769 case k_ShiftedImm: {
1770 unsigned Shift = getShiftedImmShift();
1771 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001772 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001773 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1774 break;
1775 }
1776 case k_CondCode:
1777 OS << "<condcode " << getCondCode() << ">";
1778 break;
1779 case k_Register:
1780 OS << "<register " << getReg() << ">";
1781 break;
1782 case k_VectorList: {
1783 OS << "<vectorlist ";
1784 unsigned Reg = getVectorListStart();
1785 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1786 OS << Reg + i << " ";
1787 OS << ">";
1788 break;
1789 }
1790 case k_VectorIndex:
1791 OS << "<vectorindex " << getVectorIndex() << ">";
1792 break;
1793 case k_SysReg:
1794 OS << "<sysreg: " << getSysReg() << '>';
1795 break;
1796 case k_Token:
1797 OS << "'" << getToken() << "'";
1798 break;
1799 case k_SysCR:
1800 OS << "c" << getSysCR();
1801 break;
1802 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001803 StringRef Name = getPrefetchName();
1804 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001805 OS << "<prfop " << Name << ">";
1806 else
1807 OS << "<prfop invalid #" << getPrefetch() << ">";
1808 break;
1809 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001810 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001811 OS << getPSBHintName();
1812 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001813 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001814 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1815 << getShiftExtendAmount();
1816 if (!hasShiftExtendAmount())
1817 OS << "<imp>";
1818 OS << '>';
1819 break;
1820 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001821}
1822
1823/// @name Auto-generated Match Functions
1824/// {
1825
1826static unsigned MatchRegisterName(StringRef Name);
1827
1828/// }
1829
Florian Hahnc4422242017-11-07 13:07:50 +00001830static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001831 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001832 .Case("v0", AArch64::Q0)
1833 .Case("v1", AArch64::Q1)
1834 .Case("v2", AArch64::Q2)
1835 .Case("v3", AArch64::Q3)
1836 .Case("v4", AArch64::Q4)
1837 .Case("v5", AArch64::Q5)
1838 .Case("v6", AArch64::Q6)
1839 .Case("v7", AArch64::Q7)
1840 .Case("v8", AArch64::Q8)
1841 .Case("v9", AArch64::Q9)
1842 .Case("v10", AArch64::Q10)
1843 .Case("v11", AArch64::Q11)
1844 .Case("v12", AArch64::Q12)
1845 .Case("v13", AArch64::Q13)
1846 .Case("v14", AArch64::Q14)
1847 .Case("v15", AArch64::Q15)
1848 .Case("v16", AArch64::Q16)
1849 .Case("v17", AArch64::Q17)
1850 .Case("v18", AArch64::Q18)
1851 .Case("v19", AArch64::Q19)
1852 .Case("v20", AArch64::Q20)
1853 .Case("v21", AArch64::Q21)
1854 .Case("v22", AArch64::Q22)
1855 .Case("v23", AArch64::Q23)
1856 .Case("v24", AArch64::Q24)
1857 .Case("v25", AArch64::Q25)
1858 .Case("v26", AArch64::Q26)
1859 .Case("v27", AArch64::Q27)
1860 .Case("v28", AArch64::Q28)
1861 .Case("v29", AArch64::Q29)
1862 .Case("v30", AArch64::Q30)
1863 .Case("v31", AArch64::Q31)
1864 .Default(0);
1865}
1866
1867static bool isValidVectorKind(StringRef Name) {
1868 return StringSwitch<bool>(Name.lower())
1869 .Case(".8b", true)
1870 .Case(".16b", true)
1871 .Case(".4h", true)
1872 .Case(".8h", true)
1873 .Case(".2s", true)
1874 .Case(".4s", true)
1875 .Case(".1d", true)
1876 .Case(".2d", true)
1877 .Case(".1q", true)
1878 // Accept the width neutral ones, too, for verbose syntax. If those
1879 // aren't used in the right places, the token operand won't match so
1880 // all will work out.
1881 .Case(".b", true)
1882 .Case(".h", true)
1883 .Case(".s", true)
1884 .Case(".d", true)
Oliver Stannarde4c3d212015-12-08 12:16:10 +00001885 // Needed for fp16 scalar pairwise reductions
1886 .Case(".2h", true)
Sjoerd Meijer79876332017-08-09 14:59:54 +00001887 // another special case for the ARMv8.2a dot product operand
1888 .Case(".4b", true)
Tim Northover3b0846e2014-05-24 12:50:23 +00001889 .Default(false);
1890}
1891
Florian Hahn91f11e52017-11-07 16:45:48 +00001892static unsigned matchSVEDataVectorRegName(StringRef Name) {
1893 return StringSwitch<unsigned>(Name.lower())
1894 .Case("z0", AArch64::Z0)
1895 .Case("z1", AArch64::Z1)
1896 .Case("z2", AArch64::Z2)
1897 .Case("z3", AArch64::Z3)
1898 .Case("z4", AArch64::Z4)
1899 .Case("z5", AArch64::Z5)
1900 .Case("z6", AArch64::Z6)
1901 .Case("z7", AArch64::Z7)
1902 .Case("z8", AArch64::Z8)
1903 .Case("z9", AArch64::Z9)
1904 .Case("z10", AArch64::Z10)
1905 .Case("z11", AArch64::Z11)
1906 .Case("z12", AArch64::Z12)
1907 .Case("z13", AArch64::Z13)
1908 .Case("z14", AArch64::Z14)
1909 .Case("z15", AArch64::Z15)
1910 .Case("z16", AArch64::Z16)
1911 .Case("z17", AArch64::Z17)
1912 .Case("z18", AArch64::Z18)
1913 .Case("z19", AArch64::Z19)
1914 .Case("z20", AArch64::Z20)
1915 .Case("z21", AArch64::Z21)
1916 .Case("z22", AArch64::Z22)
1917 .Case("z23", AArch64::Z23)
1918 .Case("z24", AArch64::Z24)
1919 .Case("z25", AArch64::Z25)
1920 .Case("z26", AArch64::Z26)
1921 .Case("z27", AArch64::Z27)
1922 .Case("z28", AArch64::Z28)
1923 .Case("z29", AArch64::Z29)
1924 .Case("z30", AArch64::Z30)
1925 .Case("z31", AArch64::Z31)
1926 .Default(0);
1927}
1928
1929static bool isValidSVEKind(StringRef Name) {
1930 return StringSwitch<bool>(Name.lower())
1931 .Case(".b", true)
1932 .Case(".h", true)
1933 .Case(".s", true)
1934 .Case(".d", true)
1935 .Case(".q", true)
1936 .Default(false);
1937}
1938
Tim Northover3b0846e2014-05-24 12:50:23 +00001939static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1940 char &ElementKind) {
1941 assert(isValidVectorKind(Name));
1942
1943 ElementKind = Name.lower()[Name.size() - 1];
1944 NumElements = 0;
1945
1946 if (Name.size() == 2)
1947 return;
1948
1949 // Parse the lane count
1950 Name = Name.drop_front();
1951 while (isdigit(Name.front())) {
1952 NumElements = 10 * NumElements + (Name.front() - '0');
1953 Name = Name.drop_front();
1954 }
1955}
1956
1957bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1958 SMLoc &EndLoc) {
1959 StartLoc = getLoc();
1960 RegNo = tryParseRegister();
1961 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1962 return (RegNo == (unsigned)-1);
1963}
1964
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001965// Matches a register name or register alias previously defined by '.req'
1966unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001967 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001968 unsigned RegNum = 0;
1969 if ((RegNum = matchSVEDataVectorRegName(Name)))
1970 return Kind == RegKind::SVEDataVector ? RegNum : 0;
1971
1972 if ((RegNum = MatchNeonVectorRegName(Name)))
1973 return Kind == RegKind::NeonVector ? RegNum : 0;
1974
1975 // The parsed register must be of RegKind Scalar
1976 if ((RegNum = MatchRegisterName(Name)))
1977 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001978
Florian Hahnc4422242017-11-07 13:07:50 +00001979 if (!RegNum) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001980 // Check for aliases registered via .req. Canonicalize to lower case.
1981 // That's more consistent since register names are case insensitive, and
1982 // it's how the original entry was passed in from MC/MCParser/AsmParser.
1983 auto Entry = RegisterReqs.find(Name.lower());
1984 if (Entry == RegisterReqs.end())
1985 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00001986
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001987 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00001988 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001989 RegNum = Entry->getValue().second;
1990 }
1991 return RegNum;
1992}
1993
Tim Northover3b0846e2014-05-24 12:50:23 +00001994/// tryParseRegister - Try to parse a register name. The token must be an
1995/// Identifier when called, and if it is a register name the token is eaten and
1996/// the register is added to the operand list.
1997int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00001998 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001999 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002000 if (Tok.isNot(AsmToken::Identifier))
2001 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00002002
2003 std::string lowerCase = Tok.getString().lower();
Florian Hahnc4422242017-11-07 13:07:50 +00002004 unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
Sander de Smalenc067c302017-12-20 09:45:45 +00002005
Tim Northover3b0846e2014-05-24 12:50:23 +00002006 // Also handle a few aliases of registers.
2007 if (RegNum == 0)
2008 RegNum = StringSwitch<unsigned>(lowerCase)
2009 .Case("fp", AArch64::FP)
2010 .Case("lr", AArch64::LR)
2011 .Case("x31", AArch64::XZR)
2012 .Case("w31", AArch64::WZR)
2013 .Default(0);
2014
2015 if (RegNum == 0)
2016 return -1;
2017
2018 Parser.Lex(); // Eat identifier token.
2019 return RegNum;
2020}
2021
2022/// tryMatchVectorRegister - Try to parse a vector register name with optional
2023/// kind specifier. If it is a register specifier, eat the token and return it.
2024int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002025 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002026 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2027 TokError("vector register expected");
2028 return -1;
2029 }
2030
2031 StringRef Name = Parser.getTok().getString();
2032 // If there is a kind specifier, it's separated from the register name by
2033 // a '.'.
2034 size_t Start = 0, Next = Name.find('.');
2035 StringRef Head = Name.slice(Start, Next);
Florian Hahnc4422242017-11-07 13:07:50 +00002036 unsigned RegNum = matchRegisterNameAlias(Head, RegKind::NeonVector);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002037
Tim Northover3b0846e2014-05-24 12:50:23 +00002038 if (RegNum) {
2039 if (Next != StringRef::npos) {
2040 Kind = Name.slice(Next, StringRef::npos);
2041 if (!isValidVectorKind(Kind)) {
2042 TokError("invalid vector kind qualifier");
2043 return -1;
2044 }
2045 }
2046 Parser.Lex(); // Eat the register token.
2047 return RegNum;
2048 }
2049
2050 if (expected)
2051 TokError("vector register expected");
2052 return -1;
2053}
2054
2055/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002056OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002057AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002058 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002059 SMLoc S = getLoc();
2060
2061 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2062 Error(S, "Expected cN operand where 0 <= N <= 15");
2063 return MatchOperand_ParseFail;
2064 }
2065
2066 StringRef Tok = Parser.getTok().getIdentifier();
2067 if (Tok[0] != 'c' && Tok[0] != 'C') {
2068 Error(S, "Expected cN operand where 0 <= N <= 15");
2069 return MatchOperand_ParseFail;
2070 }
2071
2072 uint32_t CRNum;
2073 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2074 if (BadNum || CRNum > 15) {
2075 Error(S, "Expected cN operand where 0 <= N <= 15");
2076 return MatchOperand_ParseFail;
2077 }
2078
2079 Parser.Lex(); // Eat identifier token.
2080 Operands.push_back(
2081 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2082 return MatchOperand_Success;
2083}
2084
2085/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002086OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002087AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002088 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002089 SMLoc S = getLoc();
2090 const AsmToken &Tok = Parser.getTok();
2091 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002092 // Eat optional hash.
2093 if (parseOptionalToken(AsmToken::Hash) ||
2094 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002095 const MCExpr *ImmVal;
2096 if (getParser().parseExpression(ImmVal))
2097 return MatchOperand_ParseFail;
2098
2099 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2100 if (!MCE) {
2101 TokError("immediate value expected for prefetch operand");
2102 return MatchOperand_ParseFail;
2103 }
2104 unsigned prfop = MCE->getValue();
2105 if (prfop > 31) {
2106 TokError("prefetch operand out of range, [0,31] expected");
2107 return MatchOperand_ParseFail;
2108 }
2109
Tim Northovere6ae6762016-07-05 21:23:04 +00002110 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2111 Operands.push_back(AArch64Operand::CreatePrefetch(
2112 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002113 return MatchOperand_Success;
2114 }
2115
2116 if (Tok.isNot(AsmToken::Identifier)) {
2117 TokError("pre-fetch hint expected");
2118 return MatchOperand_ParseFail;
2119 }
2120
Tim Northovere6ae6762016-07-05 21:23:04 +00002121 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2122 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002123 TokError("pre-fetch hint expected");
2124 return MatchOperand_ParseFail;
2125 }
2126
2127 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002128 Operands.push_back(AArch64Operand::CreatePrefetch(
2129 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002130 return MatchOperand_Success;
2131}
2132
Oliver Stannarda34e4702015-12-01 10:48:51 +00002133/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002134OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002135AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2136 MCAsmParser &Parser = getParser();
2137 SMLoc S = getLoc();
2138 const AsmToken &Tok = Parser.getTok();
2139 if (Tok.isNot(AsmToken::Identifier)) {
2140 TokError("invalid operand for instruction");
2141 return MatchOperand_ParseFail;
2142 }
2143
Tim Northovere6ae6762016-07-05 21:23:04 +00002144 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2145 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002146 TokError("invalid operand for instruction");
2147 return MatchOperand_ParseFail;
2148 }
2149
2150 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002151 Operands.push_back(AArch64Operand::CreatePSBHint(
2152 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002153 return MatchOperand_Success;
2154}
2155
Tim Northover3b0846e2014-05-24 12:50:23 +00002156/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2157/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002158OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002159AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002160 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002161 SMLoc S = getLoc();
2162 const MCExpr *Expr;
2163
2164 if (Parser.getTok().is(AsmToken::Hash)) {
2165 Parser.Lex(); // Eat hash token.
2166 }
2167
2168 if (parseSymbolicImmVal(Expr))
2169 return MatchOperand_ParseFail;
2170
2171 AArch64MCExpr::VariantKind ELFRefKind;
2172 MCSymbolRefExpr::VariantKind DarwinRefKind;
2173 int64_t Addend;
2174 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2175 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2176 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2177 // No modifier was specified at all; this is the syntax for an ELF basic
2178 // ADRP relocation (unfortunately).
2179 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002180 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002181 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2182 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2183 Addend != 0) {
2184 Error(S, "gotpage label reference not allowed an addend");
2185 return MatchOperand_ParseFail;
2186 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2187 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2188 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2189 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2190 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2191 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2192 // The operand must be an @page or @gotpage qualified symbolref.
2193 Error(S, "page or gotpage label reference expected");
2194 return MatchOperand_ParseFail;
2195 }
2196 }
2197
2198 // We have either a label reference possibly with addend or an immediate. The
2199 // addend is a raw value here. The linker will adjust it to only reference the
2200 // page.
2201 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2202 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2203
2204 return MatchOperand_Success;
2205}
2206
2207/// tryParseAdrLabel - Parse and validate a source label for the ADR
2208/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002209OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002210AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2211 SMLoc S = getLoc();
2212 const MCExpr *Expr;
2213
Nirav Davee833c6c2016-11-08 18:31:04 +00002214 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002215 if (getParser().parseExpression(Expr))
2216 return MatchOperand_ParseFail;
2217
2218 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2219 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2220
2221 return MatchOperand_Success;
2222}
2223
2224/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002225OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002226AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002227 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002228 SMLoc S = getLoc();
2229
Nirav Davee833c6c2016-11-08 18:31:04 +00002230 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002231
2232 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002233 bool isNegative = parseOptionalToken(AsmToken::Minus);
2234
Tim Northover3b0846e2014-05-24 12:50:23 +00002235 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002236 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002237 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002238 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002239 Val = Tok.getIntVal();
2240 if (Val > 255 || Val < 0) {
2241 TokError("encoded floating point value out of range");
2242 return MatchOperand_ParseFail;
2243 }
2244 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002245 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002246 if (isNegative)
2247 RealVal.changeSign();
2248
Tim Northover3b0846e2014-05-24 12:50:23 +00002249 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002250 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002251
John Brawn5ca5daa2017-04-20 10:13:54 +00002252 // Check for out of range values. As an exception we let Zero through,
2253 // but as tokens instead of an FPImm so that it can be matched by the
2254 // appropriate alias if one exists.
2255 if (RealVal.isPosZero()) {
2256 Parser.Lex(); // Eat the token.
2257 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2258 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2259 return MatchOperand_Success;
2260 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002261 TokError("expected compatible register or floating-point constant");
2262 return MatchOperand_ParseFail;
2263 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002264 }
2265 Parser.Lex(); // Eat the token.
2266 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2267 return MatchOperand_Success;
2268 }
2269
2270 if (!Hash)
2271 return MatchOperand_NoMatch;
2272
2273 TokError("invalid floating point immediate");
2274 return MatchOperand_ParseFail;
2275}
2276
2277/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002278OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002279AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002280 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002281 SMLoc S = getLoc();
2282
2283 if (Parser.getTok().is(AsmToken::Hash))
2284 Parser.Lex(); // Eat '#'
2285 else if (Parser.getTok().isNot(AsmToken::Integer))
2286 // Operand should start from # or should be integer, emit error otherwise.
2287 return MatchOperand_NoMatch;
2288
2289 const MCExpr *Imm;
2290 if (parseSymbolicImmVal(Imm))
2291 return MatchOperand_ParseFail;
2292 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2293 uint64_t ShiftAmount = 0;
2294 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2295 if (MCE) {
2296 int64_t Val = MCE->getValue();
2297 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002298 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002299 ShiftAmount = 12;
2300 }
2301 }
2302 SMLoc E = Parser.getTok().getLoc();
2303 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2304 getContext()));
2305 return MatchOperand_Success;
2306 }
2307
2308 // Eat ','
2309 Parser.Lex();
2310
2311 // The optional operand must be "lsl #N" where N is non-negative.
2312 if (!Parser.getTok().is(AsmToken::Identifier) ||
2313 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2314 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2315 return MatchOperand_ParseFail;
2316 }
2317
2318 // Eat 'lsl'
2319 Parser.Lex();
2320
Nirav Davee833c6c2016-11-08 18:31:04 +00002321 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002322
2323 if (Parser.getTok().isNot(AsmToken::Integer)) {
2324 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2325 return MatchOperand_ParseFail;
2326 }
2327
2328 int64_t ShiftAmount = Parser.getTok().getIntVal();
2329
2330 if (ShiftAmount < 0) {
2331 Error(Parser.getTok().getLoc(), "positive shift amount required");
2332 return MatchOperand_ParseFail;
2333 }
2334 Parser.Lex(); // Eat the number
2335
2336 SMLoc E = Parser.getTok().getLoc();
2337 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2338 S, E, getContext()));
2339 return MatchOperand_Success;
2340}
2341
2342/// parseCondCodeString - Parse a Condition Code string.
2343AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2344 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2345 .Case("eq", AArch64CC::EQ)
2346 .Case("ne", AArch64CC::NE)
2347 .Case("cs", AArch64CC::HS)
2348 .Case("hs", AArch64CC::HS)
2349 .Case("cc", AArch64CC::LO)
2350 .Case("lo", AArch64CC::LO)
2351 .Case("mi", AArch64CC::MI)
2352 .Case("pl", AArch64CC::PL)
2353 .Case("vs", AArch64CC::VS)
2354 .Case("vc", AArch64CC::VC)
2355 .Case("hi", AArch64CC::HI)
2356 .Case("ls", AArch64CC::LS)
2357 .Case("ge", AArch64CC::GE)
2358 .Case("lt", AArch64CC::LT)
2359 .Case("gt", AArch64CC::GT)
2360 .Case("le", AArch64CC::LE)
2361 .Case("al", AArch64CC::AL)
2362 .Case("nv", AArch64CC::NV)
2363 .Default(AArch64CC::Invalid);
2364 return CC;
2365}
2366
2367/// parseCondCode - Parse a Condition Code operand.
2368bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2369 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002370 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002371 SMLoc S = getLoc();
2372 const AsmToken &Tok = Parser.getTok();
2373 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2374
2375 StringRef Cond = Tok.getString();
2376 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2377 if (CC == AArch64CC::Invalid)
2378 return TokError("invalid condition code");
2379 Parser.Lex(); // Eat identifier token.
2380
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002381 if (invertCondCode) {
2382 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2383 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002384 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002385 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002386
2387 Operands.push_back(
2388 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2389 return false;
2390}
2391
2392/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2393/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002394OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002395AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002396 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002397 const AsmToken &Tok = Parser.getTok();
2398 std::string LowerID = Tok.getString().lower();
2399 AArch64_AM::ShiftExtendType ShOp =
2400 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2401 .Case("lsl", AArch64_AM::LSL)
2402 .Case("lsr", AArch64_AM::LSR)
2403 .Case("asr", AArch64_AM::ASR)
2404 .Case("ror", AArch64_AM::ROR)
2405 .Case("msl", AArch64_AM::MSL)
2406 .Case("uxtb", AArch64_AM::UXTB)
2407 .Case("uxth", AArch64_AM::UXTH)
2408 .Case("uxtw", AArch64_AM::UXTW)
2409 .Case("uxtx", AArch64_AM::UXTX)
2410 .Case("sxtb", AArch64_AM::SXTB)
2411 .Case("sxth", AArch64_AM::SXTH)
2412 .Case("sxtw", AArch64_AM::SXTW)
2413 .Case("sxtx", AArch64_AM::SXTX)
2414 .Default(AArch64_AM::InvalidShiftExtend);
2415
2416 if (ShOp == AArch64_AM::InvalidShiftExtend)
2417 return MatchOperand_NoMatch;
2418
2419 SMLoc S = Tok.getLoc();
2420 Parser.Lex();
2421
Nirav Davee833c6c2016-11-08 18:31:04 +00002422 bool Hash = parseOptionalToken(AsmToken::Hash);
2423
Tim Northover3b0846e2014-05-24 12:50:23 +00002424 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2425 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2426 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2427 ShOp == AArch64_AM::MSL) {
2428 // We expect a number here.
2429 TokError("expected #imm after shift specifier");
2430 return MatchOperand_ParseFail;
2431 }
2432
Chad Rosier2ff37b82016-12-27 16:58:09 +00002433 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002434 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2435 Operands.push_back(
2436 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2437 return MatchOperand_Success;
2438 }
2439
Chad Rosier2ff37b82016-12-27 16:58:09 +00002440 // Make sure we do actually have a number, identifier or a parenthesized
2441 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002442 SMLoc E = Parser.getTok().getLoc();
2443 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002444 !Parser.getTok().is(AsmToken::LParen) &&
2445 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002446 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002447 return MatchOperand_ParseFail;
2448 }
2449
2450 const MCExpr *ImmVal;
2451 if (getParser().parseExpression(ImmVal))
2452 return MatchOperand_ParseFail;
2453
2454 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2455 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002456 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002457 return MatchOperand_ParseFail;
2458 }
2459
Jim Grosbach57fd2622014-09-23 22:16:02 +00002460 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002461 Operands.push_back(AArch64Operand::CreateShiftExtend(
2462 ShOp, MCE->getValue(), true, S, E, getContext()));
2463 return MatchOperand_Success;
2464}
2465
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002466static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2467 if (FBS[AArch64::HasV8_1aOps])
2468 Str += "ARMv8.1a";
2469 else if (FBS[AArch64::HasV8_2aOps])
2470 Str += "ARMv8.2a";
2471 else
2472 Str += "(unknown)";
2473}
2474
2475void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2476 SMLoc S) {
2477 const uint16_t Op2 = Encoding & 7;
2478 const uint16_t Cm = (Encoding & 0x78) >> 3;
2479 const uint16_t Cn = (Encoding & 0x780) >> 7;
2480 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2481
2482 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2483
2484 Operands.push_back(
2485 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2486 Operands.push_back(
2487 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2488 Operands.push_back(
2489 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2490 Expr = MCConstantExpr::create(Op2, getContext());
2491 Operands.push_back(
2492 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2493}
2494
Tim Northover3b0846e2014-05-24 12:50:23 +00002495/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2496/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2497bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2498 OperandVector &Operands) {
2499 if (Name.find('.') != StringRef::npos)
2500 return TokError("invalid operand");
2501
2502 Mnemonic = Name;
2503 Operands.push_back(
2504 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2505
Rafael Espindola961d4692014-11-11 05:18:41 +00002506 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002507 const AsmToken &Tok = Parser.getTok();
2508 StringRef Op = Tok.getString();
2509 SMLoc S = Tok.getLoc();
2510
Tim Northover3b0846e2014-05-24 12:50:23 +00002511 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002512 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2513 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002514 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002515 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2516 std::string Str("IC " + std::string(IC->Name) + " requires ");
2517 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2518 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002519 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002520 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002521 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002522 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2523 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002524 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002525 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2526 std::string Str("DC " + std::string(DC->Name) + " requires ");
2527 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2528 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002529 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002530 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002531 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002532 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2533 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002534 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002535 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2536 std::string Str("AT " + std::string(AT->Name) + " requires ");
2537 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2538 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002539 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002540 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002541 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002542 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2543 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002544 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002545 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2546 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2547 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2548 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002549 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002550 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002551 }
2552
Tim Northover3b0846e2014-05-24 12:50:23 +00002553 Parser.Lex(); // Eat operand.
2554
2555 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2556 bool HasRegister = false;
2557
2558 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002559 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002560 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2561 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002562 HasRegister = true;
2563 }
2564
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002565 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002566 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002567 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002568 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002569
Nirav Davee833c6c2016-11-08 18:31:04 +00002570 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2571 return true;
2572
Tim Northover3b0846e2014-05-24 12:50:23 +00002573 return false;
2574}
2575
Alex Bradbury58eba092016-11-01 16:32:05 +00002576OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002577AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002578 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002579 const AsmToken &Tok = Parser.getTok();
2580
2581 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002582 if (parseOptionalToken(AsmToken::Hash) ||
2583 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002584 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002585 const MCExpr *ImmVal;
2586 SMLoc ExprLoc = getLoc();
2587 if (getParser().parseExpression(ImmVal))
2588 return MatchOperand_ParseFail;
2589 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2590 if (!MCE) {
2591 Error(ExprLoc, "immediate value expected for barrier operand");
2592 return MatchOperand_ParseFail;
2593 }
2594 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2595 Error(ExprLoc, "barrier operand out of range");
2596 return MatchOperand_ParseFail;
2597 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002598 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2599 Operands.push_back(AArch64Operand::CreateBarrier(
2600 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002601 return MatchOperand_Success;
2602 }
2603
2604 if (Tok.isNot(AsmToken::Identifier)) {
2605 TokError("invalid operand for instruction");
2606 return MatchOperand_ParseFail;
2607 }
2608
Tim Northover3b0846e2014-05-24 12:50:23 +00002609 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002610 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2611 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002612 TokError("'sy' or #imm operand expected");
2613 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002614 } else if (!DB) {
2615 TokError("invalid barrier option name");
2616 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002617 }
2618
Tim Northovere6ae6762016-07-05 21:23:04 +00002619 Operands.push_back(AArch64Operand::CreateBarrier(
2620 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002621 Parser.Lex(); // Consume the option
2622
2623 return MatchOperand_Success;
2624}
2625
Alex Bradbury58eba092016-11-01 16:32:05 +00002626OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002627AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002628 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002629 const AsmToken &Tok = Parser.getTok();
2630
2631 if (Tok.isNot(AsmToken::Identifier))
2632 return MatchOperand_NoMatch;
2633
Tim Northovere6ae6762016-07-05 21:23:04 +00002634 int MRSReg, MSRReg;
2635 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2636 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2637 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2638 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2639 } else
2640 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002641
Tim Northovere6ae6762016-07-05 21:23:04 +00002642 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2643 unsigned PStateImm = -1;
2644 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2645 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002646
Tim Northovere6ae6762016-07-05 21:23:04 +00002647 Operands.push_back(
2648 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2649 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002650 Parser.Lex(); // Eat identifier
2651
2652 return MatchOperand_Success;
2653}
2654
Florian Hahnc4422242017-11-07 13:07:50 +00002655/// tryParseNeonVectorRegister - Parse a vector register operand.
2656bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002657 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002658 if (Parser.getTok().isNot(AsmToken::Identifier))
2659 return true;
2660
2661 SMLoc S = getLoc();
2662 // Check for a vector register specifier first.
2663 StringRef Kind;
2664 int64_t Reg = tryMatchVectorRegister(Kind, false);
2665 if (Reg == -1)
2666 return true;
2667 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00002668 AArch64Operand::CreateReg(Reg, RegKind::NeonVector, S, getLoc(),
2669 getContext()));
2670
Tim Northover3b0846e2014-05-24 12:50:23 +00002671 // If there was an explicit qualifier, that goes on as a literal text
2672 // operand.
2673 if (!Kind.empty())
2674 Operands.push_back(
2675 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2676
2677 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002678 SMLoc SIdx = getLoc();
2679 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002680 const MCExpr *ImmVal;
2681 if (getParser().parseExpression(ImmVal))
2682 return false;
2683 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2684 if (!MCE) {
2685 TokError("immediate value expected for vector index");
2686 return false;
2687 }
2688
2689 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002690
Nirav Davee833c6c2016-11-08 18:31:04 +00002691 if (parseToken(AsmToken::RBrac, "']' expected"))
2692 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002693
2694 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2695 E, getContext()));
2696 }
2697
2698 return false;
2699}
2700
Florian Hahn91f11e52017-11-07 16:45:48 +00002701// tryParseSVEDataVectorRegister - Try to parse a SVE vector register name with
2702// optional kind specifier. If it is a register specifier, eat the token
2703// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002704OperandMatchResultTy
2705AArch64AsmParser::tryParseSVERegister(int &Reg, StringRef &Kind,
2706 RegKind MatchKind) {
2707 MCAsmParser &Parser = getParser();
2708 const AsmToken &Tok = Parser.getTok();
2709
Florian Hahn91f11e52017-11-07 16:45:48 +00002710 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002711 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002712
2713 StringRef Name = Tok.getString();
2714 // If there is a kind specifier, it's separated from the register name by
2715 // a '.'.
2716 size_t Start = 0, Next = Name.find('.');
2717 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002718 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002719
2720 if (RegNum) {
2721 if (Next != StringRef::npos) {
2722 Kind = Name.slice(Next, StringRef::npos);
2723 if (!isValidSVEKind(Kind)) {
2724 TokError("invalid sve vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002725 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002726 }
2727 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002728 Parser.Lex(); // Eat the register token.
2729
2730 Reg = RegNum;
2731 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002732 }
2733
Sander de Smalen8e607342017-11-15 15:44:43 +00002734 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002735}
2736
Tim Northover3b0846e2014-05-24 12:50:23 +00002737/// parseRegister - Parse a non-vector register operand.
2738bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2739 SMLoc S = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00002740 // Try for a vector (neon) register.
2741 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002742 return false;
2743
2744 // Try for a scalar register.
2745 int64_t Reg = tryParseRegister();
2746 if (Reg == -1)
2747 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002748 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2749 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002750
Tim Northover3b0846e2014-05-24 12:50:23 +00002751 return false;
2752}
2753
2754bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002755 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002756 bool HasELFModifier = false;
2757 AArch64MCExpr::VariantKind RefKind;
2758
Nirav Davee833c6c2016-11-08 18:31:04 +00002759 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002760 HasELFModifier = true;
2761
Nirav Davee833c6c2016-11-08 18:31:04 +00002762 if (Parser.getTok().isNot(AsmToken::Identifier))
2763 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002764
2765 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2766 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2767 .Case("lo12", AArch64MCExpr::VK_LO12)
2768 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2769 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2770 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2771 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2772 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2773 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2774 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2775 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2776 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2777 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2778 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2779 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2780 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2781 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2782 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2783 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2784 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2785 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2786 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2787 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2788 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2789 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2790 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2791 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2792 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2793 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2794 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2795 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2796 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2797 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2798 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2799 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2800 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2801 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2802 .Default(AArch64MCExpr::VK_INVALID);
2803
Nirav Davee833c6c2016-11-08 18:31:04 +00002804 if (RefKind == AArch64MCExpr::VK_INVALID)
2805 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002806
2807 Parser.Lex(); // Eat identifier
2808
Nirav Davee833c6c2016-11-08 18:31:04 +00002809 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002810 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002811 }
2812
2813 if (getParser().parseExpression(ImmVal))
2814 return true;
2815
2816 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002817 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002818
2819 return false;
2820}
2821
2822/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2823bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002824 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002825 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2826 SMLoc S = getLoc();
2827 Parser.Lex(); // Eat left bracket token.
2828 StringRef Kind;
2829 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2830 if (FirstReg == -1)
2831 return true;
2832 int64_t PrevReg = FirstReg;
2833 unsigned Count = 1;
2834
Nirav Davee833c6c2016-11-08 18:31:04 +00002835 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002836 SMLoc Loc = getLoc();
2837 StringRef NextKind;
2838 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2839 if (Reg == -1)
2840 return true;
2841 // Any Kind suffices must match on all regs in the list.
2842 if (Kind != NextKind)
2843 return Error(Loc, "mismatched register size suffix");
2844
2845 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2846
2847 if (Space == 0 || Space > 3) {
2848 return Error(Loc, "invalid number of vectors");
2849 }
2850
2851 Count += Space;
2852 }
2853 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002854 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002855 SMLoc Loc = getLoc();
2856 StringRef NextKind;
2857 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2858 if (Reg == -1)
2859 return true;
2860 // Any Kind suffices must match on all regs in the list.
2861 if (Kind != NextKind)
2862 return Error(Loc, "mismatched register size suffix");
2863
2864 // Registers must be incremental (with wraparound at 31)
2865 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2866 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2867 return Error(Loc, "registers must be sequential");
2868
2869 PrevReg = Reg;
2870 ++Count;
2871 }
2872 }
2873
Nirav Davee833c6c2016-11-08 18:31:04 +00002874 if (parseToken(AsmToken::RCurly, "'}' expected"))
2875 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002876
2877 if (Count > 4)
2878 return Error(S, "invalid number of vectors");
2879
2880 unsigned NumElements = 0;
2881 char ElementKind = 0;
2882 if (!Kind.empty())
2883 parseValidVectorKind(Kind, NumElements, ElementKind);
2884
2885 Operands.push_back(AArch64Operand::CreateVectorList(
2886 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
2887
2888 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002889 SMLoc SIdx = getLoc();
2890 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002891 const MCExpr *ImmVal;
2892 if (getParser().parseExpression(ImmVal))
2893 return false;
2894 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2895 if (!MCE) {
2896 TokError("immediate value expected for vector index");
2897 return false;
2898 }
2899
2900 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002901 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002902 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002903
2904 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2905 E, getContext()));
2906 }
2907 return false;
2908}
2909
Alex Bradbury58eba092016-11-01 16:32:05 +00002910OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002911AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002912 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002913 const AsmToken &Tok = Parser.getTok();
2914 if (!Tok.is(AsmToken::Identifier))
2915 return MatchOperand_NoMatch;
2916
Florian Hahnc4422242017-11-07 13:07:50 +00002917 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00002918
2919 MCContext &Ctx = getContext();
2920 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
2921 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
2922 return MatchOperand_NoMatch;
2923
2924 SMLoc S = getLoc();
2925 Parser.Lex(); // Eat register
2926
Nirav Davee833c6c2016-11-08 18:31:04 +00002927 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002928 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00002929 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00002930 return MatchOperand_Success;
2931 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002932
Nirav Davee833c6c2016-11-08 18:31:04 +00002933 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002934
2935 if (Parser.getTok().isNot(AsmToken::Integer)) {
2936 Error(getLoc(), "index must be absent or #0");
2937 return MatchOperand_ParseFail;
2938 }
2939
2940 const MCExpr *ImmVal;
2941 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
2942 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
2943 Error(getLoc(), "index must be absent or #0");
2944 return MatchOperand_ParseFail;
2945 }
2946
2947 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00002948 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00002949 return MatchOperand_Success;
2950}
2951
2952/// parseOperand - Parse a arm instruction operand. For now this parses the
2953/// operand regardless of the mnemonic.
2954bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
2955 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002956 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002957 // Check if the current operand has a custom associated parser, if so, try to
2958 // custom parse the operand, or fallback to the general approach.
Reid Kleckner37517a22017-12-18 20:58:25 +00002959 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
Tim Northover3b0846e2014-05-24 12:50:23 +00002960 if (ResTy == MatchOperand_Success)
2961 return false;
2962 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2963 // there was a match, but an error occurred, in which case, just return that
2964 // the operand parsing failed.
2965 if (ResTy == MatchOperand_ParseFail)
2966 return true;
2967
2968 // Nothing custom, so do general case parsing.
2969 SMLoc S, E;
2970 switch (getLexer().getKind()) {
2971 default: {
2972 SMLoc S = getLoc();
2973 const MCExpr *Expr;
2974 if (parseSymbolicImmVal(Expr))
2975 return Error(S, "invalid operand");
2976
2977 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2978 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2979 return false;
2980 }
2981 case AsmToken::LBrac: {
2982 SMLoc Loc = Parser.getTok().getLoc();
2983 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
2984 getContext()));
2985 Parser.Lex(); // Eat '['
2986
2987 // There's no comma after a '[', so we can parse the next operand
2988 // immediately.
2989 return parseOperand(Operands, false, false);
2990 }
2991 case AsmToken::LCurly:
2992 return parseVectorList(Operands);
2993 case AsmToken::Identifier: {
2994 // If we're expecting a Condition Code operand, then just parse that.
2995 if (isCondCode)
2996 return parseCondCode(Operands, invertCondCode);
2997
2998 // If it's a register name, parse it.
2999 if (!parseRegister(Operands))
3000 return false;
3001
3002 // This could be an optional "shift" or "extend" operand.
3003 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3004 // We can only continue if no tokens were eaten.
3005 if (GotShift != MatchOperand_NoMatch)
3006 return GotShift;
3007
3008 // This was not a register so parse other operands that start with an
3009 // identifier (like labels) as expressions and create them as immediates.
3010 const MCExpr *IdVal;
3011 S = getLoc();
3012 if (getParser().parseExpression(IdVal))
3013 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003014 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3015 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3016 return false;
3017 }
3018 case AsmToken::Integer:
3019 case AsmToken::Real:
3020 case AsmToken::Hash: {
3021 // #42 -> immediate.
3022 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003023
3024 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003025
3026 // Parse a negative sign
3027 bool isNegative = false;
3028 if (Parser.getTok().is(AsmToken::Minus)) {
3029 isNegative = true;
3030 // We need to consume this token only when we have a Real, otherwise
3031 // we let parseSymbolicImmVal take care of it
3032 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3033 Parser.Lex();
3034 }
3035
3036 // The only Real that should come through here is a literal #0.0 for
3037 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3038 // so convert the value.
3039 const AsmToken &Tok = Parser.getTok();
3040 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003041 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003042 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3043 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3044 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3045 Mnemonic != "fcmlt")
3046 return TokError("unexpected floating point literal");
3047 else if (IntVal != 0 || isNegative)
3048 return TokError("expected floating-point constant #0.0");
3049 Parser.Lex(); // Eat the token.
3050
3051 Operands.push_back(
3052 AArch64Operand::CreateToken("#0", false, S, getContext()));
3053 Operands.push_back(
3054 AArch64Operand::CreateToken(".0", false, S, getContext()));
3055 return false;
3056 }
3057
3058 const MCExpr *ImmVal;
3059 if (parseSymbolicImmVal(ImmVal))
3060 return true;
3061
3062 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3063 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3064 return false;
3065 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003066 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003067 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003068 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003069 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003070 Parser.Lex(); // Eat '='
3071 const MCExpr *SubExprVal;
3072 if (getParser().parseExpression(SubExprVal))
3073 return true;
3074
David Peixottoae5ba762014-07-18 16:05:14 +00003075 if (Operands.size() < 2 ||
3076 !static_cast<AArch64Operand &>(*Operands[1]).isReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003077 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003078
3079 bool IsXReg =
3080 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3081 Operands[1]->getReg());
3082
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003083 MCContext& Ctx = getContext();
3084 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3085 // 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 +00003086 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003087 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3088 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3089 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3090 ShiftAmt += 16;
3091 Imm >>= 16;
3092 }
3093 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3094 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3095 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003096 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003097 if (ShiftAmt)
3098 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3099 ShiftAmt, true, S, E, Ctx));
3100 return false;
3101 }
David Peixottoae5ba762014-07-18 16:05:14 +00003102 APInt Simm = APInt(64, Imm << ShiftAmt);
3103 // check if the immediate is an unsigned or signed 32-bit int for W regs
3104 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3105 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003106 }
3107 // 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 +00003108 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003109 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003110 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3111 return false;
3112 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003113 }
3114}
3115
3116/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3117/// operands.
3118bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3119 StringRef Name, SMLoc NameLoc,
3120 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003121 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003122 Name = StringSwitch<StringRef>(Name.lower())
3123 .Case("beq", "b.eq")
3124 .Case("bne", "b.ne")
3125 .Case("bhs", "b.hs")
3126 .Case("bcs", "b.cs")
3127 .Case("blo", "b.lo")
3128 .Case("bcc", "b.cc")
3129 .Case("bmi", "b.mi")
3130 .Case("bpl", "b.pl")
3131 .Case("bvs", "b.vs")
3132 .Case("bvc", "b.vc")
3133 .Case("bhi", "b.hi")
3134 .Case("bls", "b.ls")
3135 .Case("bge", "b.ge")
3136 .Case("blt", "b.lt")
3137 .Case("bgt", "b.gt")
3138 .Case("ble", "b.le")
3139 .Case("bal", "b.al")
3140 .Case("bnv", "b.nv")
3141 .Default(Name);
3142
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003143 // First check for the AArch64-specific .req directive.
3144 if (Parser.getTok().is(AsmToken::Identifier) &&
3145 Parser.getTok().getIdentifier() == ".req") {
3146 parseDirectiveReq(Name, NameLoc);
3147 // We always return 'error' for this, as we're done with this
3148 // statement and don't need to match the 'instruction."
3149 return true;
3150 }
3151
Tim Northover3b0846e2014-05-24 12:50:23 +00003152 // Create the leading tokens for the mnemonic, split by '.' characters.
3153 size_t Start = 0, Next = Name.find('.');
3154 StringRef Head = Name.slice(Start, Next);
3155
3156 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003157 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3158 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003159
3160 Operands.push_back(
3161 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3162 Mnemonic = Head;
3163
3164 // Handle condition codes for a branch mnemonic
3165 if (Head == "b" && Next != StringRef::npos) {
3166 Start = Next;
3167 Next = Name.find('.', Start + 1);
3168 Head = Name.slice(Start + 1, Next);
3169
3170 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3171 (Head.data() - Name.data()));
3172 AArch64CC::CondCode CC = parseCondCodeString(Head);
3173 if (CC == AArch64CC::Invalid)
3174 return Error(SuffixLoc, "invalid condition code");
3175 Operands.push_back(
3176 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3177 Operands.push_back(
3178 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3179 }
3180
3181 // Add the remaining tokens in the mnemonic.
3182 while (Next != StringRef::npos) {
3183 Start = Next;
3184 Next = Name.find('.', Start + 1);
3185 Head = Name.slice(Start, Next);
3186 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3187 (Head.data() - Name.data()) + 1);
3188 Operands.push_back(
3189 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3190 }
3191
3192 // Conditional compare instructions have a Condition Code operand, which needs
3193 // to be parsed and an immediate operand created.
3194 bool condCodeFourthOperand =
3195 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3196 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3197 Head == "csinc" || Head == "csinv" || Head == "csneg");
3198
3199 // These instructions are aliases to some of the conditional select
3200 // instructions. However, the condition code is inverted in the aliased
3201 // instruction.
3202 //
3203 // FIXME: Is this the correct way to handle these? Or should the parser
3204 // generate the aliased instructions directly?
3205 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3206 bool condCodeThirdOperand =
3207 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3208
3209 // Read the remaining operands.
3210 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3211 // Read the first operand.
3212 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003213 return true;
3214 }
3215
3216 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003217 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003218 // Parse and remember the operand.
3219 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3220 (N == 3 && condCodeThirdOperand) ||
3221 (N == 2 && condCodeSecondOperand),
3222 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003223 return true;
3224 }
3225
3226 // After successfully parsing some operands there are two special cases to
3227 // consider (i.e. notional operands not separated by commas). Both are due
3228 // to memory specifiers:
3229 // + An RBrac will end an address for load/store/prefetch
3230 // + An '!' will indicate a pre-indexed operation.
3231 //
3232 // It's someone else's responsibility to make sure these tokens are sane
3233 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003234
Nirav Davee833c6c2016-11-08 18:31:04 +00003235 SMLoc RLoc = Parser.getTok().getLoc();
3236 if (parseOptionalToken(AsmToken::RBrac))
3237 Operands.push_back(
3238 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3239 SMLoc ELoc = Parser.getTok().getLoc();
3240 if (parseOptionalToken(AsmToken::Exclaim))
3241 Operands.push_back(
3242 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003243
3244 ++N;
3245 }
3246 }
3247
Nirav Davee833c6c2016-11-08 18:31:04 +00003248 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3249 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003250
Tim Northover3b0846e2014-05-24 12:50:23 +00003251 return false;
3252}
3253
3254// FIXME: This entire function is a giant hack to provide us with decent
3255// operand range validation/diagnostics until TableGen/MC can be extended
3256// to support autogeneration of this kind of validation.
3257bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3258 SmallVectorImpl<SMLoc> &Loc) {
3259 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3260 // Check for indexed addressing modes w/ the base register being the
3261 // same as a destination/source register or pair load where
3262 // the Rt == Rt2. All of those are undefined behaviour.
3263 switch (Inst.getOpcode()) {
3264 case AArch64::LDPSWpre:
3265 case AArch64::LDPWpost:
3266 case AArch64::LDPWpre:
3267 case AArch64::LDPXpost:
3268 case AArch64::LDPXpre: {
3269 unsigned Rt = Inst.getOperand(1).getReg();
3270 unsigned Rt2 = Inst.getOperand(2).getReg();
3271 unsigned Rn = Inst.getOperand(3).getReg();
3272 if (RI->isSubRegisterEq(Rn, Rt))
3273 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3274 "is also a destination");
3275 if (RI->isSubRegisterEq(Rn, Rt2))
3276 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3277 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003278 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003279 }
3280 case AArch64::LDPDi:
3281 case AArch64::LDPQi:
3282 case AArch64::LDPSi:
3283 case AArch64::LDPSWi:
3284 case AArch64::LDPWi:
3285 case AArch64::LDPXi: {
3286 unsigned Rt = Inst.getOperand(0).getReg();
3287 unsigned Rt2 = Inst.getOperand(1).getReg();
3288 if (Rt == Rt2)
3289 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3290 break;
3291 }
3292 case AArch64::LDPDpost:
3293 case AArch64::LDPDpre:
3294 case AArch64::LDPQpost:
3295 case AArch64::LDPQpre:
3296 case AArch64::LDPSpost:
3297 case AArch64::LDPSpre:
3298 case AArch64::LDPSWpost: {
3299 unsigned Rt = Inst.getOperand(1).getReg();
3300 unsigned Rt2 = Inst.getOperand(2).getReg();
3301 if (Rt == Rt2)
3302 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3303 break;
3304 }
3305 case AArch64::STPDpost:
3306 case AArch64::STPDpre:
3307 case AArch64::STPQpost:
3308 case AArch64::STPQpre:
3309 case AArch64::STPSpost:
3310 case AArch64::STPSpre:
3311 case AArch64::STPWpost:
3312 case AArch64::STPWpre:
3313 case AArch64::STPXpost:
3314 case AArch64::STPXpre: {
3315 unsigned Rt = Inst.getOperand(1).getReg();
3316 unsigned Rt2 = Inst.getOperand(2).getReg();
3317 unsigned Rn = Inst.getOperand(3).getReg();
3318 if (RI->isSubRegisterEq(Rn, Rt))
3319 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3320 "is also a source");
3321 if (RI->isSubRegisterEq(Rn, Rt2))
3322 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3323 "is also a source");
3324 break;
3325 }
3326 case AArch64::LDRBBpre:
3327 case AArch64::LDRBpre:
3328 case AArch64::LDRHHpre:
3329 case AArch64::LDRHpre:
3330 case AArch64::LDRSBWpre:
3331 case AArch64::LDRSBXpre:
3332 case AArch64::LDRSHWpre:
3333 case AArch64::LDRSHXpre:
3334 case AArch64::LDRSWpre:
3335 case AArch64::LDRWpre:
3336 case AArch64::LDRXpre:
3337 case AArch64::LDRBBpost:
3338 case AArch64::LDRBpost:
3339 case AArch64::LDRHHpost:
3340 case AArch64::LDRHpost:
3341 case AArch64::LDRSBWpost:
3342 case AArch64::LDRSBXpost:
3343 case AArch64::LDRSHWpost:
3344 case AArch64::LDRSHXpost:
3345 case AArch64::LDRSWpost:
3346 case AArch64::LDRWpost:
3347 case AArch64::LDRXpost: {
3348 unsigned Rt = Inst.getOperand(1).getReg();
3349 unsigned Rn = Inst.getOperand(2).getReg();
3350 if (RI->isSubRegisterEq(Rn, Rt))
3351 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3352 "is also a source");
3353 break;
3354 }
3355 case AArch64::STRBBpost:
3356 case AArch64::STRBpost:
3357 case AArch64::STRHHpost:
3358 case AArch64::STRHpost:
3359 case AArch64::STRWpost:
3360 case AArch64::STRXpost:
3361 case AArch64::STRBBpre:
3362 case AArch64::STRBpre:
3363 case AArch64::STRHHpre:
3364 case AArch64::STRHpre:
3365 case AArch64::STRWpre:
3366 case AArch64::STRXpre: {
3367 unsigned Rt = Inst.getOperand(1).getReg();
3368 unsigned Rn = Inst.getOperand(2).getReg();
3369 if (RI->isSubRegisterEq(Rn, Rt))
3370 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3371 "is also a source");
3372 break;
3373 }
3374 }
3375
3376 // Now check immediate ranges. Separate from the above as there is overlap
3377 // in the instructions being checked and this keeps the nested conditionals
3378 // to a minimum.
3379 switch (Inst.getOpcode()) {
3380 case AArch64::ADDSWri:
3381 case AArch64::ADDSXri:
3382 case AArch64::ADDWri:
3383 case AArch64::ADDXri:
3384 case AArch64::SUBSWri:
3385 case AArch64::SUBSXri:
3386 case AArch64::SUBWri:
3387 case AArch64::SUBXri: {
3388 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3389 // some slight duplication here.
3390 if (Inst.getOperand(2).isExpr()) {
3391 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3392 AArch64MCExpr::VariantKind ELFRefKind;
3393 MCSymbolRefExpr::VariantKind DarwinRefKind;
3394 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003395 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3396
3397 // Only allow these with ADDXri.
3398 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3399 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3400 Inst.getOpcode() == AArch64::ADDXri)
3401 return false;
3402
3403 // Only allow these with ADDXri/ADDWri
3404 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3405 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3406 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3407 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3408 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3409 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3410 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3411 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3412 (Inst.getOpcode() == AArch64::ADDXri ||
3413 Inst.getOpcode() == AArch64::ADDWri))
3414 return false;
3415
3416 // Don't allow symbol refs in the immediate field otherwise
3417 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3418 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3419 // 'cmp w0, 'borked')
3420 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003421 }
Diana Picusc93518d2016-10-11 09:17:47 +00003422 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003423 }
3424 return false;
3425 }
3426 default:
3427 return false;
3428 }
3429}
3430
Craig Topper05515562017-10-26 06:46:41 +00003431static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3432 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003433
3434bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3435 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003436 switch (ErrCode) {
3437 case Match_MissingFeature:
3438 return Error(Loc,
3439 "instruction requires a CPU feature not currently enabled");
3440 case Match_InvalidOperand:
3441 return Error(Loc, "invalid operand for instruction");
3442 case Match_InvalidSuffix:
3443 return Error(Loc, "invalid type suffix for instruction");
3444 case Match_InvalidCondCode:
3445 return Error(Loc, "expected AArch64 condition code");
3446 case Match_AddSubRegExtendSmall:
3447 return Error(Loc,
3448 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3449 case Match_AddSubRegExtendLarge:
3450 return Error(Loc,
3451 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3452 case Match_AddSubSecondSource:
3453 return Error(Loc,
3454 "expected compatible register, symbol or integer in range [0, 4095]");
3455 case Match_LogicalSecondSource:
3456 return Error(Loc, "expected compatible register or logical immediate");
3457 case Match_InvalidMovImm32Shift:
3458 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3459 case Match_InvalidMovImm64Shift:
3460 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3461 case Match_AddSubRegShift32:
3462 return Error(Loc,
3463 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3464 case Match_AddSubRegShift64:
3465 return Error(Loc,
3466 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3467 case Match_InvalidFPImm:
3468 return Error(Loc,
3469 "expected compatible register or floating-point constant");
3470 case Match_InvalidMemoryIndexedSImm9:
3471 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003472 case Match_InvalidMemoryIndexedSImm10:
3473 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003474 case Match_InvalidMemoryIndexed4SImm7:
3475 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3476 case Match_InvalidMemoryIndexed8SImm7:
3477 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3478 case Match_InvalidMemoryIndexed16SImm7:
3479 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3480 case Match_InvalidMemoryWExtend8:
3481 return Error(Loc,
3482 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3483 case Match_InvalidMemoryWExtend16:
3484 return Error(Loc,
3485 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3486 case Match_InvalidMemoryWExtend32:
3487 return Error(Loc,
3488 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3489 case Match_InvalidMemoryWExtend64:
3490 return Error(Loc,
3491 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3492 case Match_InvalidMemoryWExtend128:
3493 return Error(Loc,
3494 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3495 case Match_InvalidMemoryXExtend8:
3496 return Error(Loc,
3497 "expected 'lsl' or 'sxtx' with optional shift of #0");
3498 case Match_InvalidMemoryXExtend16:
3499 return Error(Loc,
3500 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3501 case Match_InvalidMemoryXExtend32:
3502 return Error(Loc,
3503 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3504 case Match_InvalidMemoryXExtend64:
3505 return Error(Loc,
3506 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3507 case Match_InvalidMemoryXExtend128:
3508 return Error(Loc,
3509 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3510 case Match_InvalidMemoryIndexed1:
3511 return Error(Loc, "index must be an integer in range [0, 4095].");
3512 case Match_InvalidMemoryIndexed2:
3513 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3514 case Match_InvalidMemoryIndexed4:
3515 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3516 case Match_InvalidMemoryIndexed8:
3517 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3518 case Match_InvalidMemoryIndexed16:
3519 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003520 case Match_InvalidImm0_1:
3521 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003522 case Match_InvalidImm0_7:
3523 return Error(Loc, "immediate must be an integer in range [0, 7].");
3524 case Match_InvalidImm0_15:
3525 return Error(Loc, "immediate must be an integer in range [0, 15].");
3526 case Match_InvalidImm0_31:
3527 return Error(Loc, "immediate must be an integer in range [0, 31].");
3528 case Match_InvalidImm0_63:
3529 return Error(Loc, "immediate must be an integer in range [0, 63].");
3530 case Match_InvalidImm0_127:
3531 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003532 case Match_InvalidImm0_255:
3533 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003534 case Match_InvalidImm0_65535:
3535 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3536 case Match_InvalidImm1_8:
3537 return Error(Loc, "immediate must be an integer in range [1, 8].");
3538 case Match_InvalidImm1_16:
3539 return Error(Loc, "immediate must be an integer in range [1, 16].");
3540 case Match_InvalidImm1_32:
3541 return Error(Loc, "immediate must be an integer in range [1, 32].");
3542 case Match_InvalidImm1_64:
3543 return Error(Loc, "immediate must be an integer in range [1, 64].");
3544 case Match_InvalidIndex1:
3545 return Error(Loc, "expected lane specifier '[1]'");
3546 case Match_InvalidIndexB:
3547 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3548 case Match_InvalidIndexH:
3549 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3550 case Match_InvalidIndexS:
3551 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3552 case Match_InvalidIndexD:
3553 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3554 case Match_InvalidLabel:
3555 return Error(Loc, "expected label or encodable integer pc offset");
3556 case Match_MRS:
3557 return Error(Loc, "expected readable system register");
3558 case Match_MSR:
3559 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003560 case Match_InvalidComplexRotationEven:
3561 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3562 case Match_InvalidComplexRotationOdd:
3563 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003564 case Match_MnemonicFail: {
3565 std::string Suggestion = AArch64MnemonicSpellCheck(
3566 ((AArch64Operand &)*Operands[0]).getToken(),
3567 ComputeAvailableFeatures(STI->getFeatureBits()));
3568 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3569 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003570 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003571 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003572 }
3573}
3574
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003575static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003576
3577bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3578 OperandVector &Operands,
3579 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003580 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003581 bool MatchingInlineAsm) {
3582 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003583 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3584 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003585
David Blaikie960ea3f2014-06-08 16:18:35 +00003586 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003587 unsigned NumOperands = Operands.size();
3588
3589 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003590 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3591 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3592 if (Op2.isReg() && Op3.isImm()) {
3593 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003594 if (Op3CE) {
3595 uint64_t Op3Val = Op3CE->getValue();
3596 uint64_t NewOp3Val = 0;
3597 uint64_t NewOp4Val = 0;
3598 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003599 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003600 NewOp3Val = (32 - Op3Val) & 0x1f;
3601 NewOp4Val = 31 - Op3Val;
3602 } else {
3603 NewOp3Val = (64 - Op3Val) & 0x3f;
3604 NewOp4Val = 63 - Op3Val;
3605 }
3606
Jim Grosbach13760bd2015-05-30 01:25:56 +00003607 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3608 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003609
3610 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003611 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003612 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003613 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3614 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3615 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003616 }
3617 }
Tim Northover03b99f62015-04-30 18:28:58 +00003618 } else if (NumOperands == 4 && Tok == "bfc") {
3619 // FIXME: Horrible hack to handle BFC->BFM alias.
3620 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3621 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3622 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3623
3624 if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
3625 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3626 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3627
3628 if (LSBCE && WidthCE) {
3629 uint64_t LSB = LSBCE->getValue();
3630 uint64_t Width = WidthCE->getValue();
3631
3632 uint64_t RegWidth = 0;
3633 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3634 Op1.getReg()))
3635 RegWidth = 64;
3636 else
3637 RegWidth = 32;
3638
3639 if (LSB >= RegWidth)
3640 return Error(LSBOp.getStartLoc(),
3641 "expected integer in range [0, 31]");
3642 if (Width < 1 || Width > RegWidth)
3643 return Error(WidthOp.getStartLoc(),
3644 "expected integer in range [1, 32]");
3645
3646 uint64_t ImmR = 0;
3647 if (RegWidth == 32)
3648 ImmR = (32 - LSB) & 0x1f;
3649 else
3650 ImmR = (64 - LSB) & 0x3f;
3651
3652 uint64_t ImmS = Width - 1;
3653
3654 if (ImmR != 0 && ImmS >= ImmR)
3655 return Error(WidthOp.getStartLoc(),
3656 "requested insert overflows register");
3657
Jim Grosbach13760bd2015-05-30 01:25:56 +00003658 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3659 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003660 Operands[0] = AArch64Operand::CreateToken(
3661 "bfm", false, Op.getStartLoc(), getContext());
3662 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003663 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3664 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003665 Operands[3] = AArch64Operand::CreateImm(
3666 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3667 Operands.emplace_back(
3668 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3669 WidthOp.getEndLoc(), getContext()));
3670 }
3671 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003672 } else if (NumOperands == 5) {
3673 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3674 // UBFIZ -> UBFM aliases.
3675 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003676 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3677 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3678 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003679
David Blaikie960ea3f2014-06-08 16:18:35 +00003680 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3681 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3682 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003683
3684 if (Op3CE && Op4CE) {
3685 uint64_t Op3Val = Op3CE->getValue();
3686 uint64_t Op4Val = Op4CE->getValue();
3687
3688 uint64_t RegWidth = 0;
3689 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003690 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003691 RegWidth = 64;
3692 else
3693 RegWidth = 32;
3694
3695 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003696 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003697 "expected integer in range [0, 31]");
3698 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003699 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003700 "expected integer in range [1, 32]");
3701
3702 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003703 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003704 NewOp3Val = (32 - Op3Val) & 0x1f;
3705 else
3706 NewOp3Val = (64 - Op3Val) & 0x3f;
3707
3708 uint64_t NewOp4Val = Op4Val - 1;
3709
3710 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003711 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003712 "requested insert overflows register");
3713
3714 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003715 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003716 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003717 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003718 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003719 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003720 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003721 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003722 if (Tok == "bfi")
3723 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003724 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003725 else if (Tok == "sbfiz")
3726 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003727 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003728 else if (Tok == "ubfiz")
3729 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003730 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003731 else
3732 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003733 }
3734 }
3735
3736 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3737 // UBFX -> UBFM aliases.
3738 } else if (NumOperands == 5 &&
3739 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003740 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3741 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3742 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003743
David Blaikie960ea3f2014-06-08 16:18:35 +00003744 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3745 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3746 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003747
3748 if (Op3CE && Op4CE) {
3749 uint64_t Op3Val = Op3CE->getValue();
3750 uint64_t Op4Val = Op4CE->getValue();
3751
3752 uint64_t RegWidth = 0;
3753 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003754 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003755 RegWidth = 64;
3756 else
3757 RegWidth = 32;
3758
3759 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003760 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003761 "expected integer in range [0, 31]");
3762 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003763 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003764 "expected integer in range [1, 32]");
3765
3766 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3767
3768 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003769 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003770 "requested extract overflows register");
3771
3772 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003773 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003774 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003775 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003776 if (Tok == "bfxil")
3777 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003778 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003779 else if (Tok == "sbfx")
3780 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003781 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003782 else if (Tok == "ubfx")
3783 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003784 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003785 else
3786 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003787 }
3788 }
3789 }
3790 }
Tim Northover9097a072017-12-18 10:36:00 +00003791
3792 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
3793 // instruction for FP registers correctly in some rare circumstances. Convert
3794 // it to a safe instruction and warn (because silently changing someone's
3795 // assembly is rude).
3796 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
3797 NumOperands == 4 && Tok == "movi") {
3798 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3799 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3800 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3801 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
3802 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
3803 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
3804 if (Suffix.lower() == ".2d" &&
3805 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
3806 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
3807 " correctly on this CPU, converting to equivalent movi.16b");
3808 // Switch the suffix to .16b.
3809 unsigned Idx = Op1.isToken() ? 1 : 2;
3810 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
3811 getContext());
3812 }
3813 }
3814 }
3815
Tim Northover3b0846e2014-05-24 12:50:23 +00003816 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3817 // InstAlias can't quite handle this since the reg classes aren't
3818 // subclasses.
3819 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3820 // The source register can be Wn here, but the matcher expects a
3821 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003822 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3823 if (Op.isReg()) {
3824 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003825 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3826 Op.getStartLoc(), Op.getEndLoc(),
3827 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003828 }
3829 }
3830 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3831 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003832 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3833 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003834 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003835 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003836 // The source register can be Wn here, but the matcher expects a
3837 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003838 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3839 if (Op.isReg()) {
3840 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003841 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3842 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003843 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003844 }
3845 }
3846 }
3847 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3848 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003849 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3850 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003851 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003852 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003853 // The source register can be Wn here, but the matcher expects a
3854 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003855 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3856 if (Op.isReg()) {
3857 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003858 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3859 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003860 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003861 }
3862 }
3863 }
3864
Tim Northover3b0846e2014-05-24 12:50:23 +00003865 MCInst Inst;
3866 // First try to match against the secondary set of tables containing the
3867 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3868 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003869 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003870
3871 // If that fails, try against the alternate table containing long-form NEON:
3872 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003873 if (MatchResult != Match_Success) {
3874 // But first, save the short-form match result: we can use it in case the
3875 // long-form match also fails.
3876 auto ShortFormNEONErrorInfo = ErrorInfo;
3877 auto ShortFormNEONMatchResult = MatchResult;
3878
Tim Northover3b0846e2014-05-24 12:50:23 +00003879 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003880 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003881
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003882 // Now, both matches failed, and the long-form match failed on the mnemonic
3883 // suffix token operand. The short-form match failure is probably more
3884 // relevant: use it instead.
3885 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003886 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003887 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3888 MatchResult = ShortFormNEONMatchResult;
3889 ErrorInfo = ShortFormNEONErrorInfo;
3890 }
3891 }
3892
Tim Northover3b0846e2014-05-24 12:50:23 +00003893 switch (MatchResult) {
3894 case Match_Success: {
3895 // Perform range checking and other semantic validations
3896 SmallVector<SMLoc, 8> OperandLocs;
3897 NumOperands = Operands.size();
3898 for (unsigned i = 1; i < NumOperands; ++i)
3899 OperandLocs.push_back(Operands[i]->getStartLoc());
3900 if (validateInstruction(Inst, OperandLocs))
3901 return true;
3902
3903 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003904 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00003905 return false;
3906 }
3907 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003908 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003909 // Special case the error message for the very common case where only
3910 // a single subtarget feature is missing (neon, e.g.).
3911 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003912 uint64_t Mask = 1;
3913 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
3914 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003915 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003916 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00003917 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003918 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00003919 }
3920 return Error(IDLoc, Msg);
3921 }
3922 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003923 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003924 case Match_InvalidOperand: {
3925 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00003926
Tim Northover26bb14e2014-08-18 11:49:42 +00003927 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003928 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00003929 return Error(IDLoc, "too few operands for instruction",
3930 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003931
David Blaikie960ea3f2014-06-08 16:18:35 +00003932 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003933 if (ErrorLoc == SMLoc())
3934 ErrorLoc = IDLoc;
3935 }
3936 // If the match failed on a suffix token operand, tweak the diagnostic
3937 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00003938 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
3939 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00003940 MatchResult = Match_InvalidSuffix;
3941
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003942 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003943 }
3944 case Match_InvalidMemoryIndexed1:
3945 case Match_InvalidMemoryIndexed2:
3946 case Match_InvalidMemoryIndexed4:
3947 case Match_InvalidMemoryIndexed8:
3948 case Match_InvalidMemoryIndexed16:
3949 case Match_InvalidCondCode:
3950 case Match_AddSubRegExtendSmall:
3951 case Match_AddSubRegExtendLarge:
3952 case Match_AddSubSecondSource:
3953 case Match_LogicalSecondSource:
3954 case Match_AddSubRegShift32:
3955 case Match_AddSubRegShift64:
3956 case Match_InvalidMovImm32Shift:
3957 case Match_InvalidMovImm64Shift:
3958 case Match_InvalidFPImm:
3959 case Match_InvalidMemoryWExtend8:
3960 case Match_InvalidMemoryWExtend16:
3961 case Match_InvalidMemoryWExtend32:
3962 case Match_InvalidMemoryWExtend64:
3963 case Match_InvalidMemoryWExtend128:
3964 case Match_InvalidMemoryXExtend8:
3965 case Match_InvalidMemoryXExtend16:
3966 case Match_InvalidMemoryXExtend32:
3967 case Match_InvalidMemoryXExtend64:
3968 case Match_InvalidMemoryXExtend128:
3969 case Match_InvalidMemoryIndexed4SImm7:
3970 case Match_InvalidMemoryIndexed8SImm7:
3971 case Match_InvalidMemoryIndexed16SImm7:
3972 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00003973 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003974 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00003975 case Match_InvalidImm0_7:
3976 case Match_InvalidImm0_15:
3977 case Match_InvalidImm0_31:
3978 case Match_InvalidImm0_63:
3979 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003980 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00003981 case Match_InvalidImm0_65535:
3982 case Match_InvalidImm1_8:
3983 case Match_InvalidImm1_16:
3984 case Match_InvalidImm1_32:
3985 case Match_InvalidImm1_64:
3986 case Match_InvalidIndex1:
3987 case Match_InvalidIndexB:
3988 case Match_InvalidIndexH:
3989 case Match_InvalidIndexS:
3990 case Match_InvalidIndexD:
3991 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00003992 case Match_InvalidComplexRotationEven:
3993 case Match_InvalidComplexRotationOdd:
Tim Northover3b0846e2014-05-24 12:50:23 +00003994 case Match_MSR:
3995 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00003996 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00003997 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003998 // Any time we get here, there's nothing fancy to do. Just get the
3999 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004000 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004001 if (ErrorLoc == SMLoc())
4002 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004003 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004004 }
4005 }
4006
4007 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004008}
4009
4010/// ParseDirective parses the arm specific directives
4011bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004012 const MCObjectFileInfo::Environment Format =
4013 getContext().getObjectFileInfo()->getObjectFileType();
4014 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4015 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004016
Tim Northover3b0846e2014-05-24 12:50:23 +00004017 StringRef IDVal = DirectiveID.getIdentifier();
4018 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004019 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004020 parseDirectiveArch(Loc);
4021 else if (IDVal == ".cpu")
4022 parseDirectiveCPU(Loc);
4023 else if (IDVal == ".hword")
4024 parseDirectiveWord(2, Loc);
4025 else if (IDVal == ".word")
4026 parseDirectiveWord(4, Loc);
4027 else if (IDVal == ".xword")
4028 parseDirectiveWord(8, Loc);
4029 else if (IDVal == ".tlsdesccall")
4030 parseDirectiveTLSDescCall(Loc);
4031 else if (IDVal == ".ltorg" || IDVal == ".pool")
4032 parseDirectiveLtorg(Loc);
4033 else if (IDVal == ".unreq")
4034 parseDirectiveUnreq(Loc);
4035 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004036 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004037 parseDirectiveInst(Loc);
4038 else
4039 return true;
4040 } else if (IDVal == MCLOHDirectiveName())
4041 parseDirectiveLOH(IDVal, Loc);
4042 else
4043 return true;
4044 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004045}
4046
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004047static const struct {
4048 const char *Name;
4049 const FeatureBitset Features;
4050} ExtensionMap[] = {
4051 { "crc", {AArch64::FeatureCRC} },
4052 { "crypto", {AArch64::FeatureCrypto} },
4053 { "fp", {AArch64::FeatureFPARMv8} },
4054 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004055 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004056 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004057
4058 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004059 { "pan", {} },
4060 { "lor", {} },
4061 { "rdma", {} },
4062 { "profile", {} },
4063};
4064
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004065/// parseDirectiveArch
4066/// ::= .arch token
4067bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4068 SMLoc ArchLoc = getLoc();
4069
4070 StringRef Arch, ExtensionString;
4071 std::tie(Arch, ExtensionString) =
4072 getParser().parseStringToEndOfStatement().trim().split('+');
4073
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004074 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4075 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004076 return Error(ArchLoc, "unknown arch name");
4077
4078 if (parseToken(AsmToken::EndOfStatement))
4079 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004080
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004081 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004082 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004083 AArch64::getArchFeatures(ID, AArch64Features);
4084 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4085 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004086
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004087 MCSubtargetInfo &STI = copySTI();
4088 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4089 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4090
4091 SmallVector<StringRef, 4> RequestedExtensions;
4092 if (!ExtensionString.empty())
4093 ExtensionString.split(RequestedExtensions, '+');
4094
4095 FeatureBitset Features = STI.getFeatureBits();
4096 for (auto Name : RequestedExtensions) {
4097 bool EnableFeature = true;
4098
4099 if (Name.startswith_lower("no")) {
4100 EnableFeature = false;
4101 Name = Name.substr(2);
4102 }
4103
4104 for (const auto &Extension : ExtensionMap) {
4105 if (Extension.Name != Name)
4106 continue;
4107
4108 if (Extension.Features.none())
4109 report_fatal_error("unsupported architectural extension: " + Name);
4110
4111 FeatureBitset ToggleFeatures = EnableFeature
4112 ? (~Features & Extension.Features)
4113 : ( Features & Extension.Features);
4114 uint64_t Features =
4115 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4116 setAvailableFeatures(Features);
4117 break;
4118 }
4119 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004120 return false;
4121}
4122
Tim Northover8b96c7e2017-05-15 19:42:15 +00004123static SMLoc incrementLoc(SMLoc L, int Offset) {
4124 return SMLoc::getFromPointer(L.getPointer() + Offset);
4125}
4126
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004127/// parseDirectiveCPU
4128/// ::= .cpu id
4129bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004130 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004131
4132 StringRef CPU, ExtensionString;
4133 std::tie(CPU, ExtensionString) =
4134 getParser().parseStringToEndOfStatement().trim().split('+');
4135
Nirav Davee833c6c2016-11-08 18:31:04 +00004136 if (parseToken(AsmToken::EndOfStatement))
4137 return true;
4138
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004139 SmallVector<StringRef, 4> RequestedExtensions;
4140 if (!ExtensionString.empty())
4141 ExtensionString.split(RequestedExtensions, '+');
4142
4143 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4144 // once that is tablegen'ed
4145 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004146 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004147 return false;
4148 }
4149
4150 MCSubtargetInfo &STI = copySTI();
4151 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004152 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004153
4154 FeatureBitset Features = STI.getFeatureBits();
4155 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004156 // Advance source location past '+'.
4157 CurLoc = incrementLoc(CurLoc, 1);
4158
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004159 bool EnableFeature = true;
4160
4161 if (Name.startswith_lower("no")) {
4162 EnableFeature = false;
4163 Name = Name.substr(2);
4164 }
4165
Tim Northover8b96c7e2017-05-15 19:42:15 +00004166 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004167 for (const auto &Extension : ExtensionMap) {
4168 if (Extension.Name != Name)
4169 continue;
4170
4171 if (Extension.Features.none())
4172 report_fatal_error("unsupported architectural extension: " + Name);
4173
4174 FeatureBitset ToggleFeatures = EnableFeature
4175 ? (~Features & Extension.Features)
4176 : ( Features & Extension.Features);
4177 uint64_t Features =
4178 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4179 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004180 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004181
4182 break;
4183 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004184
4185 if (!FoundExtension)
4186 Error(CurLoc, "unsupported architectural extension");
4187
4188 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004189 }
4190 return false;
4191}
4192
Tim Northover3b0846e2014-05-24 12:50:23 +00004193/// parseDirectiveWord
4194/// ::= .word [ expression (, expression)* ]
4195bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004196 auto parseOp = [&]() -> bool {
4197 const MCExpr *Value;
4198 if (getParser().parseExpression(Value))
4199 return true;
4200 getParser().getStreamer().EmitValue(Value, Size, L);
4201 return false;
4202 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004203
Nirav Davee833c6c2016-11-08 18:31:04 +00004204 if (parseMany(parseOp))
4205 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004206 return false;
4207}
4208
Chad Rosierdcd2a302014-10-22 20:35:57 +00004209/// parseDirectiveInst
4210/// ::= .inst opcode [, ...]
4211bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004212 if (getLexer().is(AsmToken::EndOfStatement))
4213 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004214
Nirav Davee833c6c2016-11-08 18:31:04 +00004215 auto parseOp = [&]() -> bool {
4216 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004217 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004218 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4219 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004220 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004221 if (check(!Value, L, "expected constant expression"))
4222 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004223 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004224 return false;
4225 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004226
Nirav Davee833c6c2016-11-08 18:31:04 +00004227 if (parseMany(parseOp))
4228 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004229 return false;
4230}
4231
Tim Northover3b0846e2014-05-24 12:50:23 +00004232// parseDirectiveTLSDescCall:
4233// ::= .tlsdesccall symbol
4234bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4235 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004236 if (check(getParser().parseIdentifier(Name), L,
4237 "expected symbol after directive") ||
4238 parseToken(AsmToken::EndOfStatement))
4239 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004240
Jim Grosbach6f482002015-05-18 18:43:14 +00004241 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004242 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4243 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004244
4245 MCInst Inst;
4246 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004247 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004248
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004249 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004250 return false;
4251}
4252
4253/// ::= .loh <lohName | lohId> label1, ..., labelN
4254/// The number of arguments depends on the loh identifier.
4255bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004256 MCLOHType Kind;
4257 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4258 if (getParser().getTok().isNot(AsmToken::Integer))
4259 return TokError("expected an identifier or a number in directive");
4260 // We successfully get a numeric value for the identifier.
4261 // Check if it is valid.
4262 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004263 if (Id <= -1U && !isValidMCLOHType(Id))
4264 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004265 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004266 } else {
4267 StringRef Name = getTok().getIdentifier();
4268 // We successfully parse an identifier.
4269 // Check if it is a recognized one.
4270 int Id = MCLOHNameToId(Name);
4271
4272 if (Id == -1)
4273 return TokError("invalid identifier in directive");
4274 Kind = (MCLOHType)Id;
4275 }
4276 // Consume the identifier.
4277 Lex();
4278 // Get the number of arguments of this LOH.
4279 int NbArgs = MCLOHIdToNbArgs(Kind);
4280
4281 assert(NbArgs != -1 && "Invalid number of arguments");
4282
4283 SmallVector<MCSymbol *, 3> Args;
4284 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4285 StringRef Name;
4286 if (getParser().parseIdentifier(Name))
4287 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004288 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004289
4290 if (Idx + 1 == NbArgs)
4291 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004292 if (parseToken(AsmToken::Comma,
4293 "unexpected token in '" + Twine(IDVal) + "' directive"))
4294 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004295 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004296 if (parseToken(AsmToken::EndOfStatement,
4297 "unexpected token in '" + Twine(IDVal) + "' directive"))
4298 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004299
4300 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4301 return false;
4302}
4303
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004304/// parseDirectiveLtorg
4305/// ::= .ltorg | .pool
4306bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004307 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4308 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004309 getTargetStreamer().emitCurrentConstantPool();
4310 return false;
4311}
4312
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004313/// parseDirectiveReq
4314/// ::= name .req registername
4315bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004316 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004317 Parser.Lex(); // Eat the '.req' token.
4318 SMLoc SRegLoc = getLoc();
Sander de Smalen8e607342017-11-15 15:44:43 +00004319 int RegNum = tryParseRegister();
Florian Hahnc4422242017-11-07 13:07:50 +00004320 RegKind RegisterKind = RegKind::Scalar;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004321
Sander de Smalen8e607342017-11-15 15:44:43 +00004322 if (RegNum == -1) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004323 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004324 RegisterKind = RegKind::NeonVector;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004325 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004326 if (!Kind.empty())
4327 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004328 }
4329
Sander de Smalen8e607342017-11-15 15:44:43 +00004330 if (RegNum == -1) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004331 StringRef Kind;
4332 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen8e607342017-11-15 15:44:43 +00004333 OperandMatchResultTy Res =
4334 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4335
4336 if (Res == MatchOperand_ParseFail)
4337 return true;
4338
4339 if (Res == MatchOperand_Success && !Kind.empty())
4340 return Error(SRegLoc,
4341 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004342 }
4343
Sander de Smalen8e607342017-11-15 15:44:43 +00004344 if (RegNum == -1)
Nirav Dave2364748a2016-09-16 18:30:20 +00004345 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004346
4347 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004348 if (parseToken(AsmToken::EndOfStatement,
4349 "unexpected input in .req directive"))
4350 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004351
Sander de Smalen8e607342017-11-15 15:44:43 +00004352 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004353 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004354 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4355
Nirav Dave2364748a2016-09-16 18:30:20 +00004356 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004357}
4358
4359/// parseDirectiveUneq
4360/// ::= .unreq registername
4361bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004362 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004363 if (getTok().isNot(AsmToken::Identifier))
4364 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004365 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4366 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004367 if (parseToken(AsmToken::EndOfStatement))
4368 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004369 return false;
4370}
4371
Tim Northover3b0846e2014-05-24 12:50:23 +00004372bool
4373AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4374 AArch64MCExpr::VariantKind &ELFRefKind,
4375 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4376 int64_t &Addend) {
4377 ELFRefKind = AArch64MCExpr::VK_INVALID;
4378 DarwinRefKind = MCSymbolRefExpr::VK_None;
4379 Addend = 0;
4380
4381 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4382 ELFRefKind = AE->getKind();
4383 Expr = AE->getSubExpr();
4384 }
4385
4386 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4387 if (SE) {
4388 // It's a simple symbol reference with no addend.
4389 DarwinRefKind = SE->getKind();
4390 return true;
4391 }
4392
4393 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4394 if (!BE)
4395 return false;
4396
4397 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4398 if (!SE)
4399 return false;
4400 DarwinRefKind = SE->getKind();
4401
4402 if (BE->getOpcode() != MCBinaryExpr::Add &&
4403 BE->getOpcode() != MCBinaryExpr::Sub)
4404 return false;
4405
4406 // See if the addend is is a constant, otherwise there's more going
4407 // on here than we can deal with.
4408 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4409 if (!AddendExpr)
4410 return false;
4411
4412 Addend = AddendExpr->getValue();
4413 if (BE->getOpcode() == MCBinaryExpr::Sub)
4414 Addend = -Addend;
4415
4416 // It's some symbol reference + a constant addend, but really
4417 // shouldn't use both Darwin and ELF syntax.
4418 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4419 DarwinRefKind == MCSymbolRefExpr::VK_None;
4420}
4421
4422/// Force static initialization.
4423extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004424 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4425 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4426 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004427}
4428
4429#define GET_REGISTER_MATCHER
4430#define GET_SUBTARGET_FEATURE_NAME
4431#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004432#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004433#include "AArch64GenAsmMatcher.inc"
4434
4435// Define this matcher function after the auto-generated include so we
4436// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004437unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004438 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004439 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004440 // If the kind is a token for a literal immediate, check if our asm
4441 // operand matches. This is for InstAliases which have a fixed-value
4442 // immediate in the syntax.
4443 int64_t ExpectedVal;
4444 switch (Kind) {
4445 default:
4446 return Match_InvalidOperand;
4447 case MCK__35_0:
4448 ExpectedVal = 0;
4449 break;
4450 case MCK__35_1:
4451 ExpectedVal = 1;
4452 break;
4453 case MCK__35_12:
4454 ExpectedVal = 12;
4455 break;
4456 case MCK__35_16:
4457 ExpectedVal = 16;
4458 break;
4459 case MCK__35_2:
4460 ExpectedVal = 2;
4461 break;
4462 case MCK__35_24:
4463 ExpectedVal = 24;
4464 break;
4465 case MCK__35_3:
4466 ExpectedVal = 3;
4467 break;
4468 case MCK__35_32:
4469 ExpectedVal = 32;
4470 break;
4471 case MCK__35_4:
4472 ExpectedVal = 4;
4473 break;
4474 case MCK__35_48:
4475 ExpectedVal = 48;
4476 break;
4477 case MCK__35_6:
4478 ExpectedVal = 6;
4479 break;
4480 case MCK__35_64:
4481 ExpectedVal = 64;
4482 break;
4483 case MCK__35_8:
4484 ExpectedVal = 8;
4485 break;
4486 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004487 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004488 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004489 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004490 if (!CE)
4491 return Match_InvalidOperand;
4492 if (CE->getValue() == ExpectedVal)
4493 return Match_Success;
4494 return Match_InvalidOperand;
4495}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004496
Alex Bradbury58eba092016-11-01 16:32:05 +00004497OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004498AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4499
4500 SMLoc S = getLoc();
4501
4502 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4503 Error(S, "expected register");
4504 return MatchOperand_ParseFail;
4505 }
4506
4507 int FirstReg = tryParseRegister();
4508 if (FirstReg == -1) {
4509 return MatchOperand_ParseFail;
4510 }
4511 const MCRegisterClass &WRegClass =
4512 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4513 const MCRegisterClass &XRegClass =
4514 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4515
4516 bool isXReg = XRegClass.contains(FirstReg),
4517 isWReg = WRegClass.contains(FirstReg);
4518 if (!isXReg && !isWReg) {
4519 Error(S, "expected first even register of a "
4520 "consecutive same-size even/odd register pair");
4521 return MatchOperand_ParseFail;
4522 }
4523
4524 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4525 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4526
4527 if (FirstEncoding & 0x1) {
4528 Error(S, "expected first even register of a "
4529 "consecutive same-size even/odd register pair");
4530 return MatchOperand_ParseFail;
4531 }
4532
4533 SMLoc M = getLoc();
4534 if (getParser().getTok().isNot(AsmToken::Comma)) {
4535 Error(M, "expected comma");
4536 return MatchOperand_ParseFail;
4537 }
4538 // Eat the comma
4539 getParser().Lex();
4540
4541 SMLoc E = getLoc();
4542 int SecondReg = tryParseRegister();
4543 if (SecondReg ==-1) {
4544 return MatchOperand_ParseFail;
4545 }
4546
Eugene Zelenko049b0172017-01-06 00:30:53 +00004547 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004548 (isXReg && !XRegClass.contains(SecondReg)) ||
4549 (isWReg && !WRegClass.contains(SecondReg))) {
4550 Error(E,"expected second odd register of a "
4551 "consecutive same-size even/odd register pair");
4552 return MatchOperand_ParseFail;
4553 }
Joel Jones504bf332016-10-24 13:37:13 +00004554
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004555 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004556 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004557 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4558 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4559 } else {
4560 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4561 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4562 }
4563
Florian Hahnc4422242017-11-07 13:07:50 +00004564 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4565 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004566
4567 return MatchOperand_Success;
4568}
Florian Hahn91f11e52017-11-07 16:45:48 +00004569
4570template <bool ParseSuffix>
4571OperandMatchResultTy
4572AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004573 const SMLoc S = getLoc();
4574 // Check for a SVE vector register specifier first.
Sander de Smalen8e607342017-11-15 15:44:43 +00004575 int RegNum = -1;
Florian Hahn91f11e52017-11-07 16:45:48 +00004576 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004577
Sander de Smalen8e607342017-11-15 15:44:43 +00004578 OperandMatchResultTy Res =
4579 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4580
4581 if (Res != MatchOperand_Success)
4582 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004583
4584 if (ParseSuffix && Kind.empty())
4585 return MatchOperand_NoMatch;
4586
4587 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
4588 .Case("", -1)
4589 .Case(".b", 8)
4590 .Case(".h", 16)
4591 .Case(".s", 32)
4592 .Case(".d", 64)
4593 .Case(".q", 128)
4594 .Default(0);
4595 if (!ElementWidth)
4596 return MatchOperand_NoMatch;
4597
4598 Operands.push_back(
4599 AArch64Operand::CreateReg(RegNum, RegKind::SVEDataVector, ElementWidth,
4600 S, S, getContext()));
4601
4602 return MatchOperand_Success;
4603}