blob: 66d2a5d6a78659ee7c5c5ee2d2dc244167091331 [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 Smalen2b6338b2017-11-29 14:34:18 +000062enum class RegKind {
63 Scalar,
64 NeonVector,
65 SVEDataVector,
66 SVEPredicateVector
67};
Florian Hahnc4422242017-11-07 13:07:50 +000068
Tim Northover3b0846e2014-05-24 12:50:23 +000069class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000070private:
71 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000072
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000073 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000074 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000075
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000076 AArch64TargetStreamer &getTargetStreamer() {
77 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
78 return static_cast<AArch64TargetStreamer &>(TS);
79 }
80
Rafael Espindola961d4692014-11-11 05:18:41 +000081 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000082
83 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +000084 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +000085 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
86 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +000087 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +000088 int tryParseRegister();
89 int tryMatchVectorRegister(StringRef &Kind, bool expected);
90 bool parseRegister(OperandVector &Operands);
91 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
92 bool parseVectorList(OperandVector &Operands);
93 bool parseOperand(OperandVector &Operands, bool isCondCode,
94 bool invertCondCode);
95
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +000096 bool showMatchError(SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000097
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000098 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000099 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000100 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +0000101 bool parseDirectiveInst(SMLoc L);
102
Tim Northover3b0846e2014-05-24 12:50:23 +0000103 bool parseDirectiveTLSDescCall(SMLoc L);
104
105 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000106 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000107
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000108 bool parseDirectiveReq(StringRef Name, SMLoc L);
109 bool parseDirectiveUnreq(SMLoc L);
110
Tim Northover3b0846e2014-05-24 12:50:23 +0000111 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
112 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
113 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000114 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000115 bool MatchingInlineAsm) override;
116/// @name Auto-generated Match Functions
117/// {
118
119#define GET_ASSEMBLER_HEADER
120#include "AArch64GenAsmMatcher.inc"
121
122 /// }
123
Sander de Smalen8e607342017-11-15 15:44:43 +0000124 OperandMatchResultTy tryParseSVERegister(int &Reg, StringRef &Kind,
125 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000126 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
127 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
128 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
129 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
130 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
131 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000132 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000133 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
134 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
135 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
136 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
137 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000138 bool tryParseNeonVectorRegister(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000139 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Florian Hahn91f11e52017-11-07 16:45:48 +0000140 template <bool ParseSuffix>
141 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalen2b6338b2017-11-29 14:34:18 +0000142 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000143
144public:
145 enum AArch64MatchResultTy {
146 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
147#define GET_OPERAND_DIAGNOSTIC_TYPES
148#include "AArch64GenAsmMatcher.inc"
149 };
Joel Jones504bf332016-10-24 13:37:13 +0000150 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000151
Akira Hatanakab11ef082015-11-14 06:35:56 +0000152 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000153 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000154 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000155 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000156 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000157 MCStreamer &S = getParser().getStreamer();
158 if (S.getTargetStreamer() == nullptr)
159 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000160
161 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000162 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000163 }
164
165 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
166 SMLoc NameLoc, OperandVector &Operands) override;
167 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
168 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000169 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000170 unsigned Kind) override;
171
172 static bool classifySymbolRef(const MCExpr *Expr,
173 AArch64MCExpr::VariantKind &ELFRefKind,
174 MCSymbolRefExpr::VariantKind &DarwinRefKind,
175 int64_t &Addend);
176};
Tim Northover3b0846e2014-05-24 12:50:23 +0000177
178/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
179/// instruction.
180class AArch64Operand : public MCParsedAsmOperand {
181private:
182 enum KindTy {
183 k_Immediate,
184 k_ShiftedImm,
185 k_CondCode,
186 k_Register,
187 k_VectorList,
188 k_VectorIndex,
189 k_Token,
190 k_SysReg,
191 k_SysCR,
192 k_Prefetch,
193 k_ShiftExtend,
194 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000195 k_Barrier,
196 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000197 } Kind;
198
199 SMLoc StartLoc, EndLoc;
200
201 struct TokOp {
202 const char *Data;
203 unsigned Length;
204 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
205 };
206
207 struct RegOp {
208 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000209 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000210
211 int ElementWidth;
Tim Northover3b0846e2014-05-24 12:50:23 +0000212 };
213
214 struct VectorListOp {
215 unsigned RegNum;
216 unsigned Count;
217 unsigned NumElements;
218 unsigned ElementKind;
219 };
220
221 struct VectorIndexOp {
222 unsigned Val;
223 };
224
225 struct ImmOp {
226 const MCExpr *Val;
227 };
228
229 struct ShiftedImmOp {
230 const MCExpr *Val;
231 unsigned ShiftAmount;
232 };
233
234 struct CondCodeOp {
235 AArch64CC::CondCode Code;
236 };
237
238 struct FPImmOp {
239 unsigned Val; // Encoded 8-bit representation.
240 };
241
242 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000243 const char *Data;
244 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000245 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000246 };
247
248 struct SysRegOp {
249 const char *Data;
250 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000251 uint32_t MRSReg;
252 uint32_t MSRReg;
253 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000254 };
255
256 struct SysCRImmOp {
257 unsigned Val;
258 };
259
260 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000261 const char *Data;
262 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000263 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000264 };
265
Oliver Stannarda34e4702015-12-01 10:48:51 +0000266 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000267 const char *Data;
268 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000269 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000270 };
271
Tim Northover3b0846e2014-05-24 12:50:23 +0000272 struct ShiftExtendOp {
273 AArch64_AM::ShiftExtendType Type;
274 unsigned Amount;
275 bool HasExplicitAmount;
276 };
277
278 struct ExtendOp {
279 unsigned Val;
280 };
281
282 union {
283 struct TokOp Tok;
284 struct RegOp Reg;
285 struct VectorListOp VectorList;
286 struct VectorIndexOp VectorIndex;
287 struct ImmOp Imm;
288 struct ShiftedImmOp ShiftedImm;
289 struct CondCodeOp CondCode;
290 struct FPImmOp FPImm;
291 struct BarrierOp Barrier;
292 struct SysRegOp SysReg;
293 struct SysCRImmOp SysCRImm;
294 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000295 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000296 struct ShiftExtendOp ShiftExtend;
297 };
298
299 // Keep the MCContext around as the MCExprs may need manipulated during
300 // the add<>Operands() calls.
301 MCContext &Ctx;
302
David Blaikie960ea3f2014-06-08 16:18:35 +0000303public:
David Blaikie9f380a32015-03-16 18:06:57 +0000304 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000305
Tim Northover3b0846e2014-05-24 12:50:23 +0000306 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
307 Kind = o.Kind;
308 StartLoc = o.StartLoc;
309 EndLoc = o.EndLoc;
310 switch (Kind) {
311 case k_Token:
312 Tok = o.Tok;
313 break;
314 case k_Immediate:
315 Imm = o.Imm;
316 break;
317 case k_ShiftedImm:
318 ShiftedImm = o.ShiftedImm;
319 break;
320 case k_CondCode:
321 CondCode = o.CondCode;
322 break;
323 case k_FPImm:
324 FPImm = o.FPImm;
325 break;
326 case k_Barrier:
327 Barrier = o.Barrier;
328 break;
329 case k_Register:
330 Reg = o.Reg;
331 break;
332 case k_VectorList:
333 VectorList = o.VectorList;
334 break;
335 case k_VectorIndex:
336 VectorIndex = o.VectorIndex;
337 break;
338 case k_SysReg:
339 SysReg = o.SysReg;
340 break;
341 case k_SysCR:
342 SysCRImm = o.SysCRImm;
343 break;
344 case k_Prefetch:
345 Prefetch = o.Prefetch;
346 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000347 case k_PSBHint:
348 PSBHint = o.PSBHint;
349 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000350 case k_ShiftExtend:
351 ShiftExtend = o.ShiftExtend;
352 break;
353 }
354 }
355
356 /// getStartLoc - Get the location of the first token of this operand.
357 SMLoc getStartLoc() const override { return StartLoc; }
358 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000359 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000360
361 StringRef getToken() const {
362 assert(Kind == k_Token && "Invalid access!");
363 return StringRef(Tok.Data, Tok.Length);
364 }
365
366 bool isTokenSuffix() const {
367 assert(Kind == k_Token && "Invalid access!");
368 return Tok.IsSuffix;
369 }
370
371 const MCExpr *getImm() const {
372 assert(Kind == k_Immediate && "Invalid access!");
373 return Imm.Val;
374 }
375
376 const MCExpr *getShiftedImmVal() const {
377 assert(Kind == k_ShiftedImm && "Invalid access!");
378 return ShiftedImm.Val;
379 }
380
381 unsigned getShiftedImmShift() const {
382 assert(Kind == k_ShiftedImm && "Invalid access!");
383 return ShiftedImm.ShiftAmount;
384 }
385
386 AArch64CC::CondCode getCondCode() const {
387 assert(Kind == k_CondCode && "Invalid access!");
388 return CondCode.Code;
389 }
390
391 unsigned getFPImm() const {
392 assert(Kind == k_FPImm && "Invalid access!");
393 return FPImm.Val;
394 }
395
396 unsigned getBarrier() const {
397 assert(Kind == k_Barrier && "Invalid access!");
398 return Barrier.Val;
399 }
400
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000401 StringRef getBarrierName() const {
402 assert(Kind == k_Barrier && "Invalid access!");
403 return StringRef(Barrier.Data, Barrier.Length);
404 }
405
Tim Northover3b0846e2014-05-24 12:50:23 +0000406 unsigned getReg() const override {
407 assert(Kind == k_Register && "Invalid access!");
408 return Reg.RegNum;
409 }
410
411 unsigned getVectorListStart() const {
412 assert(Kind == k_VectorList && "Invalid access!");
413 return VectorList.RegNum;
414 }
415
416 unsigned getVectorListCount() const {
417 assert(Kind == k_VectorList && "Invalid access!");
418 return VectorList.Count;
419 }
420
421 unsigned getVectorIndex() const {
422 assert(Kind == k_VectorIndex && "Invalid access!");
423 return VectorIndex.Val;
424 }
425
426 StringRef getSysReg() const {
427 assert(Kind == k_SysReg && "Invalid access!");
428 return StringRef(SysReg.Data, SysReg.Length);
429 }
430
Tim Northover3b0846e2014-05-24 12:50:23 +0000431 unsigned getSysCR() const {
432 assert(Kind == k_SysCR && "Invalid access!");
433 return SysCRImm.Val;
434 }
435
436 unsigned getPrefetch() const {
437 assert(Kind == k_Prefetch && "Invalid access!");
438 return Prefetch.Val;
439 }
440
Oliver Stannarda34e4702015-12-01 10:48:51 +0000441 unsigned getPSBHint() const {
442 assert(Kind == k_PSBHint && "Invalid access!");
443 return PSBHint.Val;
444 }
445
446 StringRef getPSBHintName() const {
447 assert(Kind == k_PSBHint && "Invalid access!");
448 return StringRef(PSBHint.Data, PSBHint.Length);
449 }
450
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000451 StringRef getPrefetchName() const {
452 assert(Kind == k_Prefetch && "Invalid access!");
453 return StringRef(Prefetch.Data, Prefetch.Length);
454 }
455
Tim Northover3b0846e2014-05-24 12:50:23 +0000456 AArch64_AM::ShiftExtendType getShiftExtendType() const {
457 assert(Kind == k_ShiftExtend && "Invalid access!");
458 return ShiftExtend.Type;
459 }
460
461 unsigned getShiftExtendAmount() const {
462 assert(Kind == k_ShiftExtend && "Invalid access!");
463 return ShiftExtend.Amount;
464 }
465
466 bool hasShiftExtendAmount() const {
467 assert(Kind == k_ShiftExtend && "Invalid access!");
468 return ShiftExtend.HasExplicitAmount;
469 }
470
471 bool isImm() const override { return Kind == k_Immediate; }
472 bool isMem() const override { return false; }
473 bool isSImm9() const {
474 if (!isImm())
475 return false;
476 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
477 if (!MCE)
478 return false;
479 int64_t Val = MCE->getValue();
480 return (Val >= -256 && Val < 256);
481 }
Sam Parker6d42de72017-08-11 13:14:00 +0000482 bool isSImm10s8() const {
483 if (!isImm())
484 return false;
485 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
486 if (!MCE)
487 return false;
488 int64_t Val = MCE->getValue();
489 return (Val >= -4096 && Val < 4089 && (Val & 7) == 0);
490 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000491 bool isSImm7s4() const {
492 if (!isImm())
493 return false;
494 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
495 if (!MCE)
496 return false;
497 int64_t Val = MCE->getValue();
498 return (Val >= -256 && Val <= 252 && (Val & 3) == 0);
499 }
500 bool isSImm7s8() const {
501 if (!isImm())
502 return false;
503 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
504 if (!MCE)
505 return false;
506 int64_t Val = MCE->getValue();
507 return (Val >= -512 && Val <= 504 && (Val & 7) == 0);
508 }
509 bool isSImm7s16() const {
510 if (!isImm())
511 return false;
512 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
513 if (!MCE)
514 return false;
515 int64_t Val = MCE->getValue();
516 return (Val >= -1024 && Val <= 1008 && (Val & 15) == 0);
517 }
518
519 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
520 AArch64MCExpr::VariantKind ELFRefKind;
521 MCSymbolRefExpr::VariantKind DarwinRefKind;
522 int64_t Addend;
523 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
524 Addend)) {
525 // If we don't understand the expression, assume the best and
526 // let the fixup and relocation code deal with it.
527 return true;
528 }
529
530 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
531 ELFRefKind == AArch64MCExpr::VK_LO12 ||
532 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
533 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
534 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
535 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
536 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
537 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
538 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) {
539 // Note that we don't range-check the addend. It's adjusted modulo page
540 // size when converted, so there is no "out of range" condition when using
541 // @pageoff.
542 return Addend >= 0 && (Addend % Scale) == 0;
543 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
544 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
545 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
546 return Addend == 0;
547 }
548
549 return false;
550 }
551
552 template <int Scale> bool isUImm12Offset() const {
553 if (!isImm())
554 return false;
555
556 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
557 if (!MCE)
558 return isSymbolicUImm12Offset(getImm(), Scale);
559
560 int64_t Val = MCE->getValue();
561 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
562 }
563
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000564 template <int N, int M>
565 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000566 if (!isImm())
567 return false;
568 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
569 if (!MCE)
570 return false;
571 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000572 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000573 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000574
Tim Northover3b0846e2014-05-24 12:50:23 +0000575 bool isLogicalImm32() const {
576 if (!isImm())
577 return false;
578 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
579 if (!MCE)
580 return false;
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000581 int64_t Val = MCE->getValue();
582 if (Val >> 32 != 0 && Val >> 32 != ~0LL)
583 return false;
584 Val &= 0xFFFFFFFF;
585 return AArch64_AM::isLogicalImmediate(Val, 32);
Tim Northover3b0846e2014-05-24 12:50:23 +0000586 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000587
Tim Northover3b0846e2014-05-24 12:50:23 +0000588 bool isLogicalImm64() const {
589 if (!isImm())
590 return false;
591 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
592 if (!MCE)
593 return false;
594 return AArch64_AM::isLogicalImmediate(MCE->getValue(), 64);
595 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000596
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000597 bool isLogicalImm32Not() const {
598 if (!isImm())
599 return false;
600 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
601 if (!MCE)
602 return false;
603 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
604 return AArch64_AM::isLogicalImmediate(Val, 32);
605 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000606
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000607 bool isLogicalImm64Not() const {
608 if (!isImm())
609 return false;
610 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
611 if (!MCE)
612 return false;
613 return AArch64_AM::isLogicalImmediate(~MCE->getValue(), 64);
614 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000615
Tim Northover3b0846e2014-05-24 12:50:23 +0000616 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000617
Tim Northover3b0846e2014-05-24 12:50:23 +0000618 bool isAddSubImm() const {
619 if (!isShiftedImm() && !isImm())
620 return false;
621
622 const MCExpr *Expr;
623
624 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
625 if (isShiftedImm()) {
626 unsigned Shift = ShiftedImm.ShiftAmount;
627 Expr = ShiftedImm.Val;
628 if (Shift != 0 && Shift != 12)
629 return false;
630 } else {
631 Expr = getImm();
632 }
633
634 AArch64MCExpr::VariantKind ELFRefKind;
635 MCSymbolRefExpr::VariantKind DarwinRefKind;
636 int64_t Addend;
637 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
638 DarwinRefKind, Addend)) {
639 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
640 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
641 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
642 || ELFRefKind == AArch64MCExpr::VK_LO12
643 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
644 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
645 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
646 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
647 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
648 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
649 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12;
650 }
651
Diana Picusc93518d2016-10-11 09:17:47 +0000652 // If it's a constant, it should be a real immediate in range:
653 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
654 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
655
656 // If it's an expression, we hope for the best and let the fixup/relocation
657 // code deal with it.
658 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000659 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000660
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000661 bool isAddSubImmNeg() const {
662 if (!isShiftedImm() && !isImm())
663 return false;
664
665 const MCExpr *Expr;
666
667 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
668 if (isShiftedImm()) {
669 unsigned Shift = ShiftedImm.ShiftAmount;
670 Expr = ShiftedImm.Val;
671 if (Shift != 0 && Shift != 12)
672 return false;
673 } else
674 Expr = getImm();
675
676 // Otherwise it should be a real negative immediate in range:
677 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
678 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
679 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000680
Tim Northover3b0846e2014-05-24 12:50:23 +0000681 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000682
Tim Northover3b0846e2014-05-24 12:50:23 +0000683 bool isSIMDImmType10() const {
684 if (!isImm())
685 return false;
686 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
687 if (!MCE)
688 return false;
689 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
690 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000691
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000692 template<int N>
693 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000694 if (!isImm())
695 return false;
696 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
697 if (!MCE)
698 return true;
699 int64_t Val = MCE->getValue();
700 if (Val & 0x3)
701 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000702 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
703 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000704 }
705
706 bool
707 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
708 if (!isImm())
709 return false;
710
711 AArch64MCExpr::VariantKind ELFRefKind;
712 MCSymbolRefExpr::VariantKind DarwinRefKind;
713 int64_t Addend;
714 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
715 DarwinRefKind, Addend)) {
716 return false;
717 }
718 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
719 return false;
720
721 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
722 if (ELFRefKind == AllowedModifiers[i])
723 return Addend == 0;
724 }
725
726 return false;
727 }
728
729 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000730 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000731 }
732
733 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000734 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
735 AArch64MCExpr::VK_TPREL_G2,
736 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000737 }
738
739 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000740 return isMovWSymbol({
741 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000742 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
743 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000744 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000745 }
746
747 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000748 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
749 AArch64MCExpr::VK_TPREL_G0,
750 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000751 }
752
753 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000754 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000755 }
756
757 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000758 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000759 }
760
761 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000762 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
763 AArch64MCExpr::VK_TPREL_G1_NC,
764 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000765 }
766
767 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000768 return isMovWSymbol(
769 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
770 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000771 }
772
773 template<int RegWidth, int Shift>
774 bool isMOVZMovAlias() const {
775 if (!isImm()) return false;
776
777 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
778 if (!CE) return false;
779 uint64_t Value = CE->getValue();
780
Tim Northoverdaa1c012016-06-16 01:42:25 +0000781 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000782 }
783
784 template<int RegWidth, int Shift>
785 bool isMOVNMovAlias() const {
786 if (!isImm()) return false;
787
788 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
789 if (!CE) return false;
790 uint64_t Value = CE->getValue();
791
Tim Northoverdaa1c012016-06-16 01:42:25 +0000792 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000793 }
794
795 bool isFPImm() const { return Kind == k_FPImm; }
796 bool isBarrier() const { return Kind == k_Barrier; }
797 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000798
Tim Northover3b0846e2014-05-24 12:50:23 +0000799 bool isMRSSystemRegister() const {
800 if (!isSysReg()) return false;
801
Tim Northover7cd58932015-01-22 17:23:04 +0000802 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000803 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000804
Tim Northover3b0846e2014-05-24 12:50:23 +0000805 bool isMSRSystemRegister() const {
806 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000807 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000808 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000809
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000810 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000811 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000812 return (SysReg.PStateField == AArch64PState::PAN ||
813 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000814 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000815
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000816 bool isSystemPStateFieldWithImm0_15() const {
817 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000818 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000819 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000820
Florian Hahnc4422242017-11-07 13:07:50 +0000821 bool isReg() const override {
822 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
823 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000824
Florian Hahnc4422242017-11-07 13:07:50 +0000825 bool isNeonVectorReg() const {
826 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
827 }
828
829 bool isNeonVectorRegLo() const {
830 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000831 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
832 Reg.RegNum);
833 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000834
Sander de Smalen2b6338b2017-11-29 14:34:18 +0000835 template <unsigned Class> bool isSVEVectorReg() const {
836 RegKind RK;
837 switch (Class) {
838 case AArch64::ZPRRegClassID:
839 RK = RegKind::SVEDataVector;
840 break;
841 case AArch64::PPRRegClassID:
842 RK = RegKind::SVEPredicateVector;
843 break;
844 default:
845 llvm_unreachable("Unsupport register class");
846 }
847
848 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000849 AArch64MCRegisterClasses[Class].contains(getReg());
850 }
851
Sander de Smalen2b6338b2017-11-29 14:34:18 +0000852 template <int ElementWidth, unsigned Class>
853 bool isSVEVectorRegOfWidth() const {
854 return isSVEVectorReg<Class>() &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000855 (ElementWidth == -1 || Reg.ElementWidth == ElementWidth);
856 }
857
Tim Northover3b0846e2014-05-24 12:50:23 +0000858 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000859 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000860 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
861 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000862
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000863 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000864 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000865 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
866 Reg.RegNum);
867 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000868
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000869 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000870 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000871 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
872 Reg.RegNum);
873 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000874
875 bool isGPR64sp0() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000876 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000877 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
878 }
879
Sam Parker5f934642017-08-31 09:27:04 +0000880 template<int64_t Angle, int64_t Remainder>
881 bool isComplexRotation() const {
882 if (!isImm()) return false;
883
884 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
885 if (!CE) return false;
886 uint64_t Value = CE->getValue();
887
888 return (Value % Angle == Remainder && Value <= 270);
889 }
890
Tim Northover3b0846e2014-05-24 12:50:23 +0000891 /// Is this a vector list with the type implicit (presumably attached to the
892 /// instruction itself)?
893 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
894 return Kind == k_VectorList && VectorList.Count == NumRegs &&
895 !VectorList.ElementKind;
896 }
897
898 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
899 bool isTypedVectorList() const {
900 if (Kind != k_VectorList)
901 return false;
902 if (VectorList.Count != NumRegs)
903 return false;
904 if (VectorList.ElementKind != ElementKind)
905 return false;
906 return VectorList.NumElements == NumElements;
907 }
908
909 bool isVectorIndex1() const {
910 return Kind == k_VectorIndex && VectorIndex.Val == 1;
911 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000912
Tim Northover3b0846e2014-05-24 12:50:23 +0000913 bool isVectorIndexB() const {
914 return Kind == k_VectorIndex && VectorIndex.Val < 16;
915 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000916
Tim Northover3b0846e2014-05-24 12:50:23 +0000917 bool isVectorIndexH() const {
918 return Kind == k_VectorIndex && VectorIndex.Val < 8;
919 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000920
Tim Northover3b0846e2014-05-24 12:50:23 +0000921 bool isVectorIndexS() const {
922 return Kind == k_VectorIndex && VectorIndex.Val < 4;
923 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000924
Tim Northover3b0846e2014-05-24 12:50:23 +0000925 bool isVectorIndexD() const {
926 return Kind == k_VectorIndex && VectorIndex.Val < 2;
927 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000928
Tim Northover3b0846e2014-05-24 12:50:23 +0000929 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000930
Tim Northover3b0846e2014-05-24 12:50:23 +0000931 bool isTokenEqual(StringRef Str) const {
932 return Kind == k_Token && getToken() == Str;
933 }
934 bool isSysCR() const { return Kind == k_SysCR; }
935 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000936 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000937 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
938 bool isShifter() const {
939 if (!isShiftExtend())
940 return false;
941
942 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
943 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
944 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
945 ST == AArch64_AM::MSL);
946 }
947 bool isExtend() const {
948 if (!isShiftExtend())
949 return false;
950
951 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
952 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
953 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
954 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
955 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
956 ET == AArch64_AM::LSL) &&
957 getShiftExtendAmount() <= 4;
958 }
959
960 bool isExtend64() const {
961 if (!isExtend())
962 return false;
963 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
964 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
965 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
966 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000967
Tim Northover3b0846e2014-05-24 12:50:23 +0000968 bool isExtendLSL64() const {
969 if (!isExtend())
970 return false;
971 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
972 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
973 ET == AArch64_AM::LSL) &&
974 getShiftExtendAmount() <= 4;
975 }
976
977 template<int Width> bool isMemXExtend() const {
978 if (!isExtend())
979 return false;
980 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
981 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
982 (getShiftExtendAmount() == Log2_32(Width / 8) ||
983 getShiftExtendAmount() == 0);
984 }
985
986 template<int Width> bool isMemWExtend() const {
987 if (!isExtend())
988 return false;
989 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
990 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
991 (getShiftExtendAmount() == Log2_32(Width / 8) ||
992 getShiftExtendAmount() == 0);
993 }
994
995 template <unsigned width>
996 bool isArithmeticShifter() const {
997 if (!isShifter())
998 return false;
999
1000 // An arithmetic shifter is LSL, LSR, or ASR.
1001 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1002 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1003 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1004 }
1005
1006 template <unsigned width>
1007 bool isLogicalShifter() const {
1008 if (!isShifter())
1009 return false;
1010
1011 // A logical shifter is LSL, LSR, ASR or ROR.
1012 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1013 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1014 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1015 getShiftExtendAmount() < width;
1016 }
1017
1018 bool isMovImm32Shifter() const {
1019 if (!isShifter())
1020 return false;
1021
1022 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1023 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1024 if (ST != AArch64_AM::LSL)
1025 return false;
1026 uint64_t Val = getShiftExtendAmount();
1027 return (Val == 0 || Val == 16);
1028 }
1029
1030 bool isMovImm64Shifter() const {
1031 if (!isShifter())
1032 return false;
1033
1034 // A MOVi shifter is LSL of 0 or 16.
1035 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1036 if (ST != AArch64_AM::LSL)
1037 return false;
1038 uint64_t Val = getShiftExtendAmount();
1039 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1040 }
1041
1042 bool isLogicalVecShifter() const {
1043 if (!isShifter())
1044 return false;
1045
1046 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1047 unsigned Shift = getShiftExtendAmount();
1048 return getShiftExtendType() == AArch64_AM::LSL &&
1049 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1050 }
1051
1052 bool isLogicalVecHalfWordShifter() const {
1053 if (!isLogicalVecShifter())
1054 return false;
1055
1056 // A logical vector shifter is a left shift by 0 or 8.
1057 unsigned Shift = getShiftExtendAmount();
1058 return getShiftExtendType() == AArch64_AM::LSL &&
1059 (Shift == 0 || Shift == 8);
1060 }
1061
1062 bool isMoveVecShifter() const {
1063 if (!isShiftExtend())
1064 return false;
1065
1066 // A logical vector shifter is a left shift by 8 or 16.
1067 unsigned Shift = getShiftExtendAmount();
1068 return getShiftExtendType() == AArch64_AM::MSL &&
1069 (Shift == 8 || Shift == 16);
1070 }
1071
1072 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1073 // to LDUR/STUR when the offset is not legal for the former but is for
1074 // the latter. As such, in addition to checking for being a legal unscaled
1075 // address, also check that it is not a legal scaled address. This avoids
1076 // ambiguity in the matcher.
1077 template<int Width>
1078 bool isSImm9OffsetFB() const {
1079 return isSImm9() && !isUImm12Offset<Width / 8>();
1080 }
1081
1082 bool isAdrpLabel() const {
1083 // Validation was handled during parsing, so we just sanity check that
1084 // something didn't go haywire.
1085 if (!isImm())
1086 return false;
1087
1088 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1089 int64_t Val = CE->getValue();
1090 int64_t Min = - (4096 * (1LL << (21 - 1)));
1091 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1092 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1093 }
1094
1095 return true;
1096 }
1097
1098 bool isAdrLabel() const {
1099 // Validation was handled during parsing, so we just sanity check that
1100 // something didn't go haywire.
1101 if (!isImm())
1102 return false;
1103
1104 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1105 int64_t Val = CE->getValue();
1106 int64_t Min = - (1LL << (21 - 1));
1107 int64_t Max = ((1LL << (21 - 1)) - 1);
1108 return Val >= Min && Val <= Max;
1109 }
1110
1111 return true;
1112 }
1113
1114 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1115 // Add as immediates when possible. Null MCExpr = 0.
1116 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001117 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001118 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001119 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001120 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001121 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001122 }
1123
1124 void addRegOperands(MCInst &Inst, unsigned N) const {
1125 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001126 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001127 }
1128
1129 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1130 assert(N == 1 && "Invalid number of operands!");
1131 assert(
1132 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1133
1134 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1135 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1136 RI->getEncodingValue(getReg()));
1137
Jim Grosbache9119e42015-05-13 18:37:00 +00001138 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001139 }
1140
1141 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1142 assert(N == 1 && "Invalid number of operands!");
1143 assert(
1144 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001145 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001146 }
1147
1148 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1149 assert(N == 1 && "Invalid number of operands!");
1150 assert(
1151 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001152 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001153 }
1154
1155 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1156 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001157 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001158 }
1159
1160 template <unsigned NumRegs>
1161 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1162 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001163 static const unsigned FirstRegs[] = { AArch64::D0,
1164 AArch64::D0_D1,
1165 AArch64::D0_D1_D2,
1166 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001167 unsigned FirstReg = FirstRegs[NumRegs - 1];
1168
1169 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001170 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001171 }
1172
1173 template <unsigned NumRegs>
1174 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1175 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001176 static const unsigned FirstRegs[] = { AArch64::Q0,
1177 AArch64::Q0_Q1,
1178 AArch64::Q0_Q1_Q2,
1179 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001180 unsigned FirstReg = FirstRegs[NumRegs - 1];
1181
1182 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001183 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001184 }
1185
1186 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1187 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001188 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001189 }
1190
1191 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1192 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001193 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001194 }
1195
1196 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1197 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001198 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001199 }
1200
1201 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1202 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001203 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001204 }
1205
1206 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1207 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001208 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001209 }
1210
1211 void addImmOperands(MCInst &Inst, unsigned N) const {
1212 assert(N == 1 && "Invalid number of operands!");
1213 // If this is a pageoff symrefexpr with an addend, adjust the addend
1214 // to be only the page-offset portion. Otherwise, just add the expr
1215 // as-is.
1216 addExpr(Inst, getImm());
1217 }
1218
1219 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1220 assert(N == 2 && "Invalid number of operands!");
1221 if (isShiftedImm()) {
1222 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001223 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001224 } else {
1225 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001226 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001227 }
1228 }
1229
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001230 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1231 assert(N == 2 && "Invalid number of operands!");
1232
1233 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1234 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1235 int64_t Val = -CE->getValue();
1236 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1237
1238 Inst.addOperand(MCOperand::createImm(Val));
1239 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1240 }
1241
Tim Northover3b0846e2014-05-24 12:50:23 +00001242 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1243 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001244 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001245 }
1246
1247 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1248 assert(N == 1 && "Invalid number of operands!");
1249 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1250 if (!MCE)
1251 addExpr(Inst, getImm());
1252 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001253 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001254 }
1255
1256 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1257 addImmOperands(Inst, N);
1258 }
1259
1260 template<int Scale>
1261 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1262 assert(N == 1 && "Invalid number of operands!");
1263 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1264
1265 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001266 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001267 return;
1268 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001269 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001270 }
1271
1272 void addSImm9Operands(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()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001276 }
1277
Sam Parker6d42de72017-08-11 13:14:00 +00001278 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1279 assert(N == 1 && "Invalid number of operands!");
1280 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1281 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1282 }
1283
Tim Northover3b0846e2014-05-24 12:50:23 +00001284 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1285 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001286 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001287 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001288 }
1289
1290 void addSImm7s8Operands(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() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001294 }
1295
1296 void addSImm7s16Operands(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() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001300 }
1301
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001302 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1303 assert(N == 1 && "Invalid number of operands!");
1304 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1305 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1306 }
1307
Tim Northover3b0846e2014-05-24 12:50:23 +00001308 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1309 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001310 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001311 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001312 }
1313
1314 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1315 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001316 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001317 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001318 }
1319
1320 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1321 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001322 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001323 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001324 }
1325
1326 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1327 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001328 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001329 assert(MCE && "Invalid constant immediate operand!");
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_31Operands(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_31Operands(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_32Operands(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_63Operands(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 addImm1_63Operands(MCInst &Inst, unsigned N) const {
1358 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001359 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001360 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001361 }
1362
1363 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1364 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001365 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001366 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001367 }
1368
1369 void addImm0_127Operands(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 addImm0_255Operands(MCInst &Inst, unsigned N) const {
1376 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001377 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001378 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001379 }
1380
1381 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1382 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001383 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001384 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001385 }
1386
1387 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1388 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001389 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001390 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001391 }
1392
1393 void addLogicalImm32Operands(MCInst &Inst, unsigned N) const {
1394 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001395 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +00001396 uint64_t encoding =
1397 AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001398 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001399 }
1400
1401 void addLogicalImm64Operands(MCInst &Inst, unsigned N) const {
1402 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001403 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001404 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001405 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001406 }
1407
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001408 void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
1409 assert(N == 1 && "Invalid number of operands!");
1410 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1411 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
1412 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001413 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001414 }
1415
1416 void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
1417 assert(N == 1 && "Invalid number of operands!");
1418 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1419 uint64_t encoding =
1420 AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001421 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001422 }
1423
Tim Northover3b0846e2014-05-24 12:50:23 +00001424 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1425 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001426 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001427 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001428 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001429 }
1430
1431 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1432 // Branch operands don't encode the low bits, so shift them off
1433 // here. If it's a label, however, just put it on directly as there's
1434 // not enough information now to do anything.
1435 assert(N == 1 && "Invalid number of operands!");
1436 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1437 if (!MCE) {
1438 addExpr(Inst, getImm());
1439 return;
1440 }
1441 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001442 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001443 }
1444
1445 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1446 // Branch operands don't encode the low bits, so shift them off
1447 // here. If it's a label, however, just put it on directly as there's
1448 // not enough information now to do anything.
1449 assert(N == 1 && "Invalid number of operands!");
1450 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1451 if (!MCE) {
1452 addExpr(Inst, getImm());
1453 return;
1454 }
1455 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001456 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001457 }
1458
1459 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1460 // Branch operands don't encode the low bits, so shift them off
1461 // here. If it's a label, however, just put it on directly as there's
1462 // not enough information now to do anything.
1463 assert(N == 1 && "Invalid number of operands!");
1464 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1465 if (!MCE) {
1466 addExpr(Inst, getImm());
1467 return;
1468 }
1469 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001470 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001471 }
1472
1473 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1474 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001475 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001476 }
1477
1478 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1479 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001480 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001481 }
1482
1483 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1484 assert(N == 1 && "Invalid number of operands!");
1485
Jim Grosbache9119e42015-05-13 18:37:00 +00001486 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001487 }
1488
1489 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1490 assert(N == 1 && "Invalid number of operands!");
1491
Jim Grosbache9119e42015-05-13 18:37:00 +00001492 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001493 }
1494
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001495 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1496 assert(N == 1 && "Invalid number of operands!");
1497
1498 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1499 }
1500
1501 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001502 assert(N == 1 && "Invalid number of operands!");
1503
Jim Grosbache9119e42015-05-13 18:37:00 +00001504 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001505 }
1506
1507 void addSysCROperands(MCInst &Inst, unsigned N) const {
1508 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001509 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001510 }
1511
1512 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1513 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001514 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001515 }
1516
Oliver Stannarda34e4702015-12-01 10:48:51 +00001517 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1518 assert(N == 1 && "Invalid number of operands!");
1519 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1520 }
1521
Tim Northover3b0846e2014-05-24 12:50:23 +00001522 void addShifterOperands(MCInst &Inst, unsigned N) const {
1523 assert(N == 1 && "Invalid number of operands!");
1524 unsigned Imm =
1525 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001526 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001527 }
1528
1529 void addExtendOperands(MCInst &Inst, unsigned N) const {
1530 assert(N == 1 && "Invalid number of operands!");
1531 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1532 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1533 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001534 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001535 }
1536
1537 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1538 assert(N == 1 && "Invalid number of operands!");
1539 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1540 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1541 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001542 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001543 }
1544
1545 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1546 assert(N == 2 && "Invalid number of operands!");
1547 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1548 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001549 Inst.addOperand(MCOperand::createImm(IsSigned));
1550 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001551 }
1552
1553 // For 8-bit load/store instructions with a register offset, both the
1554 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1555 // they're disambiguated by whether the shift was explicit or implicit rather
1556 // than its size.
1557 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1558 assert(N == 2 && "Invalid number of operands!");
1559 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1560 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001561 Inst.addOperand(MCOperand::createImm(IsSigned));
1562 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001563 }
1564
1565 template<int Shift>
1566 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1567 assert(N == 1 && "Invalid number of operands!");
1568
1569 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1570 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001571 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001572 }
1573
1574 template<int Shift>
1575 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1576 assert(N == 1 && "Invalid number of operands!");
1577
1578 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1579 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001580 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001581 }
1582
Sam Parker5f934642017-08-31 09:27:04 +00001583 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1584 assert(N == 1 && "Invalid number of operands!");
1585 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1586 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1587 }
1588
1589 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1590 assert(N == 1 && "Invalid number of operands!");
1591 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1592 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1593 }
1594
Tim Northover3b0846e2014-05-24 12:50:23 +00001595 void print(raw_ostream &OS) const override;
1596
David Blaikie960ea3f2014-06-08 16:18:35 +00001597 static std::unique_ptr<AArch64Operand>
1598 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1599 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001600 Op->Tok.Data = Str.data();
1601 Op->Tok.Length = Str.size();
1602 Op->Tok.IsSuffix = IsSuffix;
1603 Op->StartLoc = S;
1604 Op->EndLoc = S;
1605 return Op;
1606 }
1607
David Blaikie960ea3f2014-06-08 16:18:35 +00001608 static std::unique_ptr<AArch64Operand>
Florian Hahnc4422242017-11-07 13:07:50 +00001609 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001610 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001611 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001612 Op->Reg.Kind = Kind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001613 Op->StartLoc = S;
1614 Op->EndLoc = E;
1615 return Op;
1616 }
1617
David Blaikie960ea3f2014-06-08 16:18:35 +00001618 static std::unique_ptr<AArch64Operand>
Florian Hahn91f11e52017-11-07 16:45:48 +00001619 CreateReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1620 SMLoc S, SMLoc E, MCContext &Ctx) {
1621 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1622 Op->Reg.RegNum = RegNum;
1623 Op->Reg.ElementWidth = ElementWidth;
1624 Op->Reg.Kind = Kind;
1625 Op->StartLoc = S;
1626 Op->EndLoc = E;
1627 return Op;
1628 }
1629
1630 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001631 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1632 char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1633 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001634 Op->VectorList.RegNum = RegNum;
1635 Op->VectorList.Count = Count;
1636 Op->VectorList.NumElements = NumElements;
1637 Op->VectorList.ElementKind = ElementKind;
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>
1644 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1645 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001646 Op->VectorIndex.Val = Idx;
1647 Op->StartLoc = S;
1648 Op->EndLoc = E;
1649 return Op;
1650 }
1651
David Blaikie960ea3f2014-06-08 16:18:35 +00001652 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1653 SMLoc E, MCContext &Ctx) {
1654 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001655 Op->Imm.Val = Val;
1656 Op->StartLoc = S;
1657 Op->EndLoc = E;
1658 return Op;
1659 }
1660
David Blaikie960ea3f2014-06-08 16:18:35 +00001661 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1662 unsigned ShiftAmount,
1663 SMLoc S, SMLoc E,
1664 MCContext &Ctx) {
1665 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001666 Op->ShiftedImm .Val = Val;
1667 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1668 Op->StartLoc = S;
1669 Op->EndLoc = E;
1670 return Op;
1671 }
1672
David Blaikie960ea3f2014-06-08 16:18:35 +00001673 static std::unique_ptr<AArch64Operand>
1674 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1675 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001676 Op->CondCode.Code = Code;
1677 Op->StartLoc = S;
1678 Op->EndLoc = E;
1679 return Op;
1680 }
1681
David Blaikie960ea3f2014-06-08 16:18:35 +00001682 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1683 MCContext &Ctx) {
1684 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001685 Op->FPImm.Val = Val;
1686 Op->StartLoc = S;
1687 Op->EndLoc = S;
1688 return Op;
1689 }
1690
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001691 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1692 StringRef Str,
1693 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001694 MCContext &Ctx) {
1695 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001696 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001697 Op->Barrier.Data = Str.data();
1698 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001699 Op->StartLoc = S;
1700 Op->EndLoc = S;
1701 return Op;
1702 }
1703
Tim Northover7cd58932015-01-22 17:23:04 +00001704 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1705 uint32_t MRSReg,
1706 uint32_t MSRReg,
1707 uint32_t PStateField,
1708 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001709 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001710 Op->SysReg.Data = Str.data();
1711 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001712 Op->SysReg.MRSReg = MRSReg;
1713 Op->SysReg.MSRReg = MSRReg;
1714 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001715 Op->StartLoc = S;
1716 Op->EndLoc = S;
1717 return Op;
1718 }
1719
David Blaikie960ea3f2014-06-08 16:18:35 +00001720 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1721 SMLoc E, MCContext &Ctx) {
1722 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001723 Op->SysCRImm.Val = Val;
1724 Op->StartLoc = S;
1725 Op->EndLoc = E;
1726 return Op;
1727 }
1728
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001729 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1730 StringRef Str,
1731 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001732 MCContext &Ctx) {
1733 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001734 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001735 Op->Barrier.Data = Str.data();
1736 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001737 Op->StartLoc = S;
1738 Op->EndLoc = S;
1739 return Op;
1740 }
1741
Oliver Stannarda34e4702015-12-01 10:48:51 +00001742 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1743 StringRef Str,
1744 SMLoc S,
1745 MCContext &Ctx) {
1746 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1747 Op->PSBHint.Val = Val;
1748 Op->PSBHint.Data = Str.data();
1749 Op->PSBHint.Length = Str.size();
1750 Op->StartLoc = S;
1751 Op->EndLoc = S;
1752 return Op;
1753 }
1754
David Blaikie960ea3f2014-06-08 16:18:35 +00001755 static std::unique_ptr<AArch64Operand>
1756 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1757 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1758 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001759 Op->ShiftExtend.Type = ShOp;
1760 Op->ShiftExtend.Amount = Val;
1761 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1762 Op->StartLoc = S;
1763 Op->EndLoc = E;
1764 return Op;
1765 }
1766};
1767
1768} // end anonymous namespace.
1769
1770void AArch64Operand::print(raw_ostream &OS) const {
1771 switch (Kind) {
1772 case k_FPImm:
1773 OS << "<fpimm " << getFPImm() << "("
1774 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1775 break;
1776 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001777 StringRef Name = getBarrierName();
1778 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001779 OS << "<barrier " << Name << ">";
1780 else
1781 OS << "<barrier invalid #" << getBarrier() << ">";
1782 break;
1783 }
1784 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001785 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001786 break;
1787 case k_ShiftedImm: {
1788 unsigned Shift = getShiftedImmShift();
1789 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001790 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001791 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1792 break;
1793 }
1794 case k_CondCode:
1795 OS << "<condcode " << getCondCode() << ">";
1796 break;
1797 case k_Register:
1798 OS << "<register " << getReg() << ">";
1799 break;
1800 case k_VectorList: {
1801 OS << "<vectorlist ";
1802 unsigned Reg = getVectorListStart();
1803 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1804 OS << Reg + i << " ";
1805 OS << ">";
1806 break;
1807 }
1808 case k_VectorIndex:
1809 OS << "<vectorindex " << getVectorIndex() << ">";
1810 break;
1811 case k_SysReg:
1812 OS << "<sysreg: " << getSysReg() << '>';
1813 break;
1814 case k_Token:
1815 OS << "'" << getToken() << "'";
1816 break;
1817 case k_SysCR:
1818 OS << "c" << getSysCR();
1819 break;
1820 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001821 StringRef Name = getPrefetchName();
1822 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001823 OS << "<prfop " << Name << ">";
1824 else
1825 OS << "<prfop invalid #" << getPrefetch() << ">";
1826 break;
1827 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001828 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001829 OS << getPSBHintName();
1830 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001831 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001832 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1833 << getShiftExtendAmount();
1834 if (!hasShiftExtendAmount())
1835 OS << "<imp>";
1836 OS << '>';
1837 break;
1838 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001839}
1840
1841/// @name Auto-generated Match Functions
1842/// {
1843
1844static unsigned MatchRegisterName(StringRef Name);
1845
1846/// }
1847
Florian Hahnc4422242017-11-07 13:07:50 +00001848static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001849 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001850 .Case("v0", AArch64::Q0)
1851 .Case("v1", AArch64::Q1)
1852 .Case("v2", AArch64::Q2)
1853 .Case("v3", AArch64::Q3)
1854 .Case("v4", AArch64::Q4)
1855 .Case("v5", AArch64::Q5)
1856 .Case("v6", AArch64::Q6)
1857 .Case("v7", AArch64::Q7)
1858 .Case("v8", AArch64::Q8)
1859 .Case("v9", AArch64::Q9)
1860 .Case("v10", AArch64::Q10)
1861 .Case("v11", AArch64::Q11)
1862 .Case("v12", AArch64::Q12)
1863 .Case("v13", AArch64::Q13)
1864 .Case("v14", AArch64::Q14)
1865 .Case("v15", AArch64::Q15)
1866 .Case("v16", AArch64::Q16)
1867 .Case("v17", AArch64::Q17)
1868 .Case("v18", AArch64::Q18)
1869 .Case("v19", AArch64::Q19)
1870 .Case("v20", AArch64::Q20)
1871 .Case("v21", AArch64::Q21)
1872 .Case("v22", AArch64::Q22)
1873 .Case("v23", AArch64::Q23)
1874 .Case("v24", AArch64::Q24)
1875 .Case("v25", AArch64::Q25)
1876 .Case("v26", AArch64::Q26)
1877 .Case("v27", AArch64::Q27)
1878 .Case("v28", AArch64::Q28)
1879 .Case("v29", AArch64::Q29)
1880 .Case("v30", AArch64::Q30)
1881 .Case("v31", AArch64::Q31)
1882 .Default(0);
1883}
1884
1885static bool isValidVectorKind(StringRef Name) {
1886 return StringSwitch<bool>(Name.lower())
1887 .Case(".8b", true)
1888 .Case(".16b", true)
1889 .Case(".4h", true)
1890 .Case(".8h", true)
1891 .Case(".2s", true)
1892 .Case(".4s", true)
1893 .Case(".1d", true)
1894 .Case(".2d", true)
1895 .Case(".1q", true)
1896 // Accept the width neutral ones, too, for verbose syntax. If those
1897 // aren't used in the right places, the token operand won't match so
1898 // all will work out.
1899 .Case(".b", true)
1900 .Case(".h", true)
1901 .Case(".s", true)
1902 .Case(".d", true)
Oliver Stannarde4c3d212015-12-08 12:16:10 +00001903 // Needed for fp16 scalar pairwise reductions
1904 .Case(".2h", true)
Sjoerd Meijer79876332017-08-09 14:59:54 +00001905 // another special case for the ARMv8.2a dot product operand
1906 .Case(".4b", true)
Tim Northover3b0846e2014-05-24 12:50:23 +00001907 .Default(false);
1908}
1909
Florian Hahn91f11e52017-11-07 16:45:48 +00001910static unsigned matchSVEDataVectorRegName(StringRef Name) {
1911 return StringSwitch<unsigned>(Name.lower())
1912 .Case("z0", AArch64::Z0)
1913 .Case("z1", AArch64::Z1)
1914 .Case("z2", AArch64::Z2)
1915 .Case("z3", AArch64::Z3)
1916 .Case("z4", AArch64::Z4)
1917 .Case("z5", AArch64::Z5)
1918 .Case("z6", AArch64::Z6)
1919 .Case("z7", AArch64::Z7)
1920 .Case("z8", AArch64::Z8)
1921 .Case("z9", AArch64::Z9)
1922 .Case("z10", AArch64::Z10)
1923 .Case("z11", AArch64::Z11)
1924 .Case("z12", AArch64::Z12)
1925 .Case("z13", AArch64::Z13)
1926 .Case("z14", AArch64::Z14)
1927 .Case("z15", AArch64::Z15)
1928 .Case("z16", AArch64::Z16)
1929 .Case("z17", AArch64::Z17)
1930 .Case("z18", AArch64::Z18)
1931 .Case("z19", AArch64::Z19)
1932 .Case("z20", AArch64::Z20)
1933 .Case("z21", AArch64::Z21)
1934 .Case("z22", AArch64::Z22)
1935 .Case("z23", AArch64::Z23)
1936 .Case("z24", AArch64::Z24)
1937 .Case("z25", AArch64::Z25)
1938 .Case("z26", AArch64::Z26)
1939 .Case("z27", AArch64::Z27)
1940 .Case("z28", AArch64::Z28)
1941 .Case("z29", AArch64::Z29)
1942 .Case("z30", AArch64::Z30)
1943 .Case("z31", AArch64::Z31)
1944 .Default(0);
1945}
1946
Sander de Smalen2b6338b2017-11-29 14:34:18 +00001947static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1948 return StringSwitch<unsigned>(Name.lower())
1949 .Case("p0", AArch64::P0)
1950 .Case("p1", AArch64::P1)
1951 .Case("p2", AArch64::P2)
1952 .Case("p3", AArch64::P3)
1953 .Case("p4", AArch64::P4)
1954 .Case("p5", AArch64::P5)
1955 .Case("p6", AArch64::P6)
1956 .Case("p7", AArch64::P7)
1957 .Case("p8", AArch64::P8)
1958 .Case("p9", AArch64::P9)
1959 .Case("p10", AArch64::P10)
1960 .Case("p11", AArch64::P11)
1961 .Case("p12", AArch64::P12)
1962 .Case("p13", AArch64::P13)
1963 .Case("p14", AArch64::P14)
1964 .Case("p15", AArch64::P15)
1965 .Default(0);
1966}
1967
Florian Hahn91f11e52017-11-07 16:45:48 +00001968static bool isValidSVEKind(StringRef Name) {
1969 return StringSwitch<bool>(Name.lower())
1970 .Case(".b", true)
1971 .Case(".h", true)
1972 .Case(".s", true)
1973 .Case(".d", true)
1974 .Case(".q", true)
1975 .Default(false);
1976}
1977
Sander de Smalen2b6338b2017-11-29 14:34:18 +00001978static bool isSVERegister(StringRef Name) {
1979 return Name[0] == 'z' || Name[0] == 'p';
Florian Hahn91f11e52017-11-07 16:45:48 +00001980}
1981
Tim Northover3b0846e2014-05-24 12:50:23 +00001982static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1983 char &ElementKind) {
1984 assert(isValidVectorKind(Name));
1985
1986 ElementKind = Name.lower()[Name.size() - 1];
1987 NumElements = 0;
1988
1989 if (Name.size() == 2)
1990 return;
1991
1992 // Parse the lane count
1993 Name = Name.drop_front();
1994 while (isdigit(Name.front())) {
1995 NumElements = 10 * NumElements + (Name.front() - '0');
1996 Name = Name.drop_front();
1997 }
1998}
1999
2000bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2001 SMLoc &EndLoc) {
2002 StartLoc = getLoc();
2003 RegNo = tryParseRegister();
2004 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2005 return (RegNo == (unsigned)-1);
2006}
2007
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002008// Matches a register name or register alias previously defined by '.req'
2009unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002010 RegKind Kind) {
2011 unsigned RegNum;
2012 switch (Kind) {
2013 case RegKind::Scalar:
2014 RegNum = MatchRegisterName(Name);
2015 break;
2016 case RegKind::NeonVector:
2017 RegNum = MatchNeonVectorRegName(Name);
2018 break;
Florian Hahn91f11e52017-11-07 16:45:48 +00002019 case RegKind::SVEDataVector:
2020 RegNum = matchSVEDataVectorRegName(Name);
2021 break;
Sander de Smalen2b6338b2017-11-29 14:34:18 +00002022 case RegKind::SVEPredicateVector:
2023 RegNum = matchSVEPredicateVectorRegName(Name);
2024 break;
Florian Hahnc4422242017-11-07 13:07:50 +00002025 }
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002026
Florian Hahnc4422242017-11-07 13:07:50 +00002027 if (!RegNum) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002028 // Check for aliases registered via .req. Canonicalize to lower case.
2029 // That's more consistent since register names are case insensitive, and
2030 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2031 auto Entry = RegisterReqs.find(Name.lower());
2032 if (Entry == RegisterReqs.end())
2033 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002034
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002035 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002036 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002037 RegNum = Entry->getValue().second;
2038 }
2039 return RegNum;
2040}
2041
Tim Northover3b0846e2014-05-24 12:50:23 +00002042/// tryParseRegister - Try to parse a register name. The token must be an
2043/// Identifier when called, and if it is a register name the token is eaten and
2044/// the register is added to the operand list.
2045int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002046 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002047 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002048 if (Tok.isNot(AsmToken::Identifier))
2049 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00002050
2051 std::string lowerCase = Tok.getString().lower();
Sander de Smalen2b6338b2017-11-29 14:34:18 +00002052 if (isSVERegister(lowerCase))
Florian Hahn91f11e52017-11-07 16:45:48 +00002053 return -1;
2054
Florian Hahnc4422242017-11-07 13:07:50 +00002055 unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00002056 // Also handle a few aliases of registers.
2057 if (RegNum == 0)
2058 RegNum = StringSwitch<unsigned>(lowerCase)
2059 .Case("fp", AArch64::FP)
2060 .Case("lr", AArch64::LR)
2061 .Case("x31", AArch64::XZR)
2062 .Case("w31", AArch64::WZR)
2063 .Default(0);
2064
2065 if (RegNum == 0)
2066 return -1;
2067
2068 Parser.Lex(); // Eat identifier token.
2069 return RegNum;
2070}
2071
2072/// tryMatchVectorRegister - Try to parse a vector register name with optional
2073/// kind specifier. If it is a register specifier, eat the token and return it.
2074int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002075 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002076 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2077 TokError("vector register expected");
2078 return -1;
2079 }
2080
2081 StringRef Name = Parser.getTok().getString();
2082 // If there is a kind specifier, it's separated from the register name by
2083 // a '.'.
2084 size_t Start = 0, Next = Name.find('.');
2085 StringRef Head = Name.slice(Start, Next);
Florian Hahnc4422242017-11-07 13:07:50 +00002086 unsigned RegNum = matchRegisterNameAlias(Head, RegKind::NeonVector);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002087
Tim Northover3b0846e2014-05-24 12:50:23 +00002088 if (RegNum) {
2089 if (Next != StringRef::npos) {
2090 Kind = Name.slice(Next, StringRef::npos);
2091 if (!isValidVectorKind(Kind)) {
2092 TokError("invalid vector kind qualifier");
2093 return -1;
2094 }
2095 }
2096 Parser.Lex(); // Eat the register token.
2097 return RegNum;
2098 }
2099
2100 if (expected)
2101 TokError("vector register expected");
2102 return -1;
2103}
2104
2105/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002106OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002107AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002108 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002109 SMLoc S = getLoc();
2110
2111 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2112 Error(S, "Expected cN operand where 0 <= N <= 15");
2113 return MatchOperand_ParseFail;
2114 }
2115
2116 StringRef Tok = Parser.getTok().getIdentifier();
2117 if (Tok[0] != 'c' && Tok[0] != 'C') {
2118 Error(S, "Expected cN operand where 0 <= N <= 15");
2119 return MatchOperand_ParseFail;
2120 }
2121
2122 uint32_t CRNum;
2123 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2124 if (BadNum || CRNum > 15) {
2125 Error(S, "Expected cN operand where 0 <= N <= 15");
2126 return MatchOperand_ParseFail;
2127 }
2128
2129 Parser.Lex(); // Eat identifier token.
2130 Operands.push_back(
2131 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2132 return MatchOperand_Success;
2133}
2134
2135/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002136OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002137AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002138 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002139 SMLoc S = getLoc();
2140 const AsmToken &Tok = Parser.getTok();
2141 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002142 // Eat optional hash.
2143 if (parseOptionalToken(AsmToken::Hash) ||
2144 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002145 const MCExpr *ImmVal;
2146 if (getParser().parseExpression(ImmVal))
2147 return MatchOperand_ParseFail;
2148
2149 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2150 if (!MCE) {
2151 TokError("immediate value expected for prefetch operand");
2152 return MatchOperand_ParseFail;
2153 }
2154 unsigned prfop = MCE->getValue();
2155 if (prfop > 31) {
2156 TokError("prefetch operand out of range, [0,31] expected");
2157 return MatchOperand_ParseFail;
2158 }
2159
Tim Northovere6ae6762016-07-05 21:23:04 +00002160 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2161 Operands.push_back(AArch64Operand::CreatePrefetch(
2162 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002163 return MatchOperand_Success;
2164 }
2165
2166 if (Tok.isNot(AsmToken::Identifier)) {
2167 TokError("pre-fetch hint expected");
2168 return MatchOperand_ParseFail;
2169 }
2170
Tim Northovere6ae6762016-07-05 21:23:04 +00002171 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2172 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002173 TokError("pre-fetch hint expected");
2174 return MatchOperand_ParseFail;
2175 }
2176
2177 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002178 Operands.push_back(AArch64Operand::CreatePrefetch(
2179 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002180 return MatchOperand_Success;
2181}
2182
Oliver Stannarda34e4702015-12-01 10:48:51 +00002183/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002184OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002185AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2186 MCAsmParser &Parser = getParser();
2187 SMLoc S = getLoc();
2188 const AsmToken &Tok = Parser.getTok();
2189 if (Tok.isNot(AsmToken::Identifier)) {
2190 TokError("invalid operand for instruction");
2191 return MatchOperand_ParseFail;
2192 }
2193
Tim Northovere6ae6762016-07-05 21:23:04 +00002194 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2195 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002196 TokError("invalid operand for instruction");
2197 return MatchOperand_ParseFail;
2198 }
2199
2200 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002201 Operands.push_back(AArch64Operand::CreatePSBHint(
2202 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002203 return MatchOperand_Success;
2204}
2205
Tim Northover3b0846e2014-05-24 12:50:23 +00002206/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2207/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002208OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002209AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002210 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002211 SMLoc S = getLoc();
2212 const MCExpr *Expr;
2213
2214 if (Parser.getTok().is(AsmToken::Hash)) {
2215 Parser.Lex(); // Eat hash token.
2216 }
2217
2218 if (parseSymbolicImmVal(Expr))
2219 return MatchOperand_ParseFail;
2220
2221 AArch64MCExpr::VariantKind ELFRefKind;
2222 MCSymbolRefExpr::VariantKind DarwinRefKind;
2223 int64_t Addend;
2224 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2225 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2226 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2227 // No modifier was specified at all; this is the syntax for an ELF basic
2228 // ADRP relocation (unfortunately).
2229 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002230 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002231 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2232 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2233 Addend != 0) {
2234 Error(S, "gotpage label reference not allowed an addend");
2235 return MatchOperand_ParseFail;
2236 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2237 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2238 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2239 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2240 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2241 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2242 // The operand must be an @page or @gotpage qualified symbolref.
2243 Error(S, "page or gotpage label reference expected");
2244 return MatchOperand_ParseFail;
2245 }
2246 }
2247
2248 // We have either a label reference possibly with addend or an immediate. The
2249 // addend is a raw value here. The linker will adjust it to only reference the
2250 // page.
2251 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2252 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2253
2254 return MatchOperand_Success;
2255}
2256
2257/// tryParseAdrLabel - Parse and validate a source label for the ADR
2258/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002259OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002260AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2261 SMLoc S = getLoc();
2262 const MCExpr *Expr;
2263
Nirav Davee833c6c2016-11-08 18:31:04 +00002264 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002265 if (getParser().parseExpression(Expr))
2266 return MatchOperand_ParseFail;
2267
2268 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2269 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2270
2271 return MatchOperand_Success;
2272}
2273
2274/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002275OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002276AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002277 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002278 SMLoc S = getLoc();
2279
Nirav Davee833c6c2016-11-08 18:31:04 +00002280 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002281
2282 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002283 bool isNegative = parseOptionalToken(AsmToken::Minus);
2284
Tim Northover3b0846e2014-05-24 12:50:23 +00002285 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002286 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002287 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002288 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002289 Val = Tok.getIntVal();
2290 if (Val > 255 || Val < 0) {
2291 TokError("encoded floating point value out of range");
2292 return MatchOperand_ParseFail;
2293 }
2294 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002295 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002296 if (isNegative)
2297 RealVal.changeSign();
2298
Tim Northover3b0846e2014-05-24 12:50:23 +00002299 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002300 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002301
John Brawn5ca5daa2017-04-20 10:13:54 +00002302 // Check for out of range values. As an exception we let Zero through,
2303 // but as tokens instead of an FPImm so that it can be matched by the
2304 // appropriate alias if one exists.
2305 if (RealVal.isPosZero()) {
2306 Parser.Lex(); // Eat the token.
2307 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2308 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2309 return MatchOperand_Success;
2310 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002311 TokError("expected compatible register or floating-point constant");
2312 return MatchOperand_ParseFail;
2313 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002314 }
2315 Parser.Lex(); // Eat the token.
2316 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2317 return MatchOperand_Success;
2318 }
2319
2320 if (!Hash)
2321 return MatchOperand_NoMatch;
2322
2323 TokError("invalid floating point immediate");
2324 return MatchOperand_ParseFail;
2325}
2326
2327/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002328OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002329AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002330 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002331 SMLoc S = getLoc();
2332
2333 if (Parser.getTok().is(AsmToken::Hash))
2334 Parser.Lex(); // Eat '#'
2335 else if (Parser.getTok().isNot(AsmToken::Integer))
2336 // Operand should start from # or should be integer, emit error otherwise.
2337 return MatchOperand_NoMatch;
2338
2339 const MCExpr *Imm;
2340 if (parseSymbolicImmVal(Imm))
2341 return MatchOperand_ParseFail;
2342 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2343 uint64_t ShiftAmount = 0;
2344 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2345 if (MCE) {
2346 int64_t Val = MCE->getValue();
2347 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002348 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002349 ShiftAmount = 12;
2350 }
2351 }
2352 SMLoc E = Parser.getTok().getLoc();
2353 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2354 getContext()));
2355 return MatchOperand_Success;
2356 }
2357
2358 // Eat ','
2359 Parser.Lex();
2360
2361 // The optional operand must be "lsl #N" where N is non-negative.
2362 if (!Parser.getTok().is(AsmToken::Identifier) ||
2363 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2364 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2365 return MatchOperand_ParseFail;
2366 }
2367
2368 // Eat 'lsl'
2369 Parser.Lex();
2370
Nirav Davee833c6c2016-11-08 18:31:04 +00002371 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002372
2373 if (Parser.getTok().isNot(AsmToken::Integer)) {
2374 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2375 return MatchOperand_ParseFail;
2376 }
2377
2378 int64_t ShiftAmount = Parser.getTok().getIntVal();
2379
2380 if (ShiftAmount < 0) {
2381 Error(Parser.getTok().getLoc(), "positive shift amount required");
2382 return MatchOperand_ParseFail;
2383 }
2384 Parser.Lex(); // Eat the number
2385
2386 SMLoc E = Parser.getTok().getLoc();
2387 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2388 S, E, getContext()));
2389 return MatchOperand_Success;
2390}
2391
2392/// parseCondCodeString - Parse a Condition Code string.
2393AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2394 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2395 .Case("eq", AArch64CC::EQ)
2396 .Case("ne", AArch64CC::NE)
2397 .Case("cs", AArch64CC::HS)
2398 .Case("hs", AArch64CC::HS)
2399 .Case("cc", AArch64CC::LO)
2400 .Case("lo", AArch64CC::LO)
2401 .Case("mi", AArch64CC::MI)
2402 .Case("pl", AArch64CC::PL)
2403 .Case("vs", AArch64CC::VS)
2404 .Case("vc", AArch64CC::VC)
2405 .Case("hi", AArch64CC::HI)
2406 .Case("ls", AArch64CC::LS)
2407 .Case("ge", AArch64CC::GE)
2408 .Case("lt", AArch64CC::LT)
2409 .Case("gt", AArch64CC::GT)
2410 .Case("le", AArch64CC::LE)
2411 .Case("al", AArch64CC::AL)
2412 .Case("nv", AArch64CC::NV)
2413 .Default(AArch64CC::Invalid);
2414 return CC;
2415}
2416
2417/// parseCondCode - Parse a Condition Code operand.
2418bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2419 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002420 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002421 SMLoc S = getLoc();
2422 const AsmToken &Tok = Parser.getTok();
2423 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2424
2425 StringRef Cond = Tok.getString();
2426 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2427 if (CC == AArch64CC::Invalid)
2428 return TokError("invalid condition code");
2429 Parser.Lex(); // Eat identifier token.
2430
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002431 if (invertCondCode) {
2432 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2433 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002434 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002435 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002436
2437 Operands.push_back(
2438 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2439 return false;
2440}
2441
2442/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2443/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002444OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002445AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002446 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002447 const AsmToken &Tok = Parser.getTok();
2448 std::string LowerID = Tok.getString().lower();
2449 AArch64_AM::ShiftExtendType ShOp =
2450 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2451 .Case("lsl", AArch64_AM::LSL)
2452 .Case("lsr", AArch64_AM::LSR)
2453 .Case("asr", AArch64_AM::ASR)
2454 .Case("ror", AArch64_AM::ROR)
2455 .Case("msl", AArch64_AM::MSL)
2456 .Case("uxtb", AArch64_AM::UXTB)
2457 .Case("uxth", AArch64_AM::UXTH)
2458 .Case("uxtw", AArch64_AM::UXTW)
2459 .Case("uxtx", AArch64_AM::UXTX)
2460 .Case("sxtb", AArch64_AM::SXTB)
2461 .Case("sxth", AArch64_AM::SXTH)
2462 .Case("sxtw", AArch64_AM::SXTW)
2463 .Case("sxtx", AArch64_AM::SXTX)
2464 .Default(AArch64_AM::InvalidShiftExtend);
2465
2466 if (ShOp == AArch64_AM::InvalidShiftExtend)
2467 return MatchOperand_NoMatch;
2468
2469 SMLoc S = Tok.getLoc();
2470 Parser.Lex();
2471
Nirav Davee833c6c2016-11-08 18:31:04 +00002472 bool Hash = parseOptionalToken(AsmToken::Hash);
2473
Tim Northover3b0846e2014-05-24 12:50:23 +00002474 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2475 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2476 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2477 ShOp == AArch64_AM::MSL) {
2478 // We expect a number here.
2479 TokError("expected #imm after shift specifier");
2480 return MatchOperand_ParseFail;
2481 }
2482
Chad Rosier2ff37b82016-12-27 16:58:09 +00002483 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002484 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2485 Operands.push_back(
2486 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2487 return MatchOperand_Success;
2488 }
2489
Chad Rosier2ff37b82016-12-27 16:58:09 +00002490 // Make sure we do actually have a number, identifier or a parenthesized
2491 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002492 SMLoc E = Parser.getTok().getLoc();
2493 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002494 !Parser.getTok().is(AsmToken::LParen) &&
2495 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002496 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002497 return MatchOperand_ParseFail;
2498 }
2499
2500 const MCExpr *ImmVal;
2501 if (getParser().parseExpression(ImmVal))
2502 return MatchOperand_ParseFail;
2503
2504 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2505 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002506 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002507 return MatchOperand_ParseFail;
2508 }
2509
Jim Grosbach57fd2622014-09-23 22:16:02 +00002510 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002511 Operands.push_back(AArch64Operand::CreateShiftExtend(
2512 ShOp, MCE->getValue(), true, S, E, getContext()));
2513 return MatchOperand_Success;
2514}
2515
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002516static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2517 if (FBS[AArch64::HasV8_1aOps])
2518 Str += "ARMv8.1a";
2519 else if (FBS[AArch64::HasV8_2aOps])
2520 Str += "ARMv8.2a";
2521 else
2522 Str += "(unknown)";
2523}
2524
2525void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2526 SMLoc S) {
2527 const uint16_t Op2 = Encoding & 7;
2528 const uint16_t Cm = (Encoding & 0x78) >> 3;
2529 const uint16_t Cn = (Encoding & 0x780) >> 7;
2530 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2531
2532 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2533
2534 Operands.push_back(
2535 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2536 Operands.push_back(
2537 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2538 Operands.push_back(
2539 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2540 Expr = MCConstantExpr::create(Op2, getContext());
2541 Operands.push_back(
2542 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2543}
2544
Tim Northover3b0846e2014-05-24 12:50:23 +00002545/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2546/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2547bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2548 OperandVector &Operands) {
2549 if (Name.find('.') != StringRef::npos)
2550 return TokError("invalid operand");
2551
2552 Mnemonic = Name;
2553 Operands.push_back(
2554 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2555
Rafael Espindola961d4692014-11-11 05:18:41 +00002556 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002557 const AsmToken &Tok = Parser.getTok();
2558 StringRef Op = Tok.getString();
2559 SMLoc S = Tok.getLoc();
2560
Tim Northover3b0846e2014-05-24 12:50:23 +00002561 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002562 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2563 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002564 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002565 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2566 std::string Str("IC " + std::string(IC->Name) + " requires ");
2567 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2568 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002569 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002570 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002571 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002572 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2573 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002574 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002575 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2576 std::string Str("DC " + std::string(DC->Name) + " requires ");
2577 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2578 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002579 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002580 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002581 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002582 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2583 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002584 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002585 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2586 std::string Str("AT " + std::string(AT->Name) + " requires ");
2587 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2588 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002589 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002590 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002591 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002592 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2593 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002594 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002595 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2596 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2597 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2598 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002599 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002600 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002601 }
2602
Tim Northover3b0846e2014-05-24 12:50:23 +00002603 Parser.Lex(); // Eat operand.
2604
2605 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2606 bool HasRegister = false;
2607
2608 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002609 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002610 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2611 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002612 HasRegister = true;
2613 }
2614
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002615 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002616 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002617 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002618 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002619
Nirav Davee833c6c2016-11-08 18:31:04 +00002620 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2621 return true;
2622
Tim Northover3b0846e2014-05-24 12:50:23 +00002623 return false;
2624}
2625
Alex Bradbury58eba092016-11-01 16:32:05 +00002626OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002627AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002628 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002629 const AsmToken &Tok = Parser.getTok();
2630
2631 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002632 if (parseOptionalToken(AsmToken::Hash) ||
2633 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002634 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002635 const MCExpr *ImmVal;
2636 SMLoc ExprLoc = getLoc();
2637 if (getParser().parseExpression(ImmVal))
2638 return MatchOperand_ParseFail;
2639 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2640 if (!MCE) {
2641 Error(ExprLoc, "immediate value expected for barrier operand");
2642 return MatchOperand_ParseFail;
2643 }
2644 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2645 Error(ExprLoc, "barrier operand out of range");
2646 return MatchOperand_ParseFail;
2647 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002648 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2649 Operands.push_back(AArch64Operand::CreateBarrier(
2650 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002651 return MatchOperand_Success;
2652 }
2653
2654 if (Tok.isNot(AsmToken::Identifier)) {
2655 TokError("invalid operand for instruction");
2656 return MatchOperand_ParseFail;
2657 }
2658
Tim Northover3b0846e2014-05-24 12:50:23 +00002659 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002660 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2661 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002662 TokError("'sy' or #imm operand expected");
2663 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002664 } else if (!DB) {
2665 TokError("invalid barrier option name");
2666 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002667 }
2668
Tim Northovere6ae6762016-07-05 21:23:04 +00002669 Operands.push_back(AArch64Operand::CreateBarrier(
2670 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002671 Parser.Lex(); // Consume the option
2672
2673 return MatchOperand_Success;
2674}
2675
Alex Bradbury58eba092016-11-01 16:32:05 +00002676OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002677AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002678 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002679 const AsmToken &Tok = Parser.getTok();
2680
2681 if (Tok.isNot(AsmToken::Identifier))
2682 return MatchOperand_NoMatch;
2683
Tim Northovere6ae6762016-07-05 21:23:04 +00002684 int MRSReg, MSRReg;
2685 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2686 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2687 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2688 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2689 } else
2690 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002691
Tim Northovere6ae6762016-07-05 21:23:04 +00002692 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2693 unsigned PStateImm = -1;
2694 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2695 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002696
Tim Northovere6ae6762016-07-05 21:23:04 +00002697 Operands.push_back(
2698 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2699 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002700 Parser.Lex(); // Eat identifier
2701
2702 return MatchOperand_Success;
2703}
2704
Florian Hahnc4422242017-11-07 13:07:50 +00002705/// tryParseNeonVectorRegister - Parse a vector register operand.
2706bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002707 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002708 if (Parser.getTok().isNot(AsmToken::Identifier))
2709 return true;
2710
2711 SMLoc S = getLoc();
2712 // Check for a vector register specifier first.
2713 StringRef Kind;
2714 int64_t Reg = tryMatchVectorRegister(Kind, false);
2715 if (Reg == -1)
2716 return true;
2717 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00002718 AArch64Operand::CreateReg(Reg, RegKind::NeonVector, S, getLoc(),
2719 getContext()));
2720
Tim Northover3b0846e2014-05-24 12:50:23 +00002721 // If there was an explicit qualifier, that goes on as a literal text
2722 // operand.
2723 if (!Kind.empty())
2724 Operands.push_back(
2725 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2726
2727 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002728 SMLoc SIdx = getLoc();
2729 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002730 const MCExpr *ImmVal;
2731 if (getParser().parseExpression(ImmVal))
2732 return false;
2733 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2734 if (!MCE) {
2735 TokError("immediate value expected for vector index");
2736 return false;
2737 }
2738
2739 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002740
Nirav Davee833c6c2016-11-08 18:31:04 +00002741 if (parseToken(AsmToken::RBrac, "']' expected"))
2742 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002743
2744 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2745 E, getContext()));
2746 }
2747
2748 return false;
2749}
2750
Florian Hahn91f11e52017-11-07 16:45:48 +00002751// tryParseSVEDataVectorRegister - Try to parse a SVE vector register name with
2752// optional kind specifier. If it is a register specifier, eat the token
2753// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002754OperandMatchResultTy
2755AArch64AsmParser::tryParseSVERegister(int &Reg, StringRef &Kind,
2756 RegKind MatchKind) {
2757 MCAsmParser &Parser = getParser();
2758 const AsmToken &Tok = Parser.getTok();
2759
Florian Hahn91f11e52017-11-07 16:45:48 +00002760 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002761 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002762
2763 StringRef Name = Tok.getString();
2764 // If there is a kind specifier, it's separated from the register name by
2765 // a '.'.
2766 size_t Start = 0, Next = Name.find('.');
2767 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002768 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002769
2770 if (RegNum) {
2771 if (Next != StringRef::npos) {
2772 Kind = Name.slice(Next, StringRef::npos);
2773 if (!isValidSVEKind(Kind)) {
2774 TokError("invalid sve vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002775 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002776 }
2777 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002778 Parser.Lex(); // Eat the register token.
2779
2780 Reg = RegNum;
2781 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002782 }
2783
Sander de Smalen8e607342017-11-15 15:44:43 +00002784 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002785}
2786
Sander de Smalen2b6338b2017-11-29 14:34:18 +00002787/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2788OperandMatchResultTy
2789AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2790 // Check for a SVE predicate register specifier first.
2791 const SMLoc S = getLoc();
2792 StringRef Kind;
2793 int RegNum = -1;
2794 auto Res = tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
2795 if (Res != MatchOperand_Success)
2796 return Res;
2797
2798 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
2799 .Case("", -1)
2800 .Case(".b", 8)
2801 .Case(".h", 16)
2802 .Case(".s", 32)
2803 .Case(".d", 64)
2804 .Case(".q", 128)
2805 .Default(0);
2806
2807 if (!ElementWidth)
2808 return MatchOperand_NoMatch;
2809
2810 Operands.push_back(
2811 AArch64Operand::CreateReg(RegNum, RegKind::SVEPredicateVector,
2812 ElementWidth, S, getLoc(), getContext()));
2813
2814 return MatchOperand_Success;
2815}
2816
Tim Northover3b0846e2014-05-24 12:50:23 +00002817/// parseRegister - Parse a non-vector register operand.
2818bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2819 SMLoc S = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00002820 // Try for a vector (neon) register.
2821 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002822 return false;
2823
2824 // Try for a scalar register.
2825 int64_t Reg = tryParseRegister();
2826 if (Reg == -1)
2827 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002828 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2829 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002830
Tim Northover3b0846e2014-05-24 12:50:23 +00002831 return false;
2832}
2833
2834bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002835 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002836 bool HasELFModifier = false;
2837 AArch64MCExpr::VariantKind RefKind;
2838
Nirav Davee833c6c2016-11-08 18:31:04 +00002839 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002840 HasELFModifier = true;
2841
Nirav Davee833c6c2016-11-08 18:31:04 +00002842 if (Parser.getTok().isNot(AsmToken::Identifier))
2843 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002844
2845 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2846 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2847 .Case("lo12", AArch64MCExpr::VK_LO12)
2848 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2849 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2850 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2851 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2852 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2853 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2854 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2855 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2856 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2857 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2858 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2859 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2860 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2861 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2862 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2863 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2864 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2865 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2866 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2867 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2868 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2869 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2870 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2871 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2872 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2873 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2874 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2875 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2876 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2877 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2878 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2879 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2880 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2881 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2882 .Default(AArch64MCExpr::VK_INVALID);
2883
Nirav Davee833c6c2016-11-08 18:31:04 +00002884 if (RefKind == AArch64MCExpr::VK_INVALID)
2885 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002886
2887 Parser.Lex(); // Eat identifier
2888
Nirav Davee833c6c2016-11-08 18:31:04 +00002889 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002890 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002891 }
2892
2893 if (getParser().parseExpression(ImmVal))
2894 return true;
2895
2896 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002897 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002898
2899 return false;
2900}
2901
2902/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2903bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002904 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002905 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2906 SMLoc S = getLoc();
2907 Parser.Lex(); // Eat left bracket token.
2908 StringRef Kind;
2909 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2910 if (FirstReg == -1)
2911 return true;
2912 int64_t PrevReg = FirstReg;
2913 unsigned Count = 1;
2914
Nirav Davee833c6c2016-11-08 18:31:04 +00002915 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002916 SMLoc Loc = getLoc();
2917 StringRef NextKind;
2918 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2919 if (Reg == -1)
2920 return true;
2921 // Any Kind suffices must match on all regs in the list.
2922 if (Kind != NextKind)
2923 return Error(Loc, "mismatched register size suffix");
2924
2925 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2926
2927 if (Space == 0 || Space > 3) {
2928 return Error(Loc, "invalid number of vectors");
2929 }
2930
2931 Count += Space;
2932 }
2933 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002934 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002935 SMLoc Loc = getLoc();
2936 StringRef NextKind;
2937 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2938 if (Reg == -1)
2939 return true;
2940 // Any Kind suffices must match on all regs in the list.
2941 if (Kind != NextKind)
2942 return Error(Loc, "mismatched register size suffix");
2943
2944 // Registers must be incremental (with wraparound at 31)
2945 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2946 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2947 return Error(Loc, "registers must be sequential");
2948
2949 PrevReg = Reg;
2950 ++Count;
2951 }
2952 }
2953
Nirav Davee833c6c2016-11-08 18:31:04 +00002954 if (parseToken(AsmToken::RCurly, "'}' expected"))
2955 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002956
2957 if (Count > 4)
2958 return Error(S, "invalid number of vectors");
2959
2960 unsigned NumElements = 0;
2961 char ElementKind = 0;
2962 if (!Kind.empty())
2963 parseValidVectorKind(Kind, NumElements, ElementKind);
2964
2965 Operands.push_back(AArch64Operand::CreateVectorList(
2966 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
2967
2968 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002969 SMLoc SIdx = getLoc();
2970 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002971 const MCExpr *ImmVal;
2972 if (getParser().parseExpression(ImmVal))
2973 return false;
2974 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2975 if (!MCE) {
2976 TokError("immediate value expected for vector index");
2977 return false;
2978 }
2979
2980 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002981 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002982 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002983
2984 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2985 E, getContext()));
2986 }
2987 return false;
2988}
2989
Alex Bradbury58eba092016-11-01 16:32:05 +00002990OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002991AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002992 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002993 const AsmToken &Tok = Parser.getTok();
2994 if (!Tok.is(AsmToken::Identifier))
2995 return MatchOperand_NoMatch;
2996
Florian Hahnc4422242017-11-07 13:07:50 +00002997 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00002998
2999 MCContext &Ctx = getContext();
3000 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
3001 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
3002 return MatchOperand_NoMatch;
3003
3004 SMLoc S = getLoc();
3005 Parser.Lex(); // Eat register
3006
Nirav Davee833c6c2016-11-08 18:31:04 +00003007 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003008 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003009 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003010 return MatchOperand_Success;
3011 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003012
Nirav Davee833c6c2016-11-08 18:31:04 +00003013 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003014
3015 if (Parser.getTok().isNot(AsmToken::Integer)) {
3016 Error(getLoc(), "index must be absent or #0");
3017 return MatchOperand_ParseFail;
3018 }
3019
3020 const MCExpr *ImmVal;
3021 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3022 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3023 Error(getLoc(), "index must be absent or #0");
3024 return MatchOperand_ParseFail;
3025 }
3026
3027 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003028 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003029 return MatchOperand_Success;
3030}
3031
3032/// parseOperand - Parse a arm instruction operand. For now this parses the
3033/// operand regardless of the mnemonic.
3034bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3035 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003036 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003037 // Check if the current operand has a custom associated parser, if so, try to
3038 // custom parse the operand, or fallback to the general approach.
3039 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3040 if (ResTy == MatchOperand_Success)
3041 return false;
3042 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3043 // there was a match, but an error occurred, in which case, just return that
3044 // the operand parsing failed.
3045 if (ResTy == MatchOperand_ParseFail)
3046 return true;
3047
3048 // Nothing custom, so do general case parsing.
3049 SMLoc S, E;
3050 switch (getLexer().getKind()) {
3051 default: {
3052 SMLoc S = getLoc();
3053 const MCExpr *Expr;
3054 if (parseSymbolicImmVal(Expr))
3055 return Error(S, "invalid operand");
3056
3057 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3058 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3059 return false;
3060 }
3061 case AsmToken::LBrac: {
3062 SMLoc Loc = Parser.getTok().getLoc();
3063 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3064 getContext()));
3065 Parser.Lex(); // Eat '['
3066
3067 // There's no comma after a '[', so we can parse the next operand
3068 // immediately.
3069 return parseOperand(Operands, false, false);
3070 }
3071 case AsmToken::LCurly:
3072 return parseVectorList(Operands);
3073 case AsmToken::Identifier: {
3074 // If we're expecting a Condition Code operand, then just parse that.
3075 if (isCondCode)
3076 return parseCondCode(Operands, invertCondCode);
3077
3078 // If it's a register name, parse it.
3079 if (!parseRegister(Operands))
3080 return false;
3081
3082 // This could be an optional "shift" or "extend" operand.
3083 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3084 // We can only continue if no tokens were eaten.
3085 if (GotShift != MatchOperand_NoMatch)
3086 return GotShift;
3087
3088 // This was not a register so parse other operands that start with an
3089 // identifier (like labels) as expressions and create them as immediates.
3090 const MCExpr *IdVal;
3091 S = getLoc();
3092 if (getParser().parseExpression(IdVal))
3093 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003094 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3095 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3096 return false;
3097 }
3098 case AsmToken::Integer:
3099 case AsmToken::Real:
3100 case AsmToken::Hash: {
3101 // #42 -> immediate.
3102 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003103
3104 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003105
3106 // Parse a negative sign
3107 bool isNegative = false;
3108 if (Parser.getTok().is(AsmToken::Minus)) {
3109 isNegative = true;
3110 // We need to consume this token only when we have a Real, otherwise
3111 // we let parseSymbolicImmVal take care of it
3112 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3113 Parser.Lex();
3114 }
3115
3116 // The only Real that should come through here is a literal #0.0 for
3117 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3118 // so convert the value.
3119 const AsmToken &Tok = Parser.getTok();
3120 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003121 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003122 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3123 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3124 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3125 Mnemonic != "fcmlt")
3126 return TokError("unexpected floating point literal");
3127 else if (IntVal != 0 || isNegative)
3128 return TokError("expected floating-point constant #0.0");
3129 Parser.Lex(); // Eat the token.
3130
3131 Operands.push_back(
3132 AArch64Operand::CreateToken("#0", false, S, getContext()));
3133 Operands.push_back(
3134 AArch64Operand::CreateToken(".0", false, S, getContext()));
3135 return false;
3136 }
3137
3138 const MCExpr *ImmVal;
3139 if (parseSymbolicImmVal(ImmVal))
3140 return true;
3141
3142 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3143 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3144 return false;
3145 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003146 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003147 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003148 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003149 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003150 Parser.Lex(); // Eat '='
3151 const MCExpr *SubExprVal;
3152 if (getParser().parseExpression(SubExprVal))
3153 return true;
3154
David Peixottoae5ba762014-07-18 16:05:14 +00003155 if (Operands.size() < 2 ||
3156 !static_cast<AArch64Operand &>(*Operands[1]).isReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003157 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003158
3159 bool IsXReg =
3160 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3161 Operands[1]->getReg());
3162
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003163 MCContext& Ctx = getContext();
3164 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3165 // 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 +00003166 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003167 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3168 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3169 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3170 ShiftAmt += 16;
3171 Imm >>= 16;
3172 }
3173 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3174 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3175 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003176 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003177 if (ShiftAmt)
3178 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3179 ShiftAmt, true, S, E, Ctx));
3180 return false;
3181 }
David Peixottoae5ba762014-07-18 16:05:14 +00003182 APInt Simm = APInt(64, Imm << ShiftAmt);
3183 // check if the immediate is an unsigned or signed 32-bit int for W regs
3184 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3185 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003186 }
3187 // 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 +00003188 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003189 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003190 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3191 return false;
3192 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003193 }
3194}
3195
3196/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3197/// operands.
3198bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3199 StringRef Name, SMLoc NameLoc,
3200 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003201 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003202 Name = StringSwitch<StringRef>(Name.lower())
3203 .Case("beq", "b.eq")
3204 .Case("bne", "b.ne")
3205 .Case("bhs", "b.hs")
3206 .Case("bcs", "b.cs")
3207 .Case("blo", "b.lo")
3208 .Case("bcc", "b.cc")
3209 .Case("bmi", "b.mi")
3210 .Case("bpl", "b.pl")
3211 .Case("bvs", "b.vs")
3212 .Case("bvc", "b.vc")
3213 .Case("bhi", "b.hi")
3214 .Case("bls", "b.ls")
3215 .Case("bge", "b.ge")
3216 .Case("blt", "b.lt")
3217 .Case("bgt", "b.gt")
3218 .Case("ble", "b.le")
3219 .Case("bal", "b.al")
3220 .Case("bnv", "b.nv")
3221 .Default(Name);
3222
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003223 // First check for the AArch64-specific .req directive.
3224 if (Parser.getTok().is(AsmToken::Identifier) &&
3225 Parser.getTok().getIdentifier() == ".req") {
3226 parseDirectiveReq(Name, NameLoc);
3227 // We always return 'error' for this, as we're done with this
3228 // statement and don't need to match the 'instruction."
3229 return true;
3230 }
3231
Tim Northover3b0846e2014-05-24 12:50:23 +00003232 // Create the leading tokens for the mnemonic, split by '.' characters.
3233 size_t Start = 0, Next = Name.find('.');
3234 StringRef Head = Name.slice(Start, Next);
3235
3236 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003237 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3238 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003239
3240 Operands.push_back(
3241 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3242 Mnemonic = Head;
3243
3244 // Handle condition codes for a branch mnemonic
3245 if (Head == "b" && Next != StringRef::npos) {
3246 Start = Next;
3247 Next = Name.find('.', Start + 1);
3248 Head = Name.slice(Start + 1, Next);
3249
3250 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3251 (Head.data() - Name.data()));
3252 AArch64CC::CondCode CC = parseCondCodeString(Head);
3253 if (CC == AArch64CC::Invalid)
3254 return Error(SuffixLoc, "invalid condition code");
3255 Operands.push_back(
3256 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3257 Operands.push_back(
3258 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3259 }
3260
3261 // Add the remaining tokens in the mnemonic.
3262 while (Next != StringRef::npos) {
3263 Start = Next;
3264 Next = Name.find('.', Start + 1);
3265 Head = Name.slice(Start, Next);
3266 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3267 (Head.data() - Name.data()) + 1);
3268 Operands.push_back(
3269 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3270 }
3271
3272 // Conditional compare instructions have a Condition Code operand, which needs
3273 // to be parsed and an immediate operand created.
3274 bool condCodeFourthOperand =
3275 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3276 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3277 Head == "csinc" || Head == "csinv" || Head == "csneg");
3278
3279 // These instructions are aliases to some of the conditional select
3280 // instructions. However, the condition code is inverted in the aliased
3281 // instruction.
3282 //
3283 // FIXME: Is this the correct way to handle these? Or should the parser
3284 // generate the aliased instructions directly?
3285 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3286 bool condCodeThirdOperand =
3287 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3288
3289 // Read the remaining operands.
3290 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3291 // Read the first operand.
3292 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003293 return true;
3294 }
3295
3296 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003297 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003298 // Parse and remember the operand.
3299 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3300 (N == 3 && condCodeThirdOperand) ||
3301 (N == 2 && condCodeSecondOperand),
3302 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003303 return true;
3304 }
3305
3306 // After successfully parsing some operands there are two special cases to
3307 // consider (i.e. notional operands not separated by commas). Both are due
3308 // to memory specifiers:
3309 // + An RBrac will end an address for load/store/prefetch
3310 // + An '!' will indicate a pre-indexed operation.
3311 //
3312 // It's someone else's responsibility to make sure these tokens are sane
3313 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003314
Nirav Davee833c6c2016-11-08 18:31:04 +00003315 SMLoc RLoc = Parser.getTok().getLoc();
3316 if (parseOptionalToken(AsmToken::RBrac))
3317 Operands.push_back(
3318 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3319 SMLoc ELoc = Parser.getTok().getLoc();
3320 if (parseOptionalToken(AsmToken::Exclaim))
3321 Operands.push_back(
3322 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003323
3324 ++N;
3325 }
3326 }
3327
Nirav Davee833c6c2016-11-08 18:31:04 +00003328 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3329 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003330
Tim Northover3b0846e2014-05-24 12:50:23 +00003331 return false;
3332}
3333
3334// FIXME: This entire function is a giant hack to provide us with decent
3335// operand range validation/diagnostics until TableGen/MC can be extended
3336// to support autogeneration of this kind of validation.
3337bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3338 SmallVectorImpl<SMLoc> &Loc) {
3339 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3340 // Check for indexed addressing modes w/ the base register being the
3341 // same as a destination/source register or pair load where
3342 // the Rt == Rt2. All of those are undefined behaviour.
3343 switch (Inst.getOpcode()) {
3344 case AArch64::LDPSWpre:
3345 case AArch64::LDPWpost:
3346 case AArch64::LDPWpre:
3347 case AArch64::LDPXpost:
3348 case AArch64::LDPXpre: {
3349 unsigned Rt = Inst.getOperand(1).getReg();
3350 unsigned Rt2 = Inst.getOperand(2).getReg();
3351 unsigned Rn = Inst.getOperand(3).getReg();
3352 if (RI->isSubRegisterEq(Rn, Rt))
3353 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3354 "is also a destination");
3355 if (RI->isSubRegisterEq(Rn, Rt2))
3356 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3357 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003358 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003359 }
3360 case AArch64::LDPDi:
3361 case AArch64::LDPQi:
3362 case AArch64::LDPSi:
3363 case AArch64::LDPSWi:
3364 case AArch64::LDPWi:
3365 case AArch64::LDPXi: {
3366 unsigned Rt = Inst.getOperand(0).getReg();
3367 unsigned Rt2 = Inst.getOperand(1).getReg();
3368 if (Rt == Rt2)
3369 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3370 break;
3371 }
3372 case AArch64::LDPDpost:
3373 case AArch64::LDPDpre:
3374 case AArch64::LDPQpost:
3375 case AArch64::LDPQpre:
3376 case AArch64::LDPSpost:
3377 case AArch64::LDPSpre:
3378 case AArch64::LDPSWpost: {
3379 unsigned Rt = Inst.getOperand(1).getReg();
3380 unsigned Rt2 = Inst.getOperand(2).getReg();
3381 if (Rt == Rt2)
3382 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3383 break;
3384 }
3385 case AArch64::STPDpost:
3386 case AArch64::STPDpre:
3387 case AArch64::STPQpost:
3388 case AArch64::STPQpre:
3389 case AArch64::STPSpost:
3390 case AArch64::STPSpre:
3391 case AArch64::STPWpost:
3392 case AArch64::STPWpre:
3393 case AArch64::STPXpost:
3394 case AArch64::STPXpre: {
3395 unsigned Rt = Inst.getOperand(1).getReg();
3396 unsigned Rt2 = Inst.getOperand(2).getReg();
3397 unsigned Rn = Inst.getOperand(3).getReg();
3398 if (RI->isSubRegisterEq(Rn, Rt))
3399 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3400 "is also a source");
3401 if (RI->isSubRegisterEq(Rn, Rt2))
3402 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3403 "is also a source");
3404 break;
3405 }
3406 case AArch64::LDRBBpre:
3407 case AArch64::LDRBpre:
3408 case AArch64::LDRHHpre:
3409 case AArch64::LDRHpre:
3410 case AArch64::LDRSBWpre:
3411 case AArch64::LDRSBXpre:
3412 case AArch64::LDRSHWpre:
3413 case AArch64::LDRSHXpre:
3414 case AArch64::LDRSWpre:
3415 case AArch64::LDRWpre:
3416 case AArch64::LDRXpre:
3417 case AArch64::LDRBBpost:
3418 case AArch64::LDRBpost:
3419 case AArch64::LDRHHpost:
3420 case AArch64::LDRHpost:
3421 case AArch64::LDRSBWpost:
3422 case AArch64::LDRSBXpost:
3423 case AArch64::LDRSHWpost:
3424 case AArch64::LDRSHXpost:
3425 case AArch64::LDRSWpost:
3426 case AArch64::LDRWpost:
3427 case AArch64::LDRXpost: {
3428 unsigned Rt = Inst.getOperand(1).getReg();
3429 unsigned Rn = Inst.getOperand(2).getReg();
3430 if (RI->isSubRegisterEq(Rn, Rt))
3431 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3432 "is also a source");
3433 break;
3434 }
3435 case AArch64::STRBBpost:
3436 case AArch64::STRBpost:
3437 case AArch64::STRHHpost:
3438 case AArch64::STRHpost:
3439 case AArch64::STRWpost:
3440 case AArch64::STRXpost:
3441 case AArch64::STRBBpre:
3442 case AArch64::STRBpre:
3443 case AArch64::STRHHpre:
3444 case AArch64::STRHpre:
3445 case AArch64::STRWpre:
3446 case AArch64::STRXpre: {
3447 unsigned Rt = Inst.getOperand(1).getReg();
3448 unsigned Rn = Inst.getOperand(2).getReg();
3449 if (RI->isSubRegisterEq(Rn, Rt))
3450 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3451 "is also a source");
3452 break;
3453 }
3454 }
3455
3456 // Now check immediate ranges. Separate from the above as there is overlap
3457 // in the instructions being checked and this keeps the nested conditionals
3458 // to a minimum.
3459 switch (Inst.getOpcode()) {
3460 case AArch64::ADDSWri:
3461 case AArch64::ADDSXri:
3462 case AArch64::ADDWri:
3463 case AArch64::ADDXri:
3464 case AArch64::SUBSWri:
3465 case AArch64::SUBSXri:
3466 case AArch64::SUBWri:
3467 case AArch64::SUBXri: {
3468 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3469 // some slight duplication here.
3470 if (Inst.getOperand(2).isExpr()) {
3471 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3472 AArch64MCExpr::VariantKind ELFRefKind;
3473 MCSymbolRefExpr::VariantKind DarwinRefKind;
3474 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003475 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3476
3477 // Only allow these with ADDXri.
3478 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3479 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3480 Inst.getOpcode() == AArch64::ADDXri)
3481 return false;
3482
3483 // Only allow these with ADDXri/ADDWri
3484 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3485 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3486 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3487 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3488 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3489 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3490 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3491 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3492 (Inst.getOpcode() == AArch64::ADDXri ||
3493 Inst.getOpcode() == AArch64::ADDWri))
3494 return false;
3495
3496 // Don't allow symbol refs in the immediate field otherwise
3497 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3498 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3499 // 'cmp w0, 'borked')
3500 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003501 }
Diana Picusc93518d2016-10-11 09:17:47 +00003502 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003503 }
3504 return false;
3505 }
3506 default:
3507 return false;
3508 }
3509}
3510
Craig Topper05515562017-10-26 06:46:41 +00003511static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3512 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003513
3514bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3515 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003516 switch (ErrCode) {
3517 case Match_MissingFeature:
3518 return Error(Loc,
3519 "instruction requires a CPU feature not currently enabled");
3520 case Match_InvalidOperand:
3521 return Error(Loc, "invalid operand for instruction");
3522 case Match_InvalidSuffix:
3523 return Error(Loc, "invalid type suffix for instruction");
3524 case Match_InvalidCondCode:
3525 return Error(Loc, "expected AArch64 condition code");
3526 case Match_AddSubRegExtendSmall:
3527 return Error(Loc,
3528 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3529 case Match_AddSubRegExtendLarge:
3530 return Error(Loc,
3531 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3532 case Match_AddSubSecondSource:
3533 return Error(Loc,
3534 "expected compatible register, symbol or integer in range [0, 4095]");
3535 case Match_LogicalSecondSource:
3536 return Error(Loc, "expected compatible register or logical immediate");
3537 case Match_InvalidMovImm32Shift:
3538 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3539 case Match_InvalidMovImm64Shift:
3540 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3541 case Match_AddSubRegShift32:
3542 return Error(Loc,
3543 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3544 case Match_AddSubRegShift64:
3545 return Error(Loc,
3546 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3547 case Match_InvalidFPImm:
3548 return Error(Loc,
3549 "expected compatible register or floating-point constant");
3550 case Match_InvalidMemoryIndexedSImm9:
3551 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003552 case Match_InvalidMemoryIndexedSImm10:
3553 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003554 case Match_InvalidMemoryIndexed4SImm7:
3555 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3556 case Match_InvalidMemoryIndexed8SImm7:
3557 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3558 case Match_InvalidMemoryIndexed16SImm7:
3559 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3560 case Match_InvalidMemoryWExtend8:
3561 return Error(Loc,
3562 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3563 case Match_InvalidMemoryWExtend16:
3564 return Error(Loc,
3565 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3566 case Match_InvalidMemoryWExtend32:
3567 return Error(Loc,
3568 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3569 case Match_InvalidMemoryWExtend64:
3570 return Error(Loc,
3571 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3572 case Match_InvalidMemoryWExtend128:
3573 return Error(Loc,
3574 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3575 case Match_InvalidMemoryXExtend8:
3576 return Error(Loc,
3577 "expected 'lsl' or 'sxtx' with optional shift of #0");
3578 case Match_InvalidMemoryXExtend16:
3579 return Error(Loc,
3580 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3581 case Match_InvalidMemoryXExtend32:
3582 return Error(Loc,
3583 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3584 case Match_InvalidMemoryXExtend64:
3585 return Error(Loc,
3586 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3587 case Match_InvalidMemoryXExtend128:
3588 return Error(Loc,
3589 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3590 case Match_InvalidMemoryIndexed1:
3591 return Error(Loc, "index must be an integer in range [0, 4095].");
3592 case Match_InvalidMemoryIndexed2:
3593 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3594 case Match_InvalidMemoryIndexed4:
3595 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3596 case Match_InvalidMemoryIndexed8:
3597 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3598 case Match_InvalidMemoryIndexed16:
3599 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003600 case Match_InvalidImm0_1:
3601 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003602 case Match_InvalidImm0_7:
3603 return Error(Loc, "immediate must be an integer in range [0, 7].");
3604 case Match_InvalidImm0_15:
3605 return Error(Loc, "immediate must be an integer in range [0, 15].");
3606 case Match_InvalidImm0_31:
3607 return Error(Loc, "immediate must be an integer in range [0, 31].");
3608 case Match_InvalidImm0_63:
3609 return Error(Loc, "immediate must be an integer in range [0, 63].");
3610 case Match_InvalidImm0_127:
3611 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003612 case Match_InvalidImm0_255:
3613 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003614 case Match_InvalidImm0_65535:
3615 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3616 case Match_InvalidImm1_8:
3617 return Error(Loc, "immediate must be an integer in range [1, 8].");
3618 case Match_InvalidImm1_16:
3619 return Error(Loc, "immediate must be an integer in range [1, 16].");
3620 case Match_InvalidImm1_32:
3621 return Error(Loc, "immediate must be an integer in range [1, 32].");
3622 case Match_InvalidImm1_64:
3623 return Error(Loc, "immediate must be an integer in range [1, 64].");
3624 case Match_InvalidIndex1:
3625 return Error(Loc, "expected lane specifier '[1]'");
3626 case Match_InvalidIndexB:
3627 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3628 case Match_InvalidIndexH:
3629 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3630 case Match_InvalidIndexS:
3631 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3632 case Match_InvalidIndexD:
3633 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3634 case Match_InvalidLabel:
3635 return Error(Loc, "expected label or encodable integer pc offset");
3636 case Match_MRS:
3637 return Error(Loc, "expected readable system register");
3638 case Match_MSR:
3639 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003640 case Match_InvalidComplexRotationEven:
3641 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3642 case Match_InvalidComplexRotationOdd:
3643 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003644 case Match_MnemonicFail: {
3645 std::string Suggestion = AArch64MnemonicSpellCheck(
3646 ((AArch64Operand &)*Operands[0]).getToken(),
3647 ComputeAvailableFeatures(STI->getFeatureBits()));
3648 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3649 }
Sander de Smalen2b6338b2017-11-29 14:34:18 +00003650 case Match_InvalidSVEPredicateAnyReg:
3651 case Match_InvalidSVEPredicateBReg:
3652 case Match_InvalidSVEPredicateHReg:
3653 case Match_InvalidSVEPredicateSReg:
3654 case Match_InvalidSVEPredicateDReg:
3655 return Error(Loc, "invalid predicate register.");
Tim Northover3b0846e2014-05-24 12:50:23 +00003656 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003657 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003658 }
3659}
3660
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003661static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003662
3663bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3664 OperandVector &Operands,
3665 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003666 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003667 bool MatchingInlineAsm) {
3668 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003669 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3670 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003671
David Blaikie960ea3f2014-06-08 16:18:35 +00003672 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003673 unsigned NumOperands = Operands.size();
3674
3675 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003676 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3677 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3678 if (Op2.isReg() && Op3.isImm()) {
3679 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003680 if (Op3CE) {
3681 uint64_t Op3Val = Op3CE->getValue();
3682 uint64_t NewOp3Val = 0;
3683 uint64_t NewOp4Val = 0;
3684 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003685 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003686 NewOp3Val = (32 - Op3Val) & 0x1f;
3687 NewOp4Val = 31 - Op3Val;
3688 } else {
3689 NewOp3Val = (64 - Op3Val) & 0x3f;
3690 NewOp4Val = 63 - Op3Val;
3691 }
3692
Jim Grosbach13760bd2015-05-30 01:25:56 +00003693 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3694 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003695
3696 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003697 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003698 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003699 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3700 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3701 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003702 }
3703 }
Tim Northover03b99f62015-04-30 18:28:58 +00003704 } else if (NumOperands == 4 && Tok == "bfc") {
3705 // FIXME: Horrible hack to handle BFC->BFM alias.
3706 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3707 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3708 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3709
3710 if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
3711 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3712 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3713
3714 if (LSBCE && WidthCE) {
3715 uint64_t LSB = LSBCE->getValue();
3716 uint64_t Width = WidthCE->getValue();
3717
3718 uint64_t RegWidth = 0;
3719 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3720 Op1.getReg()))
3721 RegWidth = 64;
3722 else
3723 RegWidth = 32;
3724
3725 if (LSB >= RegWidth)
3726 return Error(LSBOp.getStartLoc(),
3727 "expected integer in range [0, 31]");
3728 if (Width < 1 || Width > RegWidth)
3729 return Error(WidthOp.getStartLoc(),
3730 "expected integer in range [1, 32]");
3731
3732 uint64_t ImmR = 0;
3733 if (RegWidth == 32)
3734 ImmR = (32 - LSB) & 0x1f;
3735 else
3736 ImmR = (64 - LSB) & 0x3f;
3737
3738 uint64_t ImmS = Width - 1;
3739
3740 if (ImmR != 0 && ImmS >= ImmR)
3741 return Error(WidthOp.getStartLoc(),
3742 "requested insert overflows register");
3743
Jim Grosbach13760bd2015-05-30 01:25:56 +00003744 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3745 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003746 Operands[0] = AArch64Operand::CreateToken(
3747 "bfm", false, Op.getStartLoc(), getContext());
3748 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003749 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3750 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003751 Operands[3] = AArch64Operand::CreateImm(
3752 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3753 Operands.emplace_back(
3754 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3755 WidthOp.getEndLoc(), getContext()));
3756 }
3757 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003758 } else if (NumOperands == 5) {
3759 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3760 // UBFIZ -> UBFM aliases.
3761 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003762 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3763 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3764 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003765
David Blaikie960ea3f2014-06-08 16:18:35 +00003766 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3767 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3768 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003769
3770 if (Op3CE && Op4CE) {
3771 uint64_t Op3Val = Op3CE->getValue();
3772 uint64_t Op4Val = Op4CE->getValue();
3773
3774 uint64_t RegWidth = 0;
3775 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003776 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003777 RegWidth = 64;
3778 else
3779 RegWidth = 32;
3780
3781 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003782 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003783 "expected integer in range [0, 31]");
3784 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003785 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003786 "expected integer in range [1, 32]");
3787
3788 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003789 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003790 NewOp3Val = (32 - Op3Val) & 0x1f;
3791 else
3792 NewOp3Val = (64 - Op3Val) & 0x3f;
3793
3794 uint64_t NewOp4Val = Op4Val - 1;
3795
3796 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003797 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003798 "requested insert overflows register");
3799
3800 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003801 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003802 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003803 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003804 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003805 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003806 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003807 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003808 if (Tok == "bfi")
3809 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003810 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003811 else if (Tok == "sbfiz")
3812 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003813 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003814 else if (Tok == "ubfiz")
3815 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003816 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003817 else
3818 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003819 }
3820 }
3821
3822 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3823 // UBFX -> UBFM aliases.
3824 } else if (NumOperands == 5 &&
3825 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003826 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3827 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3828 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003829
David Blaikie960ea3f2014-06-08 16:18:35 +00003830 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3831 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3832 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003833
3834 if (Op3CE && Op4CE) {
3835 uint64_t Op3Val = Op3CE->getValue();
3836 uint64_t Op4Val = Op4CE->getValue();
3837
3838 uint64_t RegWidth = 0;
3839 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003840 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003841 RegWidth = 64;
3842 else
3843 RegWidth = 32;
3844
3845 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003846 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003847 "expected integer in range [0, 31]");
3848 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003849 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003850 "expected integer in range [1, 32]");
3851
3852 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3853
3854 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003855 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003856 "requested extract overflows register");
3857
3858 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003859 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003860 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003861 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003862 if (Tok == "bfxil")
3863 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003864 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003865 else if (Tok == "sbfx")
3866 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003867 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003868 else if (Tok == "ubfx")
3869 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003870 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003871 else
3872 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003873 }
3874 }
3875 }
3876 }
3877 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3878 // InstAlias can't quite handle this since the reg classes aren't
3879 // subclasses.
3880 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3881 // The source register can be Wn here, but the matcher expects a
3882 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003883 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3884 if (Op.isReg()) {
3885 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003886 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3887 Op.getStartLoc(), Op.getEndLoc(),
3888 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003889 }
3890 }
3891 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3892 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003893 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3894 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003895 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003896 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003897 // The source register can be Wn here, but the matcher expects a
3898 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003899 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3900 if (Op.isReg()) {
3901 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003902 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3903 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003904 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003905 }
3906 }
3907 }
3908 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3909 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003910 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3911 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003912 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003913 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003914 // The source register can be Wn here, but the matcher expects a
3915 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003916 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3917 if (Op.isReg()) {
3918 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003919 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3920 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003921 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003922 }
3923 }
3924 }
3925
Tim Northover3b0846e2014-05-24 12:50:23 +00003926 MCInst Inst;
3927 // First try to match against the secondary set of tables containing the
3928 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3929 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003930 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003931
3932 // If that fails, try against the alternate table containing long-form NEON:
3933 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003934 if (MatchResult != Match_Success) {
3935 // But first, save the short-form match result: we can use it in case the
3936 // long-form match also fails.
3937 auto ShortFormNEONErrorInfo = ErrorInfo;
3938 auto ShortFormNEONMatchResult = MatchResult;
3939
Tim Northover3b0846e2014-05-24 12:50:23 +00003940 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003941 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003942
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003943 // Now, both matches failed, and the long-form match failed on the mnemonic
3944 // suffix token operand. The short-form match failure is probably more
3945 // relevant: use it instead.
3946 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003947 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003948 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3949 MatchResult = ShortFormNEONMatchResult;
3950 ErrorInfo = ShortFormNEONErrorInfo;
3951 }
3952 }
3953
Tim Northover3b0846e2014-05-24 12:50:23 +00003954 switch (MatchResult) {
3955 case Match_Success: {
3956 // Perform range checking and other semantic validations
3957 SmallVector<SMLoc, 8> OperandLocs;
3958 NumOperands = Operands.size();
3959 for (unsigned i = 1; i < NumOperands; ++i)
3960 OperandLocs.push_back(Operands[i]->getStartLoc());
3961 if (validateInstruction(Inst, OperandLocs))
3962 return true;
3963
3964 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003965 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00003966 return false;
3967 }
3968 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003969 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003970 // Special case the error message for the very common case where only
3971 // a single subtarget feature is missing (neon, e.g.).
3972 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003973 uint64_t Mask = 1;
3974 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
3975 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003976 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003977 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00003978 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003979 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00003980 }
3981 return Error(IDLoc, Msg);
3982 }
3983 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003984 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003985 case Match_InvalidOperand: {
3986 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00003987
Tim Northover26bb14e2014-08-18 11:49:42 +00003988 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003989 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00003990 return Error(IDLoc, "too few operands for instruction",
3991 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003992
David Blaikie960ea3f2014-06-08 16:18:35 +00003993 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003994 if (ErrorLoc == SMLoc())
3995 ErrorLoc = IDLoc;
3996 }
3997 // If the match failed on a suffix token operand, tweak the diagnostic
3998 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00003999 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4000 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004001 MatchResult = Match_InvalidSuffix;
4002
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004003 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004004 }
4005 case Match_InvalidMemoryIndexed1:
4006 case Match_InvalidMemoryIndexed2:
4007 case Match_InvalidMemoryIndexed4:
4008 case Match_InvalidMemoryIndexed8:
4009 case Match_InvalidMemoryIndexed16:
4010 case Match_InvalidCondCode:
4011 case Match_AddSubRegExtendSmall:
4012 case Match_AddSubRegExtendLarge:
4013 case Match_AddSubSecondSource:
4014 case Match_LogicalSecondSource:
4015 case Match_AddSubRegShift32:
4016 case Match_AddSubRegShift64:
4017 case Match_InvalidMovImm32Shift:
4018 case Match_InvalidMovImm64Shift:
4019 case Match_InvalidFPImm:
4020 case Match_InvalidMemoryWExtend8:
4021 case Match_InvalidMemoryWExtend16:
4022 case Match_InvalidMemoryWExtend32:
4023 case Match_InvalidMemoryWExtend64:
4024 case Match_InvalidMemoryWExtend128:
4025 case Match_InvalidMemoryXExtend8:
4026 case Match_InvalidMemoryXExtend16:
4027 case Match_InvalidMemoryXExtend32:
4028 case Match_InvalidMemoryXExtend64:
4029 case Match_InvalidMemoryXExtend128:
4030 case Match_InvalidMemoryIndexed4SImm7:
4031 case Match_InvalidMemoryIndexed8SImm7:
4032 case Match_InvalidMemoryIndexed16SImm7:
4033 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004034 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004035 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004036 case Match_InvalidImm0_7:
4037 case Match_InvalidImm0_15:
4038 case Match_InvalidImm0_31:
4039 case Match_InvalidImm0_63:
4040 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004041 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004042 case Match_InvalidImm0_65535:
4043 case Match_InvalidImm1_8:
4044 case Match_InvalidImm1_16:
4045 case Match_InvalidImm1_32:
4046 case Match_InvalidImm1_64:
4047 case Match_InvalidIndex1:
4048 case Match_InvalidIndexB:
4049 case Match_InvalidIndexH:
4050 case Match_InvalidIndexS:
4051 case Match_InvalidIndexD:
4052 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004053 case Match_InvalidComplexRotationEven:
4054 case Match_InvalidComplexRotationOdd:
Sander de Smalen2b6338b2017-11-29 14:34:18 +00004055 case Match_InvalidSVEPredicateAnyReg:
4056 case Match_InvalidSVEPredicateBReg:
4057 case Match_InvalidSVEPredicateHReg:
4058 case Match_InvalidSVEPredicateSReg:
4059 case Match_InvalidSVEPredicateDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004060 case Match_MSR:
4061 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004062 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004063 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004064 // Any time we get here, there's nothing fancy to do. Just get the
4065 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004066 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004067 if (ErrorLoc == SMLoc())
4068 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004069 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004070 }
4071 }
4072
4073 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004074}
4075
4076/// ParseDirective parses the arm specific directives
4077bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004078 const MCObjectFileInfo::Environment Format =
4079 getContext().getObjectFileInfo()->getObjectFileType();
4080 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4081 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004082
Tim Northover3b0846e2014-05-24 12:50:23 +00004083 StringRef IDVal = DirectiveID.getIdentifier();
4084 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004085 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004086 parseDirectiveArch(Loc);
4087 else if (IDVal == ".cpu")
4088 parseDirectiveCPU(Loc);
4089 else if (IDVal == ".hword")
4090 parseDirectiveWord(2, Loc);
4091 else if (IDVal == ".word")
4092 parseDirectiveWord(4, Loc);
4093 else if (IDVal == ".xword")
4094 parseDirectiveWord(8, Loc);
4095 else if (IDVal == ".tlsdesccall")
4096 parseDirectiveTLSDescCall(Loc);
4097 else if (IDVal == ".ltorg" || IDVal == ".pool")
4098 parseDirectiveLtorg(Loc);
4099 else if (IDVal == ".unreq")
4100 parseDirectiveUnreq(Loc);
4101 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004102 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004103 parseDirectiveInst(Loc);
4104 else
4105 return true;
4106 } else if (IDVal == MCLOHDirectiveName())
4107 parseDirectiveLOH(IDVal, Loc);
4108 else
4109 return true;
4110 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004111}
4112
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004113static const struct {
4114 const char *Name;
4115 const FeatureBitset Features;
4116} ExtensionMap[] = {
4117 { "crc", {AArch64::FeatureCRC} },
4118 { "crypto", {AArch64::FeatureCrypto} },
4119 { "fp", {AArch64::FeatureFPARMv8} },
4120 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004121 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004122 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004123
4124 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004125 { "pan", {} },
4126 { "lor", {} },
4127 { "rdma", {} },
4128 { "profile", {} },
4129};
4130
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004131/// parseDirectiveArch
4132/// ::= .arch token
4133bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4134 SMLoc ArchLoc = getLoc();
4135
4136 StringRef Arch, ExtensionString;
4137 std::tie(Arch, ExtensionString) =
4138 getParser().parseStringToEndOfStatement().trim().split('+');
4139
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004140 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4141 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004142 return Error(ArchLoc, "unknown arch name");
4143
4144 if (parseToken(AsmToken::EndOfStatement))
4145 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004146
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004147 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004148 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004149 AArch64::getArchFeatures(ID, AArch64Features);
4150 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4151 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004152
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004153 MCSubtargetInfo &STI = copySTI();
4154 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4155 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4156
4157 SmallVector<StringRef, 4> RequestedExtensions;
4158 if (!ExtensionString.empty())
4159 ExtensionString.split(RequestedExtensions, '+');
4160
4161 FeatureBitset Features = STI.getFeatureBits();
4162 for (auto Name : RequestedExtensions) {
4163 bool EnableFeature = true;
4164
4165 if (Name.startswith_lower("no")) {
4166 EnableFeature = false;
4167 Name = Name.substr(2);
4168 }
4169
4170 for (const auto &Extension : ExtensionMap) {
4171 if (Extension.Name != Name)
4172 continue;
4173
4174 if (Extension.Features.none())
4175 report_fatal_error("unsupported architectural extension: " + Name);
4176
4177 FeatureBitset ToggleFeatures = EnableFeature
4178 ? (~Features & Extension.Features)
4179 : ( Features & Extension.Features);
4180 uint64_t Features =
4181 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4182 setAvailableFeatures(Features);
4183 break;
4184 }
4185 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004186 return false;
4187}
4188
Tim Northover8b96c7e2017-05-15 19:42:15 +00004189static SMLoc incrementLoc(SMLoc L, int Offset) {
4190 return SMLoc::getFromPointer(L.getPointer() + Offset);
4191}
4192
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004193/// parseDirectiveCPU
4194/// ::= .cpu id
4195bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004196 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004197
4198 StringRef CPU, ExtensionString;
4199 std::tie(CPU, ExtensionString) =
4200 getParser().parseStringToEndOfStatement().trim().split('+');
4201
Nirav Davee833c6c2016-11-08 18:31:04 +00004202 if (parseToken(AsmToken::EndOfStatement))
4203 return true;
4204
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004205 SmallVector<StringRef, 4> RequestedExtensions;
4206 if (!ExtensionString.empty())
4207 ExtensionString.split(RequestedExtensions, '+');
4208
4209 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4210 // once that is tablegen'ed
4211 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004212 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004213 return false;
4214 }
4215
4216 MCSubtargetInfo &STI = copySTI();
4217 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004218 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004219
4220 FeatureBitset Features = STI.getFeatureBits();
4221 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004222 // Advance source location past '+'.
4223 CurLoc = incrementLoc(CurLoc, 1);
4224
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004225 bool EnableFeature = true;
4226
4227 if (Name.startswith_lower("no")) {
4228 EnableFeature = false;
4229 Name = Name.substr(2);
4230 }
4231
Tim Northover8b96c7e2017-05-15 19:42:15 +00004232 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004233 for (const auto &Extension : ExtensionMap) {
4234 if (Extension.Name != Name)
4235 continue;
4236
4237 if (Extension.Features.none())
4238 report_fatal_error("unsupported architectural extension: " + Name);
4239
4240 FeatureBitset ToggleFeatures = EnableFeature
4241 ? (~Features & Extension.Features)
4242 : ( Features & Extension.Features);
4243 uint64_t Features =
4244 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4245 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004246 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004247
4248 break;
4249 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004250
4251 if (!FoundExtension)
4252 Error(CurLoc, "unsupported architectural extension");
4253
4254 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004255 }
4256 return false;
4257}
4258
Tim Northover3b0846e2014-05-24 12:50:23 +00004259/// parseDirectiveWord
4260/// ::= .word [ expression (, expression)* ]
4261bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004262 auto parseOp = [&]() -> bool {
4263 const MCExpr *Value;
4264 if (getParser().parseExpression(Value))
4265 return true;
4266 getParser().getStreamer().EmitValue(Value, Size, L);
4267 return false;
4268 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004269
Nirav Davee833c6c2016-11-08 18:31:04 +00004270 if (parseMany(parseOp))
4271 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004272 return false;
4273}
4274
Chad Rosierdcd2a302014-10-22 20:35:57 +00004275/// parseDirectiveInst
4276/// ::= .inst opcode [, ...]
4277bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004278 if (getLexer().is(AsmToken::EndOfStatement))
4279 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004280
Nirav Davee833c6c2016-11-08 18:31:04 +00004281 auto parseOp = [&]() -> bool {
4282 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004283 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004284 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4285 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004286 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004287 if (check(!Value, L, "expected constant expression"))
4288 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004289 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004290 return false;
4291 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004292
Nirav Davee833c6c2016-11-08 18:31:04 +00004293 if (parseMany(parseOp))
4294 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004295 return false;
4296}
4297
Tim Northover3b0846e2014-05-24 12:50:23 +00004298// parseDirectiveTLSDescCall:
4299// ::= .tlsdesccall symbol
4300bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4301 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004302 if (check(getParser().parseIdentifier(Name), L,
4303 "expected symbol after directive") ||
4304 parseToken(AsmToken::EndOfStatement))
4305 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004306
Jim Grosbach6f482002015-05-18 18:43:14 +00004307 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004308 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4309 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004310
4311 MCInst Inst;
4312 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004313 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004314
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004315 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004316 return false;
4317}
4318
4319/// ::= .loh <lohName | lohId> label1, ..., labelN
4320/// The number of arguments depends on the loh identifier.
4321bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004322 MCLOHType Kind;
4323 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4324 if (getParser().getTok().isNot(AsmToken::Integer))
4325 return TokError("expected an identifier or a number in directive");
4326 // We successfully get a numeric value for the identifier.
4327 // Check if it is valid.
4328 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004329 if (Id <= -1U && !isValidMCLOHType(Id))
4330 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004331 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004332 } else {
4333 StringRef Name = getTok().getIdentifier();
4334 // We successfully parse an identifier.
4335 // Check if it is a recognized one.
4336 int Id = MCLOHNameToId(Name);
4337
4338 if (Id == -1)
4339 return TokError("invalid identifier in directive");
4340 Kind = (MCLOHType)Id;
4341 }
4342 // Consume the identifier.
4343 Lex();
4344 // Get the number of arguments of this LOH.
4345 int NbArgs = MCLOHIdToNbArgs(Kind);
4346
4347 assert(NbArgs != -1 && "Invalid number of arguments");
4348
4349 SmallVector<MCSymbol *, 3> Args;
4350 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4351 StringRef Name;
4352 if (getParser().parseIdentifier(Name))
4353 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004354 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004355
4356 if (Idx + 1 == NbArgs)
4357 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004358 if (parseToken(AsmToken::Comma,
4359 "unexpected token in '" + Twine(IDVal) + "' directive"))
4360 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004361 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004362 if (parseToken(AsmToken::EndOfStatement,
4363 "unexpected token in '" + Twine(IDVal) + "' directive"))
4364 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004365
4366 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4367 return false;
4368}
4369
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004370/// parseDirectiveLtorg
4371/// ::= .ltorg | .pool
4372bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004373 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4374 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004375 getTargetStreamer().emitCurrentConstantPool();
4376 return false;
4377}
4378
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004379/// parseDirectiveReq
4380/// ::= name .req registername
4381bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004382 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004383 Parser.Lex(); // Eat the '.req' token.
4384 SMLoc SRegLoc = getLoc();
Sander de Smalen8e607342017-11-15 15:44:43 +00004385 int RegNum = tryParseRegister();
Florian Hahnc4422242017-11-07 13:07:50 +00004386 RegKind RegisterKind = RegKind::Scalar;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004387
Sander de Smalen8e607342017-11-15 15:44:43 +00004388 if (RegNum == -1) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004389 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004390 RegisterKind = RegKind::NeonVector;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004391 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004392 if (!Kind.empty())
4393 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004394 }
4395
Sander de Smalen8e607342017-11-15 15:44:43 +00004396 if (RegNum == -1) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004397 StringRef Kind;
4398 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen8e607342017-11-15 15:44:43 +00004399 OperandMatchResultTy Res =
4400 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4401
4402 if (Res == MatchOperand_ParseFail)
4403 return true;
4404
4405 if (Res == MatchOperand_Success && !Kind.empty())
4406 return Error(SRegLoc,
4407 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004408 }
4409
Sander de Smalen2b6338b2017-11-29 14:34:18 +00004410 if (RegNum == -1) {
4411 StringRef Kind;
4412 RegisterKind = RegKind::SVEPredicateVector;
4413 OperandMatchResultTy Res =
4414 tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
4415
4416 if (Res == MatchOperand_ParseFail)
4417 return true;
4418
4419 if (Res == MatchOperand_Success && !Kind.empty())
4420 return Error(SRegLoc,
4421 "sve predicate register without type specifier expected");
4422 }
4423
Sander de Smalen8e607342017-11-15 15:44:43 +00004424 if (RegNum == -1)
Nirav Dave2364748a2016-09-16 18:30:20 +00004425 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004426
4427 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004428 if (parseToken(AsmToken::EndOfStatement,
4429 "unexpected input in .req directive"))
4430 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004431
Sander de Smalen8e607342017-11-15 15:44:43 +00004432 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004433 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004434 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4435
Nirav Dave2364748a2016-09-16 18:30:20 +00004436 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004437}
4438
4439/// parseDirectiveUneq
4440/// ::= .unreq registername
4441bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004442 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004443 if (getTok().isNot(AsmToken::Identifier))
4444 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004445 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4446 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004447 if (parseToken(AsmToken::EndOfStatement))
4448 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004449 return false;
4450}
4451
Tim Northover3b0846e2014-05-24 12:50:23 +00004452bool
4453AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4454 AArch64MCExpr::VariantKind &ELFRefKind,
4455 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4456 int64_t &Addend) {
4457 ELFRefKind = AArch64MCExpr::VK_INVALID;
4458 DarwinRefKind = MCSymbolRefExpr::VK_None;
4459 Addend = 0;
4460
4461 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4462 ELFRefKind = AE->getKind();
4463 Expr = AE->getSubExpr();
4464 }
4465
4466 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4467 if (SE) {
4468 // It's a simple symbol reference with no addend.
4469 DarwinRefKind = SE->getKind();
4470 return true;
4471 }
4472
4473 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4474 if (!BE)
4475 return false;
4476
4477 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4478 if (!SE)
4479 return false;
4480 DarwinRefKind = SE->getKind();
4481
4482 if (BE->getOpcode() != MCBinaryExpr::Add &&
4483 BE->getOpcode() != MCBinaryExpr::Sub)
4484 return false;
4485
4486 // See if the addend is is a constant, otherwise there's more going
4487 // on here than we can deal with.
4488 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4489 if (!AddendExpr)
4490 return false;
4491
4492 Addend = AddendExpr->getValue();
4493 if (BE->getOpcode() == MCBinaryExpr::Sub)
4494 Addend = -Addend;
4495
4496 // It's some symbol reference + a constant addend, but really
4497 // shouldn't use both Darwin and ELF syntax.
4498 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4499 DarwinRefKind == MCSymbolRefExpr::VK_None;
4500}
4501
4502/// Force static initialization.
4503extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004504 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4505 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4506 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004507}
4508
4509#define GET_REGISTER_MATCHER
4510#define GET_SUBTARGET_FEATURE_NAME
4511#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004512#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004513#include "AArch64GenAsmMatcher.inc"
4514
4515// Define this matcher function after the auto-generated include so we
4516// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004517unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004518 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004519 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004520 // If the kind is a token for a literal immediate, check if our asm
4521 // operand matches. This is for InstAliases which have a fixed-value
4522 // immediate in the syntax.
4523 int64_t ExpectedVal;
4524 switch (Kind) {
4525 default:
4526 return Match_InvalidOperand;
4527 case MCK__35_0:
4528 ExpectedVal = 0;
4529 break;
4530 case MCK__35_1:
4531 ExpectedVal = 1;
4532 break;
4533 case MCK__35_12:
4534 ExpectedVal = 12;
4535 break;
4536 case MCK__35_16:
4537 ExpectedVal = 16;
4538 break;
4539 case MCK__35_2:
4540 ExpectedVal = 2;
4541 break;
4542 case MCK__35_24:
4543 ExpectedVal = 24;
4544 break;
4545 case MCK__35_3:
4546 ExpectedVal = 3;
4547 break;
4548 case MCK__35_32:
4549 ExpectedVal = 32;
4550 break;
4551 case MCK__35_4:
4552 ExpectedVal = 4;
4553 break;
4554 case MCK__35_48:
4555 ExpectedVal = 48;
4556 break;
4557 case MCK__35_6:
4558 ExpectedVal = 6;
4559 break;
4560 case MCK__35_64:
4561 ExpectedVal = 64;
4562 break;
4563 case MCK__35_8:
4564 ExpectedVal = 8;
4565 break;
4566 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004567 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004568 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004569 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004570 if (!CE)
4571 return Match_InvalidOperand;
4572 if (CE->getValue() == ExpectedVal)
4573 return Match_Success;
4574 return Match_InvalidOperand;
4575}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004576
Alex Bradbury58eba092016-11-01 16:32:05 +00004577OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004578AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4579
4580 SMLoc S = getLoc();
4581
4582 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4583 Error(S, "expected register");
4584 return MatchOperand_ParseFail;
4585 }
4586
4587 int FirstReg = tryParseRegister();
4588 if (FirstReg == -1) {
4589 return MatchOperand_ParseFail;
4590 }
4591 const MCRegisterClass &WRegClass =
4592 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4593 const MCRegisterClass &XRegClass =
4594 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4595
4596 bool isXReg = XRegClass.contains(FirstReg),
4597 isWReg = WRegClass.contains(FirstReg);
4598 if (!isXReg && !isWReg) {
4599 Error(S, "expected first even register of a "
4600 "consecutive same-size even/odd register pair");
4601 return MatchOperand_ParseFail;
4602 }
4603
4604 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4605 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4606
4607 if (FirstEncoding & 0x1) {
4608 Error(S, "expected first even register of a "
4609 "consecutive same-size even/odd register pair");
4610 return MatchOperand_ParseFail;
4611 }
4612
4613 SMLoc M = getLoc();
4614 if (getParser().getTok().isNot(AsmToken::Comma)) {
4615 Error(M, "expected comma");
4616 return MatchOperand_ParseFail;
4617 }
4618 // Eat the comma
4619 getParser().Lex();
4620
4621 SMLoc E = getLoc();
4622 int SecondReg = tryParseRegister();
4623 if (SecondReg ==-1) {
4624 return MatchOperand_ParseFail;
4625 }
4626
Eugene Zelenko049b0172017-01-06 00:30:53 +00004627 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004628 (isXReg && !XRegClass.contains(SecondReg)) ||
4629 (isWReg && !WRegClass.contains(SecondReg))) {
4630 Error(E,"expected second odd register of a "
4631 "consecutive same-size even/odd register pair");
4632 return MatchOperand_ParseFail;
4633 }
Joel Jones504bf332016-10-24 13:37:13 +00004634
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004635 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004636 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004637 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4638 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4639 } else {
4640 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4641 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4642 }
4643
Florian Hahnc4422242017-11-07 13:07:50 +00004644 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4645 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004646
4647 return MatchOperand_Success;
4648}
Florian Hahn91f11e52017-11-07 16:45:48 +00004649
4650template <bool ParseSuffix>
4651OperandMatchResultTy
4652AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004653 const SMLoc S = getLoc();
4654 // Check for a SVE vector register specifier first.
Sander de Smalen8e607342017-11-15 15:44:43 +00004655 int RegNum = -1;
Florian Hahn91f11e52017-11-07 16:45:48 +00004656 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004657
Sander de Smalen8e607342017-11-15 15:44:43 +00004658 OperandMatchResultTy Res =
4659 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4660
4661 if (Res != MatchOperand_Success)
4662 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004663
4664 if (ParseSuffix && Kind.empty())
4665 return MatchOperand_NoMatch;
4666
4667 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
4668 .Case("", -1)
4669 .Case(".b", 8)
4670 .Case(".h", 16)
4671 .Case(".s", 32)
4672 .Case(".d", 64)
4673 .Case(".q", 128)
4674 .Default(0);
4675 if (!ElementWidth)
4676 return MatchOperand_NoMatch;
4677
4678 Operands.push_back(
4679 AArch64Operand::CreateReg(RegNum, RegKind::SVEDataVector, ElementWidth,
4680 S, S, getContext()));
4681
4682 return MatchOperand_Success;
4683}