blob: fd2ef18fbe0a89462a0efc94f1588a4f2221ee47 [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/AArch64AddressingModes.h"
11#include "MCTargetDesc/AArch64MCExpr.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000012#include "MCTargetDesc/AArch64MCTargetDesc.h"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000013#include "MCTargetDesc/AArch64TargetStreamer.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000014#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000015#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000016#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000017#include "llvm/ADT/ArrayRef.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000018#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "llvm/ADT/SmallVector.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000020#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000021#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000023#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000025#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000028#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000029#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000030#include "llvm/MC/MCParser/MCAsmLexer.h"
31#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000032#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000033#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000034#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000035#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSubtargetInfo.h"
38#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000039#include "llvm/MC/MCTargetOptions.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000043#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000044#include "llvm/Support/MathExtras.h"
45#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000046#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000047#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000049#include <cassert>
50#include <cctype>
51#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000052#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000053#include <string>
54#include <tuple>
55#include <utility>
56#include <vector>
57
Tim Northover3b0846e2014-05-24 12:50:23 +000058using namespace llvm;
59
60namespace {
61
Sander de Smalen6a3bf1f2017-11-29 15:14:39 +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
Sander de Smalen6a3bf1f2017-11-29 15:14:39 +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
Sander de Smalen6a3bf1f2017-11-29 15:14:39 +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
Sander de Smalen6a3bf1f2017-11-29 15:14:39 +00001939static bool isSVEDataVectorRegister(StringRef Name) {
1940 return Name[0] == 'z';
Florian Hahn91f11e52017-11-07 16:45:48 +00001941}
1942
Tim Northover3b0846e2014-05-24 12:50:23 +00001943static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1944 char &ElementKind) {
1945 assert(isValidVectorKind(Name));
1946
1947 ElementKind = Name.lower()[Name.size() - 1];
1948 NumElements = 0;
1949
1950 if (Name.size() == 2)
1951 return;
1952
1953 // Parse the lane count
1954 Name = Name.drop_front();
1955 while (isdigit(Name.front())) {
1956 NumElements = 10 * NumElements + (Name.front() - '0');
1957 Name = Name.drop_front();
1958 }
1959}
1960
1961bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1962 SMLoc &EndLoc) {
1963 StartLoc = getLoc();
1964 RegNo = tryParseRegister();
1965 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1966 return (RegNo == (unsigned)-1);
1967}
1968
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001969// Matches a register name or register alias previously defined by '.req'
1970unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001971 RegKind Kind) {
1972 unsigned RegNum;
1973 switch (Kind) {
1974 case RegKind::Scalar:
1975 RegNum = MatchRegisterName(Name);
1976 break;
1977 case RegKind::NeonVector:
1978 RegNum = MatchNeonVectorRegName(Name);
1979 break;
Florian Hahn91f11e52017-11-07 16:45:48 +00001980 case RegKind::SVEDataVector:
1981 RegNum = matchSVEDataVectorRegName(Name);
1982 break;
Florian Hahnc4422242017-11-07 13:07:50 +00001983 }
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001984
Florian Hahnc4422242017-11-07 13:07:50 +00001985 if (!RegNum) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001986 // Check for aliases registered via .req. Canonicalize to lower case.
1987 // That's more consistent since register names are case insensitive, and
1988 // it's how the original entry was passed in from MC/MCParser/AsmParser.
1989 auto Entry = RegisterReqs.find(Name.lower());
1990 if (Entry == RegisterReqs.end())
1991 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00001992
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001993 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00001994 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001995 RegNum = Entry->getValue().second;
1996 }
1997 return RegNum;
1998}
1999
Tim Northover3b0846e2014-05-24 12:50:23 +00002000/// tryParseRegister - Try to parse a register name. The token must be an
2001/// Identifier when called, and if it is a register name the token is eaten and
2002/// the register is added to the operand list.
2003int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002004 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002005 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002006 if (Tok.isNot(AsmToken::Identifier))
2007 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00002008
2009 std::string lowerCase = Tok.getString().lower();
Sander de Smalen6a3bf1f2017-11-29 15:14:39 +00002010 if (isSVEDataVectorRegister(lowerCase))
Florian Hahn91f11e52017-11-07 16:45:48 +00002011 return -1;
2012
Florian Hahnc4422242017-11-07 13:07:50 +00002013 unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00002014 // Also handle a few aliases of registers.
2015 if (RegNum == 0)
2016 RegNum = StringSwitch<unsigned>(lowerCase)
2017 .Case("fp", AArch64::FP)
2018 .Case("lr", AArch64::LR)
2019 .Case("x31", AArch64::XZR)
2020 .Case("w31", AArch64::WZR)
2021 .Default(0);
2022
2023 if (RegNum == 0)
2024 return -1;
2025
2026 Parser.Lex(); // Eat identifier token.
2027 return RegNum;
2028}
2029
2030/// tryMatchVectorRegister - Try to parse a vector register name with optional
2031/// kind specifier. If it is a register specifier, eat the token and return it.
2032int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002033 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002034 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2035 TokError("vector register expected");
2036 return -1;
2037 }
2038
2039 StringRef Name = Parser.getTok().getString();
2040 // If there is a kind specifier, it's separated from the register name by
2041 // a '.'.
2042 size_t Start = 0, Next = Name.find('.');
2043 StringRef Head = Name.slice(Start, Next);
Florian Hahnc4422242017-11-07 13:07:50 +00002044 unsigned RegNum = matchRegisterNameAlias(Head, RegKind::NeonVector);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002045
Tim Northover3b0846e2014-05-24 12:50:23 +00002046 if (RegNum) {
2047 if (Next != StringRef::npos) {
2048 Kind = Name.slice(Next, StringRef::npos);
2049 if (!isValidVectorKind(Kind)) {
2050 TokError("invalid vector kind qualifier");
2051 return -1;
2052 }
2053 }
2054 Parser.Lex(); // Eat the register token.
2055 return RegNum;
2056 }
2057
2058 if (expected)
2059 TokError("vector register expected");
2060 return -1;
2061}
2062
2063/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002064OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002065AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002066 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002067 SMLoc S = getLoc();
2068
2069 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2070 Error(S, "Expected cN operand where 0 <= N <= 15");
2071 return MatchOperand_ParseFail;
2072 }
2073
2074 StringRef Tok = Parser.getTok().getIdentifier();
2075 if (Tok[0] != 'c' && Tok[0] != 'C') {
2076 Error(S, "Expected cN operand where 0 <= N <= 15");
2077 return MatchOperand_ParseFail;
2078 }
2079
2080 uint32_t CRNum;
2081 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2082 if (BadNum || CRNum > 15) {
2083 Error(S, "Expected cN operand where 0 <= N <= 15");
2084 return MatchOperand_ParseFail;
2085 }
2086
2087 Parser.Lex(); // Eat identifier token.
2088 Operands.push_back(
2089 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2090 return MatchOperand_Success;
2091}
2092
2093/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002094OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002095AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002096 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002097 SMLoc S = getLoc();
2098 const AsmToken &Tok = Parser.getTok();
2099 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002100 // Eat optional hash.
2101 if (parseOptionalToken(AsmToken::Hash) ||
2102 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002103 const MCExpr *ImmVal;
2104 if (getParser().parseExpression(ImmVal))
2105 return MatchOperand_ParseFail;
2106
2107 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2108 if (!MCE) {
2109 TokError("immediate value expected for prefetch operand");
2110 return MatchOperand_ParseFail;
2111 }
2112 unsigned prfop = MCE->getValue();
2113 if (prfop > 31) {
2114 TokError("prefetch operand out of range, [0,31] expected");
2115 return MatchOperand_ParseFail;
2116 }
2117
Tim Northovere6ae6762016-07-05 21:23:04 +00002118 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2119 Operands.push_back(AArch64Operand::CreatePrefetch(
2120 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002121 return MatchOperand_Success;
2122 }
2123
2124 if (Tok.isNot(AsmToken::Identifier)) {
2125 TokError("pre-fetch hint expected");
2126 return MatchOperand_ParseFail;
2127 }
2128
Tim Northovere6ae6762016-07-05 21:23:04 +00002129 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2130 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002131 TokError("pre-fetch hint expected");
2132 return MatchOperand_ParseFail;
2133 }
2134
2135 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002136 Operands.push_back(AArch64Operand::CreatePrefetch(
2137 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002138 return MatchOperand_Success;
2139}
2140
Oliver Stannarda34e4702015-12-01 10:48:51 +00002141/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002142OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002143AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2144 MCAsmParser &Parser = getParser();
2145 SMLoc S = getLoc();
2146 const AsmToken &Tok = Parser.getTok();
2147 if (Tok.isNot(AsmToken::Identifier)) {
2148 TokError("invalid operand for instruction");
2149 return MatchOperand_ParseFail;
2150 }
2151
Tim Northovere6ae6762016-07-05 21:23:04 +00002152 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2153 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002154 TokError("invalid operand for instruction");
2155 return MatchOperand_ParseFail;
2156 }
2157
2158 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002159 Operands.push_back(AArch64Operand::CreatePSBHint(
2160 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002161 return MatchOperand_Success;
2162}
2163
Tim Northover3b0846e2014-05-24 12:50:23 +00002164/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2165/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002166OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002167AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002168 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002169 SMLoc S = getLoc();
2170 const MCExpr *Expr;
2171
2172 if (Parser.getTok().is(AsmToken::Hash)) {
2173 Parser.Lex(); // Eat hash token.
2174 }
2175
2176 if (parseSymbolicImmVal(Expr))
2177 return MatchOperand_ParseFail;
2178
2179 AArch64MCExpr::VariantKind ELFRefKind;
2180 MCSymbolRefExpr::VariantKind DarwinRefKind;
2181 int64_t Addend;
2182 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2183 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2184 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2185 // No modifier was specified at all; this is the syntax for an ELF basic
2186 // ADRP relocation (unfortunately).
2187 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002188 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002189 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2190 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2191 Addend != 0) {
2192 Error(S, "gotpage label reference not allowed an addend");
2193 return MatchOperand_ParseFail;
2194 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2195 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2196 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2197 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2198 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2199 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2200 // The operand must be an @page or @gotpage qualified symbolref.
2201 Error(S, "page or gotpage label reference expected");
2202 return MatchOperand_ParseFail;
2203 }
2204 }
2205
2206 // We have either a label reference possibly with addend or an immediate. The
2207 // addend is a raw value here. The linker will adjust it to only reference the
2208 // page.
2209 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2210 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2211
2212 return MatchOperand_Success;
2213}
2214
2215/// tryParseAdrLabel - Parse and validate a source label for the ADR
2216/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002217OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002218AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2219 SMLoc S = getLoc();
2220 const MCExpr *Expr;
2221
Nirav Davee833c6c2016-11-08 18:31:04 +00002222 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002223 if (getParser().parseExpression(Expr))
2224 return MatchOperand_ParseFail;
2225
2226 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2227 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2228
2229 return MatchOperand_Success;
2230}
2231
2232/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002233OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002234AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002235 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002236 SMLoc S = getLoc();
2237
Nirav Davee833c6c2016-11-08 18:31:04 +00002238 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002239
2240 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002241 bool isNegative = parseOptionalToken(AsmToken::Minus);
2242
Tim Northover3b0846e2014-05-24 12:50:23 +00002243 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002244 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002245 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002246 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002247 Val = Tok.getIntVal();
2248 if (Val > 255 || Val < 0) {
2249 TokError("encoded floating point value out of range");
2250 return MatchOperand_ParseFail;
2251 }
2252 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002253 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002254 if (isNegative)
2255 RealVal.changeSign();
2256
Tim Northover3b0846e2014-05-24 12:50:23 +00002257 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002258 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002259
John Brawn5ca5daa2017-04-20 10:13:54 +00002260 // Check for out of range values. As an exception we let Zero through,
2261 // but as tokens instead of an FPImm so that it can be matched by the
2262 // appropriate alias if one exists.
2263 if (RealVal.isPosZero()) {
2264 Parser.Lex(); // Eat the token.
2265 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2266 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2267 return MatchOperand_Success;
2268 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002269 TokError("expected compatible register or floating-point constant");
2270 return MatchOperand_ParseFail;
2271 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002272 }
2273 Parser.Lex(); // Eat the token.
2274 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2275 return MatchOperand_Success;
2276 }
2277
2278 if (!Hash)
2279 return MatchOperand_NoMatch;
2280
2281 TokError("invalid floating point immediate");
2282 return MatchOperand_ParseFail;
2283}
2284
2285/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002286OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002287AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002288 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002289 SMLoc S = getLoc();
2290
2291 if (Parser.getTok().is(AsmToken::Hash))
2292 Parser.Lex(); // Eat '#'
2293 else if (Parser.getTok().isNot(AsmToken::Integer))
2294 // Operand should start from # or should be integer, emit error otherwise.
2295 return MatchOperand_NoMatch;
2296
2297 const MCExpr *Imm;
2298 if (parseSymbolicImmVal(Imm))
2299 return MatchOperand_ParseFail;
2300 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2301 uint64_t ShiftAmount = 0;
2302 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2303 if (MCE) {
2304 int64_t Val = MCE->getValue();
2305 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002306 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002307 ShiftAmount = 12;
2308 }
2309 }
2310 SMLoc E = Parser.getTok().getLoc();
2311 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2312 getContext()));
2313 return MatchOperand_Success;
2314 }
2315
2316 // Eat ','
2317 Parser.Lex();
2318
2319 // The optional operand must be "lsl #N" where N is non-negative.
2320 if (!Parser.getTok().is(AsmToken::Identifier) ||
2321 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2322 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2323 return MatchOperand_ParseFail;
2324 }
2325
2326 // Eat 'lsl'
2327 Parser.Lex();
2328
Nirav Davee833c6c2016-11-08 18:31:04 +00002329 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002330
2331 if (Parser.getTok().isNot(AsmToken::Integer)) {
2332 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2333 return MatchOperand_ParseFail;
2334 }
2335
2336 int64_t ShiftAmount = Parser.getTok().getIntVal();
2337
2338 if (ShiftAmount < 0) {
2339 Error(Parser.getTok().getLoc(), "positive shift amount required");
2340 return MatchOperand_ParseFail;
2341 }
2342 Parser.Lex(); // Eat the number
2343
2344 SMLoc E = Parser.getTok().getLoc();
2345 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2346 S, E, getContext()));
2347 return MatchOperand_Success;
2348}
2349
2350/// parseCondCodeString - Parse a Condition Code string.
2351AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2352 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2353 .Case("eq", AArch64CC::EQ)
2354 .Case("ne", AArch64CC::NE)
2355 .Case("cs", AArch64CC::HS)
2356 .Case("hs", AArch64CC::HS)
2357 .Case("cc", AArch64CC::LO)
2358 .Case("lo", AArch64CC::LO)
2359 .Case("mi", AArch64CC::MI)
2360 .Case("pl", AArch64CC::PL)
2361 .Case("vs", AArch64CC::VS)
2362 .Case("vc", AArch64CC::VC)
2363 .Case("hi", AArch64CC::HI)
2364 .Case("ls", AArch64CC::LS)
2365 .Case("ge", AArch64CC::GE)
2366 .Case("lt", AArch64CC::LT)
2367 .Case("gt", AArch64CC::GT)
2368 .Case("le", AArch64CC::LE)
2369 .Case("al", AArch64CC::AL)
2370 .Case("nv", AArch64CC::NV)
2371 .Default(AArch64CC::Invalid);
2372 return CC;
2373}
2374
2375/// parseCondCode - Parse a Condition Code operand.
2376bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2377 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002378 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002379 SMLoc S = getLoc();
2380 const AsmToken &Tok = Parser.getTok();
2381 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2382
2383 StringRef Cond = Tok.getString();
2384 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2385 if (CC == AArch64CC::Invalid)
2386 return TokError("invalid condition code");
2387 Parser.Lex(); // Eat identifier token.
2388
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002389 if (invertCondCode) {
2390 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2391 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002392 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002393 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002394
2395 Operands.push_back(
2396 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2397 return false;
2398}
2399
2400/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2401/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002402OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002403AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002404 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002405 const AsmToken &Tok = Parser.getTok();
2406 std::string LowerID = Tok.getString().lower();
2407 AArch64_AM::ShiftExtendType ShOp =
2408 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2409 .Case("lsl", AArch64_AM::LSL)
2410 .Case("lsr", AArch64_AM::LSR)
2411 .Case("asr", AArch64_AM::ASR)
2412 .Case("ror", AArch64_AM::ROR)
2413 .Case("msl", AArch64_AM::MSL)
2414 .Case("uxtb", AArch64_AM::UXTB)
2415 .Case("uxth", AArch64_AM::UXTH)
2416 .Case("uxtw", AArch64_AM::UXTW)
2417 .Case("uxtx", AArch64_AM::UXTX)
2418 .Case("sxtb", AArch64_AM::SXTB)
2419 .Case("sxth", AArch64_AM::SXTH)
2420 .Case("sxtw", AArch64_AM::SXTW)
2421 .Case("sxtx", AArch64_AM::SXTX)
2422 .Default(AArch64_AM::InvalidShiftExtend);
2423
2424 if (ShOp == AArch64_AM::InvalidShiftExtend)
2425 return MatchOperand_NoMatch;
2426
2427 SMLoc S = Tok.getLoc();
2428 Parser.Lex();
2429
Nirav Davee833c6c2016-11-08 18:31:04 +00002430 bool Hash = parseOptionalToken(AsmToken::Hash);
2431
Tim Northover3b0846e2014-05-24 12:50:23 +00002432 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2433 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2434 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2435 ShOp == AArch64_AM::MSL) {
2436 // We expect a number here.
2437 TokError("expected #imm after shift specifier");
2438 return MatchOperand_ParseFail;
2439 }
2440
Chad Rosier2ff37b82016-12-27 16:58:09 +00002441 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002442 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2443 Operands.push_back(
2444 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2445 return MatchOperand_Success;
2446 }
2447
Chad Rosier2ff37b82016-12-27 16:58:09 +00002448 // Make sure we do actually have a number, identifier or a parenthesized
2449 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002450 SMLoc E = Parser.getTok().getLoc();
2451 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002452 !Parser.getTok().is(AsmToken::LParen) &&
2453 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002454 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002455 return MatchOperand_ParseFail;
2456 }
2457
2458 const MCExpr *ImmVal;
2459 if (getParser().parseExpression(ImmVal))
2460 return MatchOperand_ParseFail;
2461
2462 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2463 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002464 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002465 return MatchOperand_ParseFail;
2466 }
2467
Jim Grosbach57fd2622014-09-23 22:16:02 +00002468 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002469 Operands.push_back(AArch64Operand::CreateShiftExtend(
2470 ShOp, MCE->getValue(), true, S, E, getContext()));
2471 return MatchOperand_Success;
2472}
2473
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002474static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2475 if (FBS[AArch64::HasV8_1aOps])
2476 Str += "ARMv8.1a";
2477 else if (FBS[AArch64::HasV8_2aOps])
2478 Str += "ARMv8.2a";
2479 else
2480 Str += "(unknown)";
2481}
2482
2483void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2484 SMLoc S) {
2485 const uint16_t Op2 = Encoding & 7;
2486 const uint16_t Cm = (Encoding & 0x78) >> 3;
2487 const uint16_t Cn = (Encoding & 0x780) >> 7;
2488 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2489
2490 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2491
2492 Operands.push_back(
2493 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2494 Operands.push_back(
2495 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2496 Operands.push_back(
2497 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2498 Expr = MCConstantExpr::create(Op2, getContext());
2499 Operands.push_back(
2500 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2501}
2502
Tim Northover3b0846e2014-05-24 12:50:23 +00002503/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2504/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2505bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2506 OperandVector &Operands) {
2507 if (Name.find('.') != StringRef::npos)
2508 return TokError("invalid operand");
2509
2510 Mnemonic = Name;
2511 Operands.push_back(
2512 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2513
Rafael Espindola961d4692014-11-11 05:18:41 +00002514 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002515 const AsmToken &Tok = Parser.getTok();
2516 StringRef Op = Tok.getString();
2517 SMLoc S = Tok.getLoc();
2518
Tim Northover3b0846e2014-05-24 12:50:23 +00002519 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002520 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2521 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002522 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002523 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2524 std::string Str("IC " + std::string(IC->Name) + " requires ");
2525 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2526 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002527 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002528 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002529 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002530 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2531 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002532 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002533 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2534 std::string Str("DC " + std::string(DC->Name) + " requires ");
2535 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2536 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002537 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002538 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002539 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002540 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2541 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002542 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002543 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2544 std::string Str("AT " + std::string(AT->Name) + " requires ");
2545 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2546 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002547 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002548 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002549 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002550 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2551 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002552 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002553 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2554 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2555 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2556 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002557 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002558 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002559 }
2560
Tim Northover3b0846e2014-05-24 12:50:23 +00002561 Parser.Lex(); // Eat operand.
2562
2563 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2564 bool HasRegister = false;
2565
2566 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002567 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002568 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2569 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002570 HasRegister = true;
2571 }
2572
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002573 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002574 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002575 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002576 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002577
Nirav Davee833c6c2016-11-08 18:31:04 +00002578 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2579 return true;
2580
Tim Northover3b0846e2014-05-24 12:50:23 +00002581 return false;
2582}
2583
Alex Bradbury58eba092016-11-01 16:32:05 +00002584OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002585AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002586 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002587 const AsmToken &Tok = Parser.getTok();
2588
2589 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002590 if (parseOptionalToken(AsmToken::Hash) ||
2591 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002592 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002593 const MCExpr *ImmVal;
2594 SMLoc ExprLoc = getLoc();
2595 if (getParser().parseExpression(ImmVal))
2596 return MatchOperand_ParseFail;
2597 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2598 if (!MCE) {
2599 Error(ExprLoc, "immediate value expected for barrier operand");
2600 return MatchOperand_ParseFail;
2601 }
2602 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2603 Error(ExprLoc, "barrier operand out of range");
2604 return MatchOperand_ParseFail;
2605 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002606 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2607 Operands.push_back(AArch64Operand::CreateBarrier(
2608 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002609 return MatchOperand_Success;
2610 }
2611
2612 if (Tok.isNot(AsmToken::Identifier)) {
2613 TokError("invalid operand for instruction");
2614 return MatchOperand_ParseFail;
2615 }
2616
Tim Northover3b0846e2014-05-24 12:50:23 +00002617 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002618 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2619 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002620 TokError("'sy' or #imm operand expected");
2621 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002622 } else if (!DB) {
2623 TokError("invalid barrier option name");
2624 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002625 }
2626
Tim Northovere6ae6762016-07-05 21:23:04 +00002627 Operands.push_back(AArch64Operand::CreateBarrier(
2628 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002629 Parser.Lex(); // Consume the option
2630
2631 return MatchOperand_Success;
2632}
2633
Alex Bradbury58eba092016-11-01 16:32:05 +00002634OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002635AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002636 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002637 const AsmToken &Tok = Parser.getTok();
2638
2639 if (Tok.isNot(AsmToken::Identifier))
2640 return MatchOperand_NoMatch;
2641
Tim Northovere6ae6762016-07-05 21:23:04 +00002642 int MRSReg, MSRReg;
2643 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2644 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2645 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2646 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2647 } else
2648 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002649
Tim Northovere6ae6762016-07-05 21:23:04 +00002650 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2651 unsigned PStateImm = -1;
2652 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2653 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002654
Tim Northovere6ae6762016-07-05 21:23:04 +00002655 Operands.push_back(
2656 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2657 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002658 Parser.Lex(); // Eat identifier
2659
2660 return MatchOperand_Success;
2661}
2662
Florian Hahnc4422242017-11-07 13:07:50 +00002663/// tryParseNeonVectorRegister - Parse a vector register operand.
2664bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002665 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002666 if (Parser.getTok().isNot(AsmToken::Identifier))
2667 return true;
2668
2669 SMLoc S = getLoc();
2670 // Check for a vector register specifier first.
2671 StringRef Kind;
2672 int64_t Reg = tryMatchVectorRegister(Kind, false);
2673 if (Reg == -1)
2674 return true;
2675 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00002676 AArch64Operand::CreateReg(Reg, RegKind::NeonVector, S, getLoc(),
2677 getContext()));
2678
Tim Northover3b0846e2014-05-24 12:50:23 +00002679 // If there was an explicit qualifier, that goes on as a literal text
2680 // operand.
2681 if (!Kind.empty())
2682 Operands.push_back(
2683 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2684
2685 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002686 SMLoc SIdx = getLoc();
2687 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002688 const MCExpr *ImmVal;
2689 if (getParser().parseExpression(ImmVal))
2690 return false;
2691 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2692 if (!MCE) {
2693 TokError("immediate value expected for vector index");
2694 return false;
2695 }
2696
2697 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002698
Nirav Davee833c6c2016-11-08 18:31:04 +00002699 if (parseToken(AsmToken::RBrac, "']' expected"))
2700 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002701
2702 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2703 E, getContext()));
2704 }
2705
2706 return false;
2707}
2708
Florian Hahn91f11e52017-11-07 16:45:48 +00002709// tryParseSVEDataVectorRegister - Try to parse a SVE vector register name with
2710// optional kind specifier. If it is a register specifier, eat the token
2711// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002712OperandMatchResultTy
2713AArch64AsmParser::tryParseSVERegister(int &Reg, StringRef &Kind,
2714 RegKind MatchKind) {
2715 MCAsmParser &Parser = getParser();
2716 const AsmToken &Tok = Parser.getTok();
2717
Florian Hahn91f11e52017-11-07 16:45:48 +00002718 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002719 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002720
2721 StringRef Name = Tok.getString();
2722 // If there is a kind specifier, it's separated from the register name by
2723 // a '.'.
2724 size_t Start = 0, Next = Name.find('.');
2725 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002726 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002727
2728 if (RegNum) {
2729 if (Next != StringRef::npos) {
2730 Kind = Name.slice(Next, StringRef::npos);
2731 if (!isValidSVEKind(Kind)) {
2732 TokError("invalid sve vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002733 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002734 }
2735 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002736 Parser.Lex(); // Eat the register token.
2737
2738 Reg = RegNum;
2739 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002740 }
2741
Sander de Smalen8e607342017-11-15 15:44:43 +00002742 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002743}
2744
Tim Northover3b0846e2014-05-24 12:50:23 +00002745/// parseRegister - Parse a non-vector register operand.
2746bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2747 SMLoc S = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00002748 // Try for a vector (neon) register.
2749 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002750 return false;
2751
2752 // Try for a scalar register.
2753 int64_t Reg = tryParseRegister();
2754 if (Reg == -1)
2755 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002756 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2757 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002758
Tim Northover3b0846e2014-05-24 12:50:23 +00002759 return false;
2760}
2761
2762bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002763 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002764 bool HasELFModifier = false;
2765 AArch64MCExpr::VariantKind RefKind;
2766
Nirav Davee833c6c2016-11-08 18:31:04 +00002767 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002768 HasELFModifier = true;
2769
Nirav Davee833c6c2016-11-08 18:31:04 +00002770 if (Parser.getTok().isNot(AsmToken::Identifier))
2771 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002772
2773 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2774 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2775 .Case("lo12", AArch64MCExpr::VK_LO12)
2776 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2777 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2778 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2779 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2780 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2781 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2782 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2783 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2784 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2785 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2786 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2787 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2788 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2789 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2790 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2791 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2792 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2793 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2794 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2795 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2796 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2797 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2798 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2799 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2800 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2801 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2802 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2803 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2804 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2805 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2806 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2807 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2808 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2809 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2810 .Default(AArch64MCExpr::VK_INVALID);
2811
Nirav Davee833c6c2016-11-08 18:31:04 +00002812 if (RefKind == AArch64MCExpr::VK_INVALID)
2813 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002814
2815 Parser.Lex(); // Eat identifier
2816
Nirav Davee833c6c2016-11-08 18:31:04 +00002817 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002818 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002819 }
2820
2821 if (getParser().parseExpression(ImmVal))
2822 return true;
2823
2824 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002825 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002826
2827 return false;
2828}
2829
2830/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2831bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002832 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002833 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2834 SMLoc S = getLoc();
2835 Parser.Lex(); // Eat left bracket token.
2836 StringRef Kind;
2837 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2838 if (FirstReg == -1)
2839 return true;
2840 int64_t PrevReg = FirstReg;
2841 unsigned Count = 1;
2842
Nirav Davee833c6c2016-11-08 18:31:04 +00002843 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002844 SMLoc Loc = getLoc();
2845 StringRef NextKind;
2846 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2847 if (Reg == -1)
2848 return true;
2849 // Any Kind suffices must match on all regs in the list.
2850 if (Kind != NextKind)
2851 return Error(Loc, "mismatched register size suffix");
2852
2853 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2854
2855 if (Space == 0 || Space > 3) {
2856 return Error(Loc, "invalid number of vectors");
2857 }
2858
2859 Count += Space;
2860 }
2861 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002862 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002863 SMLoc Loc = getLoc();
2864 StringRef NextKind;
2865 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2866 if (Reg == -1)
2867 return true;
2868 // Any Kind suffices must match on all regs in the list.
2869 if (Kind != NextKind)
2870 return Error(Loc, "mismatched register size suffix");
2871
2872 // Registers must be incremental (with wraparound at 31)
2873 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2874 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2875 return Error(Loc, "registers must be sequential");
2876
2877 PrevReg = Reg;
2878 ++Count;
2879 }
2880 }
2881
Nirav Davee833c6c2016-11-08 18:31:04 +00002882 if (parseToken(AsmToken::RCurly, "'}' expected"))
2883 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002884
2885 if (Count > 4)
2886 return Error(S, "invalid number of vectors");
2887
2888 unsigned NumElements = 0;
2889 char ElementKind = 0;
2890 if (!Kind.empty())
2891 parseValidVectorKind(Kind, NumElements, ElementKind);
2892
2893 Operands.push_back(AArch64Operand::CreateVectorList(
2894 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
2895
2896 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002897 SMLoc SIdx = getLoc();
2898 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002899 const MCExpr *ImmVal;
2900 if (getParser().parseExpression(ImmVal))
2901 return false;
2902 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2903 if (!MCE) {
2904 TokError("immediate value expected for vector index");
2905 return false;
2906 }
2907
2908 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002909 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002910 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002911
2912 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2913 E, getContext()));
2914 }
2915 return false;
2916}
2917
Alex Bradbury58eba092016-11-01 16:32:05 +00002918OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002919AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002920 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002921 const AsmToken &Tok = Parser.getTok();
2922 if (!Tok.is(AsmToken::Identifier))
2923 return MatchOperand_NoMatch;
2924
Florian Hahnc4422242017-11-07 13:07:50 +00002925 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00002926
2927 MCContext &Ctx = getContext();
2928 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
2929 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
2930 return MatchOperand_NoMatch;
2931
2932 SMLoc S = getLoc();
2933 Parser.Lex(); // Eat register
2934
Nirav Davee833c6c2016-11-08 18:31:04 +00002935 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002936 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00002937 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00002938 return MatchOperand_Success;
2939 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002940
Nirav Davee833c6c2016-11-08 18:31:04 +00002941 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002942
2943 if (Parser.getTok().isNot(AsmToken::Integer)) {
2944 Error(getLoc(), "index must be absent or #0");
2945 return MatchOperand_ParseFail;
2946 }
2947
2948 const MCExpr *ImmVal;
2949 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
2950 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
2951 Error(getLoc(), "index must be absent or #0");
2952 return MatchOperand_ParseFail;
2953 }
2954
2955 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00002956 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00002957 return MatchOperand_Success;
2958}
2959
2960/// parseOperand - Parse a arm instruction operand. For now this parses the
2961/// operand regardless of the mnemonic.
2962bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
2963 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002964 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002965 // Check if the current operand has a custom associated parser, if so, try to
2966 // custom parse the operand, or fallback to the general approach.
2967 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2968 if (ResTy == MatchOperand_Success)
2969 return false;
2970 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2971 // there was a match, but an error occurred, in which case, just return that
2972 // the operand parsing failed.
2973 if (ResTy == MatchOperand_ParseFail)
2974 return true;
2975
2976 // Nothing custom, so do general case parsing.
2977 SMLoc S, E;
2978 switch (getLexer().getKind()) {
2979 default: {
2980 SMLoc S = getLoc();
2981 const MCExpr *Expr;
2982 if (parseSymbolicImmVal(Expr))
2983 return Error(S, "invalid operand");
2984
2985 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2986 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2987 return false;
2988 }
2989 case AsmToken::LBrac: {
2990 SMLoc Loc = Parser.getTok().getLoc();
2991 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
2992 getContext()));
2993 Parser.Lex(); // Eat '['
2994
2995 // There's no comma after a '[', so we can parse the next operand
2996 // immediately.
2997 return parseOperand(Operands, false, false);
2998 }
2999 case AsmToken::LCurly:
3000 return parseVectorList(Operands);
3001 case AsmToken::Identifier: {
3002 // If we're expecting a Condition Code operand, then just parse that.
3003 if (isCondCode)
3004 return parseCondCode(Operands, invertCondCode);
3005
3006 // If it's a register name, parse it.
3007 if (!parseRegister(Operands))
3008 return false;
3009
3010 // This could be an optional "shift" or "extend" operand.
3011 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3012 // We can only continue if no tokens were eaten.
3013 if (GotShift != MatchOperand_NoMatch)
3014 return GotShift;
3015
3016 // This was not a register so parse other operands that start with an
3017 // identifier (like labels) as expressions and create them as immediates.
3018 const MCExpr *IdVal;
3019 S = getLoc();
3020 if (getParser().parseExpression(IdVal))
3021 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003022 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3023 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3024 return false;
3025 }
3026 case AsmToken::Integer:
3027 case AsmToken::Real:
3028 case AsmToken::Hash: {
3029 // #42 -> immediate.
3030 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003031
3032 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003033
3034 // Parse a negative sign
3035 bool isNegative = false;
3036 if (Parser.getTok().is(AsmToken::Minus)) {
3037 isNegative = true;
3038 // We need to consume this token only when we have a Real, otherwise
3039 // we let parseSymbolicImmVal take care of it
3040 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3041 Parser.Lex();
3042 }
3043
3044 // The only Real that should come through here is a literal #0.0 for
3045 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3046 // so convert the value.
3047 const AsmToken &Tok = Parser.getTok();
3048 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003049 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003050 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3051 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3052 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3053 Mnemonic != "fcmlt")
3054 return TokError("unexpected floating point literal");
3055 else if (IntVal != 0 || isNegative)
3056 return TokError("expected floating-point constant #0.0");
3057 Parser.Lex(); // Eat the token.
3058
3059 Operands.push_back(
3060 AArch64Operand::CreateToken("#0", false, S, getContext()));
3061 Operands.push_back(
3062 AArch64Operand::CreateToken(".0", false, S, getContext()));
3063 return false;
3064 }
3065
3066 const MCExpr *ImmVal;
3067 if (parseSymbolicImmVal(ImmVal))
3068 return true;
3069
3070 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3071 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3072 return false;
3073 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003074 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003075 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003076 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003077 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003078 Parser.Lex(); // Eat '='
3079 const MCExpr *SubExprVal;
3080 if (getParser().parseExpression(SubExprVal))
3081 return true;
3082
David Peixottoae5ba762014-07-18 16:05:14 +00003083 if (Operands.size() < 2 ||
3084 !static_cast<AArch64Operand &>(*Operands[1]).isReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003085 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003086
3087 bool IsXReg =
3088 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3089 Operands[1]->getReg());
3090
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003091 MCContext& Ctx = getContext();
3092 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3093 // 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 +00003094 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003095 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3096 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3097 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3098 ShiftAmt += 16;
3099 Imm >>= 16;
3100 }
3101 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3102 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3103 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003104 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003105 if (ShiftAmt)
3106 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3107 ShiftAmt, true, S, E, Ctx));
3108 return false;
3109 }
David Peixottoae5ba762014-07-18 16:05:14 +00003110 APInt Simm = APInt(64, Imm << ShiftAmt);
3111 // check if the immediate is an unsigned or signed 32-bit int for W regs
3112 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3113 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003114 }
3115 // 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 +00003116 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003117 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003118 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3119 return false;
3120 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003121 }
3122}
3123
3124/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3125/// operands.
3126bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3127 StringRef Name, SMLoc NameLoc,
3128 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003129 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003130 Name = StringSwitch<StringRef>(Name.lower())
3131 .Case("beq", "b.eq")
3132 .Case("bne", "b.ne")
3133 .Case("bhs", "b.hs")
3134 .Case("bcs", "b.cs")
3135 .Case("blo", "b.lo")
3136 .Case("bcc", "b.cc")
3137 .Case("bmi", "b.mi")
3138 .Case("bpl", "b.pl")
3139 .Case("bvs", "b.vs")
3140 .Case("bvc", "b.vc")
3141 .Case("bhi", "b.hi")
3142 .Case("bls", "b.ls")
3143 .Case("bge", "b.ge")
3144 .Case("blt", "b.lt")
3145 .Case("bgt", "b.gt")
3146 .Case("ble", "b.le")
3147 .Case("bal", "b.al")
3148 .Case("bnv", "b.nv")
3149 .Default(Name);
3150
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003151 // First check for the AArch64-specific .req directive.
3152 if (Parser.getTok().is(AsmToken::Identifier) &&
3153 Parser.getTok().getIdentifier() == ".req") {
3154 parseDirectiveReq(Name, NameLoc);
3155 // We always return 'error' for this, as we're done with this
3156 // statement and don't need to match the 'instruction."
3157 return true;
3158 }
3159
Tim Northover3b0846e2014-05-24 12:50:23 +00003160 // Create the leading tokens for the mnemonic, split by '.' characters.
3161 size_t Start = 0, Next = Name.find('.');
3162 StringRef Head = Name.slice(Start, Next);
3163
3164 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003165 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3166 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003167
3168 Operands.push_back(
3169 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3170 Mnemonic = Head;
3171
3172 // Handle condition codes for a branch mnemonic
3173 if (Head == "b" && Next != StringRef::npos) {
3174 Start = Next;
3175 Next = Name.find('.', Start + 1);
3176 Head = Name.slice(Start + 1, Next);
3177
3178 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3179 (Head.data() - Name.data()));
3180 AArch64CC::CondCode CC = parseCondCodeString(Head);
3181 if (CC == AArch64CC::Invalid)
3182 return Error(SuffixLoc, "invalid condition code");
3183 Operands.push_back(
3184 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3185 Operands.push_back(
3186 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3187 }
3188
3189 // Add the remaining tokens in the mnemonic.
3190 while (Next != StringRef::npos) {
3191 Start = Next;
3192 Next = Name.find('.', Start + 1);
3193 Head = Name.slice(Start, Next);
3194 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3195 (Head.data() - Name.data()) + 1);
3196 Operands.push_back(
3197 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3198 }
3199
3200 // Conditional compare instructions have a Condition Code operand, which needs
3201 // to be parsed and an immediate operand created.
3202 bool condCodeFourthOperand =
3203 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3204 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3205 Head == "csinc" || Head == "csinv" || Head == "csneg");
3206
3207 // These instructions are aliases to some of the conditional select
3208 // instructions. However, the condition code is inverted in the aliased
3209 // instruction.
3210 //
3211 // FIXME: Is this the correct way to handle these? Or should the parser
3212 // generate the aliased instructions directly?
3213 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3214 bool condCodeThirdOperand =
3215 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3216
3217 // Read the remaining operands.
3218 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3219 // Read the first operand.
3220 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003221 return true;
3222 }
3223
3224 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003225 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003226 // Parse and remember the operand.
3227 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3228 (N == 3 && condCodeThirdOperand) ||
3229 (N == 2 && condCodeSecondOperand),
3230 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003231 return true;
3232 }
3233
3234 // After successfully parsing some operands there are two special cases to
3235 // consider (i.e. notional operands not separated by commas). Both are due
3236 // to memory specifiers:
3237 // + An RBrac will end an address for load/store/prefetch
3238 // + An '!' will indicate a pre-indexed operation.
3239 //
3240 // It's someone else's responsibility to make sure these tokens are sane
3241 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003242
Nirav Davee833c6c2016-11-08 18:31:04 +00003243 SMLoc RLoc = Parser.getTok().getLoc();
3244 if (parseOptionalToken(AsmToken::RBrac))
3245 Operands.push_back(
3246 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3247 SMLoc ELoc = Parser.getTok().getLoc();
3248 if (parseOptionalToken(AsmToken::Exclaim))
3249 Operands.push_back(
3250 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003251
3252 ++N;
3253 }
3254 }
3255
Nirav Davee833c6c2016-11-08 18:31:04 +00003256 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3257 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003258
Tim Northover3b0846e2014-05-24 12:50:23 +00003259 return false;
3260}
3261
3262// FIXME: This entire function is a giant hack to provide us with decent
3263// operand range validation/diagnostics until TableGen/MC can be extended
3264// to support autogeneration of this kind of validation.
3265bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3266 SmallVectorImpl<SMLoc> &Loc) {
3267 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3268 // Check for indexed addressing modes w/ the base register being the
3269 // same as a destination/source register or pair load where
3270 // the Rt == Rt2. All of those are undefined behaviour.
3271 switch (Inst.getOpcode()) {
3272 case AArch64::LDPSWpre:
3273 case AArch64::LDPWpost:
3274 case AArch64::LDPWpre:
3275 case AArch64::LDPXpost:
3276 case AArch64::LDPXpre: {
3277 unsigned Rt = Inst.getOperand(1).getReg();
3278 unsigned Rt2 = Inst.getOperand(2).getReg();
3279 unsigned Rn = Inst.getOperand(3).getReg();
3280 if (RI->isSubRegisterEq(Rn, Rt))
3281 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3282 "is also a destination");
3283 if (RI->isSubRegisterEq(Rn, Rt2))
3284 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3285 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003286 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003287 }
3288 case AArch64::LDPDi:
3289 case AArch64::LDPQi:
3290 case AArch64::LDPSi:
3291 case AArch64::LDPSWi:
3292 case AArch64::LDPWi:
3293 case AArch64::LDPXi: {
3294 unsigned Rt = Inst.getOperand(0).getReg();
3295 unsigned Rt2 = Inst.getOperand(1).getReg();
3296 if (Rt == Rt2)
3297 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3298 break;
3299 }
3300 case AArch64::LDPDpost:
3301 case AArch64::LDPDpre:
3302 case AArch64::LDPQpost:
3303 case AArch64::LDPQpre:
3304 case AArch64::LDPSpost:
3305 case AArch64::LDPSpre:
3306 case AArch64::LDPSWpost: {
3307 unsigned Rt = Inst.getOperand(1).getReg();
3308 unsigned Rt2 = Inst.getOperand(2).getReg();
3309 if (Rt == Rt2)
3310 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3311 break;
3312 }
3313 case AArch64::STPDpost:
3314 case AArch64::STPDpre:
3315 case AArch64::STPQpost:
3316 case AArch64::STPQpre:
3317 case AArch64::STPSpost:
3318 case AArch64::STPSpre:
3319 case AArch64::STPWpost:
3320 case AArch64::STPWpre:
3321 case AArch64::STPXpost:
3322 case AArch64::STPXpre: {
3323 unsigned Rt = Inst.getOperand(1).getReg();
3324 unsigned Rt2 = Inst.getOperand(2).getReg();
3325 unsigned Rn = Inst.getOperand(3).getReg();
3326 if (RI->isSubRegisterEq(Rn, Rt))
3327 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3328 "is also a source");
3329 if (RI->isSubRegisterEq(Rn, Rt2))
3330 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3331 "is also a source");
3332 break;
3333 }
3334 case AArch64::LDRBBpre:
3335 case AArch64::LDRBpre:
3336 case AArch64::LDRHHpre:
3337 case AArch64::LDRHpre:
3338 case AArch64::LDRSBWpre:
3339 case AArch64::LDRSBXpre:
3340 case AArch64::LDRSHWpre:
3341 case AArch64::LDRSHXpre:
3342 case AArch64::LDRSWpre:
3343 case AArch64::LDRWpre:
3344 case AArch64::LDRXpre:
3345 case AArch64::LDRBBpost:
3346 case AArch64::LDRBpost:
3347 case AArch64::LDRHHpost:
3348 case AArch64::LDRHpost:
3349 case AArch64::LDRSBWpost:
3350 case AArch64::LDRSBXpost:
3351 case AArch64::LDRSHWpost:
3352 case AArch64::LDRSHXpost:
3353 case AArch64::LDRSWpost:
3354 case AArch64::LDRWpost:
3355 case AArch64::LDRXpost: {
3356 unsigned Rt = Inst.getOperand(1).getReg();
3357 unsigned Rn = Inst.getOperand(2).getReg();
3358 if (RI->isSubRegisterEq(Rn, Rt))
3359 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3360 "is also a source");
3361 break;
3362 }
3363 case AArch64::STRBBpost:
3364 case AArch64::STRBpost:
3365 case AArch64::STRHHpost:
3366 case AArch64::STRHpost:
3367 case AArch64::STRWpost:
3368 case AArch64::STRXpost:
3369 case AArch64::STRBBpre:
3370 case AArch64::STRBpre:
3371 case AArch64::STRHHpre:
3372 case AArch64::STRHpre:
3373 case AArch64::STRWpre:
3374 case AArch64::STRXpre: {
3375 unsigned Rt = Inst.getOperand(1).getReg();
3376 unsigned Rn = Inst.getOperand(2).getReg();
3377 if (RI->isSubRegisterEq(Rn, Rt))
3378 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3379 "is also a source");
3380 break;
3381 }
3382 }
3383
3384 // Now check immediate ranges. Separate from the above as there is overlap
3385 // in the instructions being checked and this keeps the nested conditionals
3386 // to a minimum.
3387 switch (Inst.getOpcode()) {
3388 case AArch64::ADDSWri:
3389 case AArch64::ADDSXri:
3390 case AArch64::ADDWri:
3391 case AArch64::ADDXri:
3392 case AArch64::SUBSWri:
3393 case AArch64::SUBSXri:
3394 case AArch64::SUBWri:
3395 case AArch64::SUBXri: {
3396 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3397 // some slight duplication here.
3398 if (Inst.getOperand(2).isExpr()) {
3399 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3400 AArch64MCExpr::VariantKind ELFRefKind;
3401 MCSymbolRefExpr::VariantKind DarwinRefKind;
3402 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003403 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3404
3405 // Only allow these with ADDXri.
3406 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3407 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3408 Inst.getOpcode() == AArch64::ADDXri)
3409 return false;
3410
3411 // Only allow these with ADDXri/ADDWri
3412 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3413 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3414 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3415 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3416 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3417 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3418 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3419 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3420 (Inst.getOpcode() == AArch64::ADDXri ||
3421 Inst.getOpcode() == AArch64::ADDWri))
3422 return false;
3423
3424 // Don't allow symbol refs in the immediate field otherwise
3425 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3426 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3427 // 'cmp w0, 'borked')
3428 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003429 }
Diana Picusc93518d2016-10-11 09:17:47 +00003430 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003431 }
3432 return false;
3433 }
3434 default:
3435 return false;
3436 }
3437}
3438
Craig Topper05515562017-10-26 06:46:41 +00003439static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3440 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003441
3442bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3443 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003444 switch (ErrCode) {
3445 case Match_MissingFeature:
3446 return Error(Loc,
3447 "instruction requires a CPU feature not currently enabled");
3448 case Match_InvalidOperand:
3449 return Error(Loc, "invalid operand for instruction");
3450 case Match_InvalidSuffix:
3451 return Error(Loc, "invalid type suffix for instruction");
3452 case Match_InvalidCondCode:
3453 return Error(Loc, "expected AArch64 condition code");
3454 case Match_AddSubRegExtendSmall:
3455 return Error(Loc,
3456 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3457 case Match_AddSubRegExtendLarge:
3458 return Error(Loc,
3459 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3460 case Match_AddSubSecondSource:
3461 return Error(Loc,
3462 "expected compatible register, symbol or integer in range [0, 4095]");
3463 case Match_LogicalSecondSource:
3464 return Error(Loc, "expected compatible register or logical immediate");
3465 case Match_InvalidMovImm32Shift:
3466 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3467 case Match_InvalidMovImm64Shift:
3468 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3469 case Match_AddSubRegShift32:
3470 return Error(Loc,
3471 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3472 case Match_AddSubRegShift64:
3473 return Error(Loc,
3474 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3475 case Match_InvalidFPImm:
3476 return Error(Loc,
3477 "expected compatible register or floating-point constant");
3478 case Match_InvalidMemoryIndexedSImm9:
3479 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003480 case Match_InvalidMemoryIndexedSImm10:
3481 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003482 case Match_InvalidMemoryIndexed4SImm7:
3483 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3484 case Match_InvalidMemoryIndexed8SImm7:
3485 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3486 case Match_InvalidMemoryIndexed16SImm7:
3487 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3488 case Match_InvalidMemoryWExtend8:
3489 return Error(Loc,
3490 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3491 case Match_InvalidMemoryWExtend16:
3492 return Error(Loc,
3493 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3494 case Match_InvalidMemoryWExtend32:
3495 return Error(Loc,
3496 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3497 case Match_InvalidMemoryWExtend64:
3498 return Error(Loc,
3499 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3500 case Match_InvalidMemoryWExtend128:
3501 return Error(Loc,
3502 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3503 case Match_InvalidMemoryXExtend8:
3504 return Error(Loc,
3505 "expected 'lsl' or 'sxtx' with optional shift of #0");
3506 case Match_InvalidMemoryXExtend16:
3507 return Error(Loc,
3508 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3509 case Match_InvalidMemoryXExtend32:
3510 return Error(Loc,
3511 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3512 case Match_InvalidMemoryXExtend64:
3513 return Error(Loc,
3514 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3515 case Match_InvalidMemoryXExtend128:
3516 return Error(Loc,
3517 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3518 case Match_InvalidMemoryIndexed1:
3519 return Error(Loc, "index must be an integer in range [0, 4095].");
3520 case Match_InvalidMemoryIndexed2:
3521 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3522 case Match_InvalidMemoryIndexed4:
3523 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3524 case Match_InvalidMemoryIndexed8:
3525 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3526 case Match_InvalidMemoryIndexed16:
3527 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003528 case Match_InvalidImm0_1:
3529 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003530 case Match_InvalidImm0_7:
3531 return Error(Loc, "immediate must be an integer in range [0, 7].");
3532 case Match_InvalidImm0_15:
3533 return Error(Loc, "immediate must be an integer in range [0, 15].");
3534 case Match_InvalidImm0_31:
3535 return Error(Loc, "immediate must be an integer in range [0, 31].");
3536 case Match_InvalidImm0_63:
3537 return Error(Loc, "immediate must be an integer in range [0, 63].");
3538 case Match_InvalidImm0_127:
3539 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003540 case Match_InvalidImm0_255:
3541 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003542 case Match_InvalidImm0_65535:
3543 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3544 case Match_InvalidImm1_8:
3545 return Error(Loc, "immediate must be an integer in range [1, 8].");
3546 case Match_InvalidImm1_16:
3547 return Error(Loc, "immediate must be an integer in range [1, 16].");
3548 case Match_InvalidImm1_32:
3549 return Error(Loc, "immediate must be an integer in range [1, 32].");
3550 case Match_InvalidImm1_64:
3551 return Error(Loc, "immediate must be an integer in range [1, 64].");
3552 case Match_InvalidIndex1:
3553 return Error(Loc, "expected lane specifier '[1]'");
3554 case Match_InvalidIndexB:
3555 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3556 case Match_InvalidIndexH:
3557 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3558 case Match_InvalidIndexS:
3559 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3560 case Match_InvalidIndexD:
3561 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3562 case Match_InvalidLabel:
3563 return Error(Loc, "expected label or encodable integer pc offset");
3564 case Match_MRS:
3565 return Error(Loc, "expected readable system register");
3566 case Match_MSR:
3567 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003568 case Match_InvalidComplexRotationEven:
3569 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3570 case Match_InvalidComplexRotationOdd:
3571 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003572 case Match_MnemonicFail: {
3573 std::string Suggestion = AArch64MnemonicSpellCheck(
3574 ((AArch64Operand &)*Operands[0]).getToken(),
3575 ComputeAvailableFeatures(STI->getFeatureBits()));
3576 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3577 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003578 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003579 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003580 }
3581}
3582
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003583static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003584
3585bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3586 OperandVector &Operands,
3587 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003588 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003589 bool MatchingInlineAsm) {
3590 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003591 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3592 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003593
David Blaikie960ea3f2014-06-08 16:18:35 +00003594 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003595 unsigned NumOperands = Operands.size();
3596
3597 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003598 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3599 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3600 if (Op2.isReg() && Op3.isImm()) {
3601 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003602 if (Op3CE) {
3603 uint64_t Op3Val = Op3CE->getValue();
3604 uint64_t NewOp3Val = 0;
3605 uint64_t NewOp4Val = 0;
3606 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003607 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003608 NewOp3Val = (32 - Op3Val) & 0x1f;
3609 NewOp4Val = 31 - Op3Val;
3610 } else {
3611 NewOp3Val = (64 - Op3Val) & 0x3f;
3612 NewOp4Val = 63 - Op3Val;
3613 }
3614
Jim Grosbach13760bd2015-05-30 01:25:56 +00003615 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3616 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003617
3618 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003619 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003620 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003621 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3622 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3623 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003624 }
3625 }
Tim Northover03b99f62015-04-30 18:28:58 +00003626 } else if (NumOperands == 4 && Tok == "bfc") {
3627 // FIXME: Horrible hack to handle BFC->BFM alias.
3628 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3629 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3630 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3631
3632 if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
3633 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3634 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3635
3636 if (LSBCE && WidthCE) {
3637 uint64_t LSB = LSBCE->getValue();
3638 uint64_t Width = WidthCE->getValue();
3639
3640 uint64_t RegWidth = 0;
3641 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3642 Op1.getReg()))
3643 RegWidth = 64;
3644 else
3645 RegWidth = 32;
3646
3647 if (LSB >= RegWidth)
3648 return Error(LSBOp.getStartLoc(),
3649 "expected integer in range [0, 31]");
3650 if (Width < 1 || Width > RegWidth)
3651 return Error(WidthOp.getStartLoc(),
3652 "expected integer in range [1, 32]");
3653
3654 uint64_t ImmR = 0;
3655 if (RegWidth == 32)
3656 ImmR = (32 - LSB) & 0x1f;
3657 else
3658 ImmR = (64 - LSB) & 0x3f;
3659
3660 uint64_t ImmS = Width - 1;
3661
3662 if (ImmR != 0 && ImmS >= ImmR)
3663 return Error(WidthOp.getStartLoc(),
3664 "requested insert overflows register");
3665
Jim Grosbach13760bd2015-05-30 01:25:56 +00003666 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3667 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003668 Operands[0] = AArch64Operand::CreateToken(
3669 "bfm", false, Op.getStartLoc(), getContext());
3670 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003671 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3672 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003673 Operands[3] = AArch64Operand::CreateImm(
3674 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3675 Operands.emplace_back(
3676 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3677 WidthOp.getEndLoc(), getContext()));
3678 }
3679 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003680 } else if (NumOperands == 5) {
3681 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3682 // UBFIZ -> UBFM aliases.
3683 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003684 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3685 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3686 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003687
David Blaikie960ea3f2014-06-08 16:18:35 +00003688 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3689 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3690 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003691
3692 if (Op3CE && Op4CE) {
3693 uint64_t Op3Val = Op3CE->getValue();
3694 uint64_t Op4Val = Op4CE->getValue();
3695
3696 uint64_t RegWidth = 0;
3697 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003698 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003699 RegWidth = 64;
3700 else
3701 RegWidth = 32;
3702
3703 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003704 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003705 "expected integer in range [0, 31]");
3706 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003707 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003708 "expected integer in range [1, 32]");
3709
3710 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003711 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003712 NewOp3Val = (32 - Op3Val) & 0x1f;
3713 else
3714 NewOp3Val = (64 - Op3Val) & 0x3f;
3715
3716 uint64_t NewOp4Val = Op4Val - 1;
3717
3718 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003719 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003720 "requested insert overflows register");
3721
3722 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003723 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003724 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003725 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003726 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003727 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003728 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003729 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003730 if (Tok == "bfi")
3731 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003732 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003733 else if (Tok == "sbfiz")
3734 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003735 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003736 else if (Tok == "ubfiz")
3737 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003738 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003739 else
3740 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003741 }
3742 }
3743
3744 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3745 // UBFX -> UBFM aliases.
3746 } else if (NumOperands == 5 &&
3747 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003748 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3749 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3750 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003751
David Blaikie960ea3f2014-06-08 16:18:35 +00003752 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3753 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3754 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003755
3756 if (Op3CE && Op4CE) {
3757 uint64_t Op3Val = Op3CE->getValue();
3758 uint64_t Op4Val = Op4CE->getValue();
3759
3760 uint64_t RegWidth = 0;
3761 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003762 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003763 RegWidth = 64;
3764 else
3765 RegWidth = 32;
3766
3767 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003768 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003769 "expected integer in range [0, 31]");
3770 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003771 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003772 "expected integer in range [1, 32]");
3773
3774 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3775
3776 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003777 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003778 "requested extract overflows register");
3779
3780 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003781 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003782 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003783 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003784 if (Tok == "bfxil")
3785 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003786 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003787 else if (Tok == "sbfx")
3788 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003789 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003790 else if (Tok == "ubfx")
3791 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003792 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003793 else
3794 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003795 }
3796 }
3797 }
3798 }
Tim Northover9097a072017-12-18 10:36:00 +00003799
3800 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
3801 // instruction for FP registers correctly in some rare circumstances. Convert
3802 // it to a safe instruction and warn (because silently changing someone's
3803 // assembly is rude).
3804 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
3805 NumOperands == 4 && Tok == "movi") {
3806 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3807 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3808 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3809 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
3810 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
3811 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
3812 if (Suffix.lower() == ".2d" &&
3813 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
3814 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
3815 " correctly on this CPU, converting to equivalent movi.16b");
3816 // Switch the suffix to .16b.
3817 unsigned Idx = Op1.isToken() ? 1 : 2;
3818 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
3819 getContext());
3820 }
3821 }
3822 }
3823
Tim Northover3b0846e2014-05-24 12:50:23 +00003824 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3825 // InstAlias can't quite handle this since the reg classes aren't
3826 // subclasses.
3827 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3828 // The source register can be Wn here, but the matcher expects a
3829 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003830 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3831 if (Op.isReg()) {
3832 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003833 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3834 Op.getStartLoc(), Op.getEndLoc(),
3835 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003836 }
3837 }
3838 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3839 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003840 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3841 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003842 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003843 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003844 // The source register can be Wn here, but the matcher expects a
3845 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003846 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3847 if (Op.isReg()) {
3848 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003849 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3850 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003851 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003852 }
3853 }
3854 }
3855 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3856 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003857 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3858 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003859 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003860 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003861 // The source register can be Wn here, but the matcher expects a
3862 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003863 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3864 if (Op.isReg()) {
3865 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003866 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3867 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003868 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003869 }
3870 }
3871 }
3872
Tim Northover3b0846e2014-05-24 12:50:23 +00003873 MCInst Inst;
3874 // First try to match against the secondary set of tables containing the
3875 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3876 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003877 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003878
3879 // If that fails, try against the alternate table containing long-form NEON:
3880 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003881 if (MatchResult != Match_Success) {
3882 // But first, save the short-form match result: we can use it in case the
3883 // long-form match also fails.
3884 auto ShortFormNEONErrorInfo = ErrorInfo;
3885 auto ShortFormNEONMatchResult = MatchResult;
3886
Tim Northover3b0846e2014-05-24 12:50:23 +00003887 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003888 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003889
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003890 // Now, both matches failed, and the long-form match failed on the mnemonic
3891 // suffix token operand. The short-form match failure is probably more
3892 // relevant: use it instead.
3893 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003894 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003895 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3896 MatchResult = ShortFormNEONMatchResult;
3897 ErrorInfo = ShortFormNEONErrorInfo;
3898 }
3899 }
3900
Tim Northover3b0846e2014-05-24 12:50:23 +00003901 switch (MatchResult) {
3902 case Match_Success: {
3903 // Perform range checking and other semantic validations
3904 SmallVector<SMLoc, 8> OperandLocs;
3905 NumOperands = Operands.size();
3906 for (unsigned i = 1; i < NumOperands; ++i)
3907 OperandLocs.push_back(Operands[i]->getStartLoc());
3908 if (validateInstruction(Inst, OperandLocs))
3909 return true;
3910
3911 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003912 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00003913 return false;
3914 }
3915 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003916 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003917 // Special case the error message for the very common case where only
3918 // a single subtarget feature is missing (neon, e.g.).
3919 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003920 uint64_t Mask = 1;
3921 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
3922 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003923 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003924 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00003925 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003926 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00003927 }
3928 return Error(IDLoc, Msg);
3929 }
3930 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003931 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003932 case Match_InvalidOperand: {
3933 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00003934
Tim Northover26bb14e2014-08-18 11:49:42 +00003935 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003936 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00003937 return Error(IDLoc, "too few operands for instruction",
3938 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003939
David Blaikie960ea3f2014-06-08 16:18:35 +00003940 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003941 if (ErrorLoc == SMLoc())
3942 ErrorLoc = IDLoc;
3943 }
3944 // If the match failed on a suffix token operand, tweak the diagnostic
3945 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00003946 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
3947 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00003948 MatchResult = Match_InvalidSuffix;
3949
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003950 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003951 }
3952 case Match_InvalidMemoryIndexed1:
3953 case Match_InvalidMemoryIndexed2:
3954 case Match_InvalidMemoryIndexed4:
3955 case Match_InvalidMemoryIndexed8:
3956 case Match_InvalidMemoryIndexed16:
3957 case Match_InvalidCondCode:
3958 case Match_AddSubRegExtendSmall:
3959 case Match_AddSubRegExtendLarge:
3960 case Match_AddSubSecondSource:
3961 case Match_LogicalSecondSource:
3962 case Match_AddSubRegShift32:
3963 case Match_AddSubRegShift64:
3964 case Match_InvalidMovImm32Shift:
3965 case Match_InvalidMovImm64Shift:
3966 case Match_InvalidFPImm:
3967 case Match_InvalidMemoryWExtend8:
3968 case Match_InvalidMemoryWExtend16:
3969 case Match_InvalidMemoryWExtend32:
3970 case Match_InvalidMemoryWExtend64:
3971 case Match_InvalidMemoryWExtend128:
3972 case Match_InvalidMemoryXExtend8:
3973 case Match_InvalidMemoryXExtend16:
3974 case Match_InvalidMemoryXExtend32:
3975 case Match_InvalidMemoryXExtend64:
3976 case Match_InvalidMemoryXExtend128:
3977 case Match_InvalidMemoryIndexed4SImm7:
3978 case Match_InvalidMemoryIndexed8SImm7:
3979 case Match_InvalidMemoryIndexed16SImm7:
3980 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00003981 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003982 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00003983 case Match_InvalidImm0_7:
3984 case Match_InvalidImm0_15:
3985 case Match_InvalidImm0_31:
3986 case Match_InvalidImm0_63:
3987 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003988 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00003989 case Match_InvalidImm0_65535:
3990 case Match_InvalidImm1_8:
3991 case Match_InvalidImm1_16:
3992 case Match_InvalidImm1_32:
3993 case Match_InvalidImm1_64:
3994 case Match_InvalidIndex1:
3995 case Match_InvalidIndexB:
3996 case Match_InvalidIndexH:
3997 case Match_InvalidIndexS:
3998 case Match_InvalidIndexD:
3999 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004000 case Match_InvalidComplexRotationEven:
4001 case Match_InvalidComplexRotationOdd:
Tim Northover3b0846e2014-05-24 12:50:23 +00004002 case Match_MSR:
4003 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004004 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004005 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004006 // Any time we get here, there's nothing fancy to do. Just get the
4007 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004008 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004009 if (ErrorLoc == SMLoc())
4010 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004011 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004012 }
4013 }
4014
4015 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004016}
4017
4018/// ParseDirective parses the arm specific directives
4019bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004020 const MCObjectFileInfo::Environment Format =
4021 getContext().getObjectFileInfo()->getObjectFileType();
4022 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4023 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004024
Tim Northover3b0846e2014-05-24 12:50:23 +00004025 StringRef IDVal = DirectiveID.getIdentifier();
4026 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004027 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004028 parseDirectiveArch(Loc);
4029 else if (IDVal == ".cpu")
4030 parseDirectiveCPU(Loc);
4031 else if (IDVal == ".hword")
4032 parseDirectiveWord(2, Loc);
4033 else if (IDVal == ".word")
4034 parseDirectiveWord(4, Loc);
4035 else if (IDVal == ".xword")
4036 parseDirectiveWord(8, Loc);
4037 else if (IDVal == ".tlsdesccall")
4038 parseDirectiveTLSDescCall(Loc);
4039 else if (IDVal == ".ltorg" || IDVal == ".pool")
4040 parseDirectiveLtorg(Loc);
4041 else if (IDVal == ".unreq")
4042 parseDirectiveUnreq(Loc);
4043 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004044 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004045 parseDirectiveInst(Loc);
4046 else
4047 return true;
4048 } else if (IDVal == MCLOHDirectiveName())
4049 parseDirectiveLOH(IDVal, Loc);
4050 else
4051 return true;
4052 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004053}
4054
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004055static const struct {
4056 const char *Name;
4057 const FeatureBitset Features;
4058} ExtensionMap[] = {
4059 { "crc", {AArch64::FeatureCRC} },
4060 { "crypto", {AArch64::FeatureCrypto} },
4061 { "fp", {AArch64::FeatureFPARMv8} },
4062 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004063 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004064 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004065
4066 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004067 { "pan", {} },
4068 { "lor", {} },
4069 { "rdma", {} },
4070 { "profile", {} },
4071};
4072
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004073/// parseDirectiveArch
4074/// ::= .arch token
4075bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4076 SMLoc ArchLoc = getLoc();
4077
4078 StringRef Arch, ExtensionString;
4079 std::tie(Arch, ExtensionString) =
4080 getParser().parseStringToEndOfStatement().trim().split('+');
4081
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004082 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4083 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004084 return Error(ArchLoc, "unknown arch name");
4085
4086 if (parseToken(AsmToken::EndOfStatement))
4087 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004088
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004089 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004090 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004091 AArch64::getArchFeatures(ID, AArch64Features);
4092 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4093 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004094
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004095 MCSubtargetInfo &STI = copySTI();
4096 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4097 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4098
4099 SmallVector<StringRef, 4> RequestedExtensions;
4100 if (!ExtensionString.empty())
4101 ExtensionString.split(RequestedExtensions, '+');
4102
4103 FeatureBitset Features = STI.getFeatureBits();
4104 for (auto Name : RequestedExtensions) {
4105 bool EnableFeature = true;
4106
4107 if (Name.startswith_lower("no")) {
4108 EnableFeature = false;
4109 Name = Name.substr(2);
4110 }
4111
4112 for (const auto &Extension : ExtensionMap) {
4113 if (Extension.Name != Name)
4114 continue;
4115
4116 if (Extension.Features.none())
4117 report_fatal_error("unsupported architectural extension: " + Name);
4118
4119 FeatureBitset ToggleFeatures = EnableFeature
4120 ? (~Features & Extension.Features)
4121 : ( Features & Extension.Features);
4122 uint64_t Features =
4123 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4124 setAvailableFeatures(Features);
4125 break;
4126 }
4127 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004128 return false;
4129}
4130
Tim Northover8b96c7e2017-05-15 19:42:15 +00004131static SMLoc incrementLoc(SMLoc L, int Offset) {
4132 return SMLoc::getFromPointer(L.getPointer() + Offset);
4133}
4134
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004135/// parseDirectiveCPU
4136/// ::= .cpu id
4137bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004138 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004139
4140 StringRef CPU, ExtensionString;
4141 std::tie(CPU, ExtensionString) =
4142 getParser().parseStringToEndOfStatement().trim().split('+');
4143
Nirav Davee833c6c2016-11-08 18:31:04 +00004144 if (parseToken(AsmToken::EndOfStatement))
4145 return true;
4146
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004147 SmallVector<StringRef, 4> RequestedExtensions;
4148 if (!ExtensionString.empty())
4149 ExtensionString.split(RequestedExtensions, '+');
4150
4151 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4152 // once that is tablegen'ed
4153 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004154 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004155 return false;
4156 }
4157
4158 MCSubtargetInfo &STI = copySTI();
4159 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004160 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004161
4162 FeatureBitset Features = STI.getFeatureBits();
4163 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004164 // Advance source location past '+'.
4165 CurLoc = incrementLoc(CurLoc, 1);
4166
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004167 bool EnableFeature = true;
4168
4169 if (Name.startswith_lower("no")) {
4170 EnableFeature = false;
4171 Name = Name.substr(2);
4172 }
4173
Tim Northover8b96c7e2017-05-15 19:42:15 +00004174 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004175 for (const auto &Extension : ExtensionMap) {
4176 if (Extension.Name != Name)
4177 continue;
4178
4179 if (Extension.Features.none())
4180 report_fatal_error("unsupported architectural extension: " + Name);
4181
4182 FeatureBitset ToggleFeatures = EnableFeature
4183 ? (~Features & Extension.Features)
4184 : ( Features & Extension.Features);
4185 uint64_t Features =
4186 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4187 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004188 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004189
4190 break;
4191 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004192
4193 if (!FoundExtension)
4194 Error(CurLoc, "unsupported architectural extension");
4195
4196 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004197 }
4198 return false;
4199}
4200
Tim Northover3b0846e2014-05-24 12:50:23 +00004201/// parseDirectiveWord
4202/// ::= .word [ expression (, expression)* ]
4203bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004204 auto parseOp = [&]() -> bool {
4205 const MCExpr *Value;
4206 if (getParser().parseExpression(Value))
4207 return true;
4208 getParser().getStreamer().EmitValue(Value, Size, L);
4209 return false;
4210 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004211
Nirav Davee833c6c2016-11-08 18:31:04 +00004212 if (parseMany(parseOp))
4213 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004214 return false;
4215}
4216
Chad Rosierdcd2a302014-10-22 20:35:57 +00004217/// parseDirectiveInst
4218/// ::= .inst opcode [, ...]
4219bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004220 if (getLexer().is(AsmToken::EndOfStatement))
4221 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004222
Nirav Davee833c6c2016-11-08 18:31:04 +00004223 auto parseOp = [&]() -> bool {
4224 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004225 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004226 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4227 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004228 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004229 if (check(!Value, L, "expected constant expression"))
4230 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004231 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004232 return false;
4233 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004234
Nirav Davee833c6c2016-11-08 18:31:04 +00004235 if (parseMany(parseOp))
4236 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004237 return false;
4238}
4239
Tim Northover3b0846e2014-05-24 12:50:23 +00004240// parseDirectiveTLSDescCall:
4241// ::= .tlsdesccall symbol
4242bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4243 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004244 if (check(getParser().parseIdentifier(Name), L,
4245 "expected symbol after directive") ||
4246 parseToken(AsmToken::EndOfStatement))
4247 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004248
Jim Grosbach6f482002015-05-18 18:43:14 +00004249 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004250 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4251 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004252
4253 MCInst Inst;
4254 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004255 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004256
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004257 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004258 return false;
4259}
4260
4261/// ::= .loh <lohName | lohId> label1, ..., labelN
4262/// The number of arguments depends on the loh identifier.
4263bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004264 MCLOHType Kind;
4265 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4266 if (getParser().getTok().isNot(AsmToken::Integer))
4267 return TokError("expected an identifier or a number in directive");
4268 // We successfully get a numeric value for the identifier.
4269 // Check if it is valid.
4270 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004271 if (Id <= -1U && !isValidMCLOHType(Id))
4272 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004273 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004274 } else {
4275 StringRef Name = getTok().getIdentifier();
4276 // We successfully parse an identifier.
4277 // Check if it is a recognized one.
4278 int Id = MCLOHNameToId(Name);
4279
4280 if (Id == -1)
4281 return TokError("invalid identifier in directive");
4282 Kind = (MCLOHType)Id;
4283 }
4284 // Consume the identifier.
4285 Lex();
4286 // Get the number of arguments of this LOH.
4287 int NbArgs = MCLOHIdToNbArgs(Kind);
4288
4289 assert(NbArgs != -1 && "Invalid number of arguments");
4290
4291 SmallVector<MCSymbol *, 3> Args;
4292 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4293 StringRef Name;
4294 if (getParser().parseIdentifier(Name))
4295 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004296 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004297
4298 if (Idx + 1 == NbArgs)
4299 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004300 if (parseToken(AsmToken::Comma,
4301 "unexpected token in '" + Twine(IDVal) + "' directive"))
4302 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004303 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004304 if (parseToken(AsmToken::EndOfStatement,
4305 "unexpected token in '" + Twine(IDVal) + "' directive"))
4306 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004307
4308 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4309 return false;
4310}
4311
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004312/// parseDirectiveLtorg
4313/// ::= .ltorg | .pool
4314bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004315 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4316 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004317 getTargetStreamer().emitCurrentConstantPool();
4318 return false;
4319}
4320
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004321/// parseDirectiveReq
4322/// ::= name .req registername
4323bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004324 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004325 Parser.Lex(); // Eat the '.req' token.
4326 SMLoc SRegLoc = getLoc();
Sander de Smalen8e607342017-11-15 15:44:43 +00004327 int RegNum = tryParseRegister();
Florian Hahnc4422242017-11-07 13:07:50 +00004328 RegKind RegisterKind = RegKind::Scalar;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004329
Sander de Smalen8e607342017-11-15 15:44:43 +00004330 if (RegNum == -1) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004331 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004332 RegisterKind = RegKind::NeonVector;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004333 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004334 if (!Kind.empty())
4335 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004336 }
4337
Sander de Smalen8e607342017-11-15 15:44:43 +00004338 if (RegNum == -1) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004339 StringRef Kind;
4340 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen8e607342017-11-15 15:44:43 +00004341 OperandMatchResultTy Res =
4342 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4343
4344 if (Res == MatchOperand_ParseFail)
4345 return true;
4346
4347 if (Res == MatchOperand_Success && !Kind.empty())
4348 return Error(SRegLoc,
4349 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004350 }
4351
Sander de Smalen8e607342017-11-15 15:44:43 +00004352 if (RegNum == -1)
Nirav Dave2364748a2016-09-16 18:30:20 +00004353 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004354
4355 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004356 if (parseToken(AsmToken::EndOfStatement,
4357 "unexpected input in .req directive"))
4358 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004359
Sander de Smalen8e607342017-11-15 15:44:43 +00004360 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004361 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004362 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4363
Nirav Dave2364748a2016-09-16 18:30:20 +00004364 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004365}
4366
4367/// parseDirectiveUneq
4368/// ::= .unreq registername
4369bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004370 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004371 if (getTok().isNot(AsmToken::Identifier))
4372 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004373 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4374 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004375 if (parseToken(AsmToken::EndOfStatement))
4376 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004377 return false;
4378}
4379
Tim Northover3b0846e2014-05-24 12:50:23 +00004380bool
4381AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4382 AArch64MCExpr::VariantKind &ELFRefKind,
4383 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4384 int64_t &Addend) {
4385 ELFRefKind = AArch64MCExpr::VK_INVALID;
4386 DarwinRefKind = MCSymbolRefExpr::VK_None;
4387 Addend = 0;
4388
4389 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4390 ELFRefKind = AE->getKind();
4391 Expr = AE->getSubExpr();
4392 }
4393
4394 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4395 if (SE) {
4396 // It's a simple symbol reference with no addend.
4397 DarwinRefKind = SE->getKind();
4398 return true;
4399 }
4400
4401 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4402 if (!BE)
4403 return false;
4404
4405 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4406 if (!SE)
4407 return false;
4408 DarwinRefKind = SE->getKind();
4409
4410 if (BE->getOpcode() != MCBinaryExpr::Add &&
4411 BE->getOpcode() != MCBinaryExpr::Sub)
4412 return false;
4413
4414 // See if the addend is is a constant, otherwise there's more going
4415 // on here than we can deal with.
4416 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4417 if (!AddendExpr)
4418 return false;
4419
4420 Addend = AddendExpr->getValue();
4421 if (BE->getOpcode() == MCBinaryExpr::Sub)
4422 Addend = -Addend;
4423
4424 // It's some symbol reference + a constant addend, but really
4425 // shouldn't use both Darwin and ELF syntax.
4426 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4427 DarwinRefKind == MCSymbolRefExpr::VK_None;
4428}
4429
4430/// Force static initialization.
4431extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004432 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4433 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4434 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004435}
4436
4437#define GET_REGISTER_MATCHER
4438#define GET_SUBTARGET_FEATURE_NAME
4439#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004440#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004441#include "AArch64GenAsmMatcher.inc"
4442
4443// Define this matcher function after the auto-generated include so we
4444// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004445unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004446 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004447 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004448 // If the kind is a token for a literal immediate, check if our asm
4449 // operand matches. This is for InstAliases which have a fixed-value
4450 // immediate in the syntax.
4451 int64_t ExpectedVal;
4452 switch (Kind) {
4453 default:
4454 return Match_InvalidOperand;
4455 case MCK__35_0:
4456 ExpectedVal = 0;
4457 break;
4458 case MCK__35_1:
4459 ExpectedVal = 1;
4460 break;
4461 case MCK__35_12:
4462 ExpectedVal = 12;
4463 break;
4464 case MCK__35_16:
4465 ExpectedVal = 16;
4466 break;
4467 case MCK__35_2:
4468 ExpectedVal = 2;
4469 break;
4470 case MCK__35_24:
4471 ExpectedVal = 24;
4472 break;
4473 case MCK__35_3:
4474 ExpectedVal = 3;
4475 break;
4476 case MCK__35_32:
4477 ExpectedVal = 32;
4478 break;
4479 case MCK__35_4:
4480 ExpectedVal = 4;
4481 break;
4482 case MCK__35_48:
4483 ExpectedVal = 48;
4484 break;
4485 case MCK__35_6:
4486 ExpectedVal = 6;
4487 break;
4488 case MCK__35_64:
4489 ExpectedVal = 64;
4490 break;
4491 case MCK__35_8:
4492 ExpectedVal = 8;
4493 break;
4494 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004495 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004496 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004497 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004498 if (!CE)
4499 return Match_InvalidOperand;
4500 if (CE->getValue() == ExpectedVal)
4501 return Match_Success;
4502 return Match_InvalidOperand;
4503}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004504
Alex Bradbury58eba092016-11-01 16:32:05 +00004505OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004506AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4507
4508 SMLoc S = getLoc();
4509
4510 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4511 Error(S, "expected register");
4512 return MatchOperand_ParseFail;
4513 }
4514
4515 int FirstReg = tryParseRegister();
4516 if (FirstReg == -1) {
4517 return MatchOperand_ParseFail;
4518 }
4519 const MCRegisterClass &WRegClass =
4520 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4521 const MCRegisterClass &XRegClass =
4522 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4523
4524 bool isXReg = XRegClass.contains(FirstReg),
4525 isWReg = WRegClass.contains(FirstReg);
4526 if (!isXReg && !isWReg) {
4527 Error(S, "expected first even register of a "
4528 "consecutive same-size even/odd register pair");
4529 return MatchOperand_ParseFail;
4530 }
4531
4532 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4533 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4534
4535 if (FirstEncoding & 0x1) {
4536 Error(S, "expected first even register of a "
4537 "consecutive same-size even/odd register pair");
4538 return MatchOperand_ParseFail;
4539 }
4540
4541 SMLoc M = getLoc();
4542 if (getParser().getTok().isNot(AsmToken::Comma)) {
4543 Error(M, "expected comma");
4544 return MatchOperand_ParseFail;
4545 }
4546 // Eat the comma
4547 getParser().Lex();
4548
4549 SMLoc E = getLoc();
4550 int SecondReg = tryParseRegister();
4551 if (SecondReg ==-1) {
4552 return MatchOperand_ParseFail;
4553 }
4554
Eugene Zelenko049b0172017-01-06 00:30:53 +00004555 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004556 (isXReg && !XRegClass.contains(SecondReg)) ||
4557 (isWReg && !WRegClass.contains(SecondReg))) {
4558 Error(E,"expected second odd register of a "
4559 "consecutive same-size even/odd register pair");
4560 return MatchOperand_ParseFail;
4561 }
Joel Jones504bf332016-10-24 13:37:13 +00004562
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004563 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004564 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004565 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4566 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4567 } else {
4568 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4569 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4570 }
4571
Florian Hahnc4422242017-11-07 13:07:50 +00004572 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4573 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004574
4575 return MatchOperand_Success;
4576}
Florian Hahn91f11e52017-11-07 16:45:48 +00004577
4578template <bool ParseSuffix>
4579OperandMatchResultTy
4580AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004581 const SMLoc S = getLoc();
4582 // Check for a SVE vector register specifier first.
Sander de Smalen8e607342017-11-15 15:44:43 +00004583 int RegNum = -1;
Florian Hahn91f11e52017-11-07 16:45:48 +00004584 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004585
Sander de Smalen8e607342017-11-15 15:44:43 +00004586 OperandMatchResultTy Res =
4587 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4588
4589 if (Res != MatchOperand_Success)
4590 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004591
4592 if (ParseSuffix && Kind.empty())
4593 return MatchOperand_NoMatch;
4594
4595 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
4596 .Case("", -1)
4597 .Case(".b", 8)
4598 .Case(".h", 16)
4599 .Case(".s", 32)
4600 .Case(".d", 64)
4601 .Case(".q", 128)
4602 .Default(0);
4603 if (!ElementWidth)
4604 return MatchOperand_NoMatch;
4605
4606 Operands.push_back(
4607 AArch64Operand::CreateReg(RegNum, RegKind::SVEDataVector, ElementWidth,
4608 S, S, getContext()));
4609
4610 return MatchOperand_Success;
4611}