blob: a480fa3b6048ebab7e0b1f521b0039a14a80c0eb [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/AArch64AddressingModes.h"
11#include "MCTargetDesc/AArch64MCExpr.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000012#include "MCTargetDesc/AArch64MCTargetDesc.h"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000013#include "MCTargetDesc/AArch64TargetStreamer.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000014#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000015#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000016#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000017#include "llvm/ADT/ArrayRef.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000018#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "llvm/ADT/SmallVector.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000020#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000021#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000023#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000025#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000028#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000029#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000030#include "llvm/MC/MCParser/MCAsmLexer.h"
31#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000032#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000033#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000034#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000035#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSubtargetInfo.h"
38#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000039#include "llvm/MC/MCTargetOptions.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000043#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000044#include "llvm/Support/MathExtras.h"
45#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000046#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000047#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000049#include <cassert>
50#include <cctype>
51#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000052#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000053#include <string>
54#include <tuple>
55#include <utility>
56#include <vector>
57
Tim Northover3b0846e2014-05-24 12:50:23 +000058using namespace llvm;
59
60namespace {
61
Sander de Smalencd6be962017-12-20 11:02:42 +000062enum class RegKind {
63 Scalar,
64 NeonVector,
65 SVEDataVector,
66 SVEPredicateVector
67};
Florian Hahnc4422242017-11-07 13:07:50 +000068
Tim Northover3b0846e2014-05-24 12:50:23 +000069class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000070private:
71 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000072
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000073 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000074 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000075
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000076 AArch64TargetStreamer &getTargetStreamer() {
77 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
78 return static_cast<AArch64TargetStreamer &>(TS);
79 }
80
Rafael Espindola961d4692014-11-11 05:18:41 +000081 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000082
83 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +000084 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +000085 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
86 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +000087 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +000088 int tryParseRegister();
89 int tryMatchVectorRegister(StringRef &Kind, bool expected);
90 bool parseRegister(OperandVector &Operands);
91 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
92 bool parseVectorList(OperandVector &Operands);
93 bool parseOperand(OperandVector &Operands, bool isCondCode,
94 bool invertCondCode);
95
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +000096 bool showMatchError(SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000097
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000098 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000099 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000100 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +0000101 bool parseDirectiveInst(SMLoc L);
102
Tim Northover3b0846e2014-05-24 12:50:23 +0000103 bool parseDirectiveTLSDescCall(SMLoc L);
104
105 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000106 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000107
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000108 bool parseDirectiveReq(StringRef Name, SMLoc L);
109 bool parseDirectiveUnreq(SMLoc L);
110
Tim Northover3b0846e2014-05-24 12:50:23 +0000111 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
112 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
113 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000114 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000115 bool MatchingInlineAsm) override;
116/// @name Auto-generated Match Functions
117/// {
118
119#define GET_ASSEMBLER_HEADER
120#include "AArch64GenAsmMatcher.inc"
121
122 /// }
123
Sander de Smalen8e607342017-11-15 15:44:43 +0000124 OperandMatchResultTy tryParseSVERegister(int &Reg, StringRef &Kind,
125 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000126 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
127 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
128 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
129 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
130 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
131 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000132 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000133 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
134 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
135 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
136 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
137 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000138 bool tryParseNeonVectorRegister(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000139 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Florian Hahn91f11e52017-11-07 16:45:48 +0000140 template <bool ParseSuffix>
141 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000142 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
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 {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000822 return Kind == k_Register;
823 }
824
825 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000826 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
827 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000828
Florian Hahnc4422242017-11-07 13:07:50 +0000829 bool isNeonVectorReg() const {
830 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
831 }
832
833 bool isNeonVectorRegLo() const {
834 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000835 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
836 Reg.RegNum);
837 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000838
Sander de Smalencd6be962017-12-20 11:02:42 +0000839 template <unsigned Class> bool isSVEVectorReg() const {
840 RegKind RK;
841 switch (Class) {
842 case AArch64::ZPRRegClassID:
843 RK = RegKind::SVEDataVector;
844 break;
845 case AArch64::PPRRegClassID:
846 RK = RegKind::SVEPredicateVector;
847 break;
848 default:
849 llvm_unreachable("Unsupport register class");
850 }
851
852 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000853 AArch64MCRegisterClasses[Class].contains(getReg());
854 }
855
Sander de Smalencd6be962017-12-20 11:02:42 +0000856 template <int ElementWidth, unsigned Class>
857 bool isSVEVectorRegOfWidth() const {
858 return isSVEVectorReg<Class>() &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000859 (ElementWidth == -1 || Reg.ElementWidth == ElementWidth);
860 }
861
Tim Northover3b0846e2014-05-24 12:50:23 +0000862 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000863 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000864 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
865 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000866
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000867 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000868 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000869 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
870 Reg.RegNum);
871 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000872
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000873 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000874 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000875 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
876 Reg.RegNum);
877 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000878
879 bool isGPR64sp0() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000880 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000881 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
882 }
883
Sam Parker5f934642017-08-31 09:27:04 +0000884 template<int64_t Angle, int64_t Remainder>
885 bool isComplexRotation() const {
886 if (!isImm()) return false;
887
888 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
889 if (!CE) return false;
890 uint64_t Value = CE->getValue();
891
892 return (Value % Angle == Remainder && Value <= 270);
893 }
894
Tim Northover3b0846e2014-05-24 12:50:23 +0000895 /// Is this a vector list with the type implicit (presumably attached to the
896 /// instruction itself)?
897 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
898 return Kind == k_VectorList && VectorList.Count == NumRegs &&
899 !VectorList.ElementKind;
900 }
901
902 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
903 bool isTypedVectorList() const {
904 if (Kind != k_VectorList)
905 return false;
906 if (VectorList.Count != NumRegs)
907 return false;
908 if (VectorList.ElementKind != ElementKind)
909 return false;
910 return VectorList.NumElements == NumElements;
911 }
912
913 bool isVectorIndex1() const {
914 return Kind == k_VectorIndex && VectorIndex.Val == 1;
915 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000916
Tim Northover3b0846e2014-05-24 12:50:23 +0000917 bool isVectorIndexB() const {
918 return Kind == k_VectorIndex && VectorIndex.Val < 16;
919 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000920
Tim Northover3b0846e2014-05-24 12:50:23 +0000921 bool isVectorIndexH() const {
922 return Kind == k_VectorIndex && VectorIndex.Val < 8;
923 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000924
Tim Northover3b0846e2014-05-24 12:50:23 +0000925 bool isVectorIndexS() const {
926 return Kind == k_VectorIndex && VectorIndex.Val < 4;
927 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000928
Tim Northover3b0846e2014-05-24 12:50:23 +0000929 bool isVectorIndexD() const {
930 return Kind == k_VectorIndex && VectorIndex.Val < 2;
931 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000932
Tim Northover3b0846e2014-05-24 12:50:23 +0000933 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000934
Tim Northover3b0846e2014-05-24 12:50:23 +0000935 bool isTokenEqual(StringRef Str) const {
936 return Kind == k_Token && getToken() == Str;
937 }
938 bool isSysCR() const { return Kind == k_SysCR; }
939 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000940 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000941 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
942 bool isShifter() const {
943 if (!isShiftExtend())
944 return false;
945
946 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
947 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
948 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
949 ST == AArch64_AM::MSL);
950 }
951 bool isExtend() const {
952 if (!isShiftExtend())
953 return false;
954
955 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
956 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
957 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
958 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
959 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
960 ET == AArch64_AM::LSL) &&
961 getShiftExtendAmount() <= 4;
962 }
963
964 bool isExtend64() const {
965 if (!isExtend())
966 return false;
967 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
968 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
969 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
970 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000971
Tim Northover3b0846e2014-05-24 12:50:23 +0000972 bool isExtendLSL64() const {
973 if (!isExtend())
974 return false;
975 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
976 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
977 ET == AArch64_AM::LSL) &&
978 getShiftExtendAmount() <= 4;
979 }
980
981 template<int Width> bool isMemXExtend() const {
982 if (!isExtend())
983 return false;
984 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
985 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
986 (getShiftExtendAmount() == Log2_32(Width / 8) ||
987 getShiftExtendAmount() == 0);
988 }
989
990 template<int Width> bool isMemWExtend() const {
991 if (!isExtend())
992 return false;
993 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
994 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
995 (getShiftExtendAmount() == Log2_32(Width / 8) ||
996 getShiftExtendAmount() == 0);
997 }
998
999 template <unsigned width>
1000 bool isArithmeticShifter() const {
1001 if (!isShifter())
1002 return false;
1003
1004 // An arithmetic shifter is LSL, LSR, or ASR.
1005 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1006 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1007 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1008 }
1009
1010 template <unsigned width>
1011 bool isLogicalShifter() const {
1012 if (!isShifter())
1013 return false;
1014
1015 // A logical shifter is LSL, LSR, ASR or ROR.
1016 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1017 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1018 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1019 getShiftExtendAmount() < width;
1020 }
1021
1022 bool isMovImm32Shifter() const {
1023 if (!isShifter())
1024 return false;
1025
1026 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1027 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1028 if (ST != AArch64_AM::LSL)
1029 return false;
1030 uint64_t Val = getShiftExtendAmount();
1031 return (Val == 0 || Val == 16);
1032 }
1033
1034 bool isMovImm64Shifter() const {
1035 if (!isShifter())
1036 return false;
1037
1038 // A MOVi shifter is LSL of 0 or 16.
1039 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1040 if (ST != AArch64_AM::LSL)
1041 return false;
1042 uint64_t Val = getShiftExtendAmount();
1043 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1044 }
1045
1046 bool isLogicalVecShifter() const {
1047 if (!isShifter())
1048 return false;
1049
1050 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1051 unsigned Shift = getShiftExtendAmount();
1052 return getShiftExtendType() == AArch64_AM::LSL &&
1053 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1054 }
1055
1056 bool isLogicalVecHalfWordShifter() const {
1057 if (!isLogicalVecShifter())
1058 return false;
1059
1060 // A logical vector shifter is a left shift by 0 or 8.
1061 unsigned Shift = getShiftExtendAmount();
1062 return getShiftExtendType() == AArch64_AM::LSL &&
1063 (Shift == 0 || Shift == 8);
1064 }
1065
1066 bool isMoveVecShifter() const {
1067 if (!isShiftExtend())
1068 return false;
1069
1070 // A logical vector shifter is a left shift by 8 or 16.
1071 unsigned Shift = getShiftExtendAmount();
1072 return getShiftExtendType() == AArch64_AM::MSL &&
1073 (Shift == 8 || Shift == 16);
1074 }
1075
1076 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1077 // to LDUR/STUR when the offset is not legal for the former but is for
1078 // the latter. As such, in addition to checking for being a legal unscaled
1079 // address, also check that it is not a legal scaled address. This avoids
1080 // ambiguity in the matcher.
1081 template<int Width>
1082 bool isSImm9OffsetFB() const {
1083 return isSImm9() && !isUImm12Offset<Width / 8>();
1084 }
1085
1086 bool isAdrpLabel() const {
1087 // Validation was handled during parsing, so we just sanity check that
1088 // something didn't go haywire.
1089 if (!isImm())
1090 return false;
1091
1092 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1093 int64_t Val = CE->getValue();
1094 int64_t Min = - (4096 * (1LL << (21 - 1)));
1095 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1096 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1097 }
1098
1099 return true;
1100 }
1101
1102 bool isAdrLabel() const {
1103 // Validation was handled during parsing, so we just sanity check that
1104 // something didn't go haywire.
1105 if (!isImm())
1106 return false;
1107
1108 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1109 int64_t Val = CE->getValue();
1110 int64_t Min = - (1LL << (21 - 1));
1111 int64_t Max = ((1LL << (21 - 1)) - 1);
1112 return Val >= Min && Val <= Max;
1113 }
1114
1115 return true;
1116 }
1117
1118 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1119 // Add as immediates when possible. Null MCExpr = 0.
1120 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001121 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001122 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001123 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001124 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001125 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001126 }
1127
1128 void addRegOperands(MCInst &Inst, unsigned N) const {
1129 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001130 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001131 }
1132
1133 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1134 assert(N == 1 && "Invalid number of operands!");
1135 assert(
1136 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1137
1138 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1139 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1140 RI->getEncodingValue(getReg()));
1141
Jim Grosbache9119e42015-05-13 18:37:00 +00001142 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001143 }
1144
1145 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1146 assert(N == 1 && "Invalid number of operands!");
1147 assert(
1148 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001149 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001150 }
1151
1152 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1153 assert(N == 1 && "Invalid number of operands!");
1154 assert(
1155 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001156 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001157 }
1158
1159 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1160 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001161 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001162 }
1163
1164 template <unsigned NumRegs>
1165 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1166 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001167 static const unsigned FirstRegs[] = { AArch64::D0,
1168 AArch64::D0_D1,
1169 AArch64::D0_D1_D2,
1170 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001171 unsigned FirstReg = FirstRegs[NumRegs - 1];
1172
1173 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001174 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001175 }
1176
1177 template <unsigned NumRegs>
1178 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1179 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001180 static const unsigned FirstRegs[] = { AArch64::Q0,
1181 AArch64::Q0_Q1,
1182 AArch64::Q0_Q1_Q2,
1183 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001184 unsigned FirstReg = FirstRegs[NumRegs - 1];
1185
1186 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001187 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001188 }
1189
1190 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1191 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001192 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001193 }
1194
1195 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1196 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001197 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001198 }
1199
1200 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1201 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001202 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001203 }
1204
1205 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1206 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001207 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001208 }
1209
1210 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1211 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001212 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001213 }
1214
1215 void addImmOperands(MCInst &Inst, unsigned N) const {
1216 assert(N == 1 && "Invalid number of operands!");
1217 // If this is a pageoff symrefexpr with an addend, adjust the addend
1218 // to be only the page-offset portion. Otherwise, just add the expr
1219 // as-is.
1220 addExpr(Inst, getImm());
1221 }
1222
1223 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1224 assert(N == 2 && "Invalid number of operands!");
1225 if (isShiftedImm()) {
1226 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001227 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001228 } else {
1229 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001230 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001231 }
1232 }
1233
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001234 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1235 assert(N == 2 && "Invalid number of operands!");
1236
1237 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1238 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1239 int64_t Val = -CE->getValue();
1240 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1241
1242 Inst.addOperand(MCOperand::createImm(Val));
1243 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1244 }
1245
Tim Northover3b0846e2014-05-24 12:50:23 +00001246 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1247 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001248 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001249 }
1250
1251 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1252 assert(N == 1 && "Invalid number of operands!");
1253 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1254 if (!MCE)
1255 addExpr(Inst, getImm());
1256 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001257 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001258 }
1259
1260 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1261 addImmOperands(Inst, N);
1262 }
1263
1264 template<int Scale>
1265 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1266 assert(N == 1 && "Invalid number of operands!");
1267 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1268
1269 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001270 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001271 return;
1272 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001273 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001274 }
1275
1276 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1277 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001278 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001279 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001280 }
1281
Sam Parker6d42de72017-08-11 13:14:00 +00001282 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1283 assert(N == 1 && "Invalid number of operands!");
1284 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1285 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1286 }
1287
Tim Northover3b0846e2014-05-24 12:50:23 +00001288 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1289 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001290 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001291 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001292 }
1293
1294 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1295 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001296 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001297 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001298 }
1299
1300 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1301 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001302 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001303 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001304 }
1305
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001306 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1307 assert(N == 1 && "Invalid number of operands!");
1308 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1309 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1310 }
1311
Tim Northover3b0846e2014-05-24 12:50:23 +00001312 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1313 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001314 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001315 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001316 }
1317
1318 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1319 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001320 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001321 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001322 }
1323
1324 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1325 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001326 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001327 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001328 }
1329
1330 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1331 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001332 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001333 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001334 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001335 }
1336
1337 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1338 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001339 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001340 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001341 }
1342
1343 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1344 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001345 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001346 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001347 }
1348
1349 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1350 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001351 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001352 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001353 }
1354
1355 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1356 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001357 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001358 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001359 }
1360
1361 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1362 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001363 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001364 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001365 }
1366
1367 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1368 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001369 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001370 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001371 }
1372
1373 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1374 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001375 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001376 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001377 }
1378
1379 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1380 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001381 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001382 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001383 }
1384
1385 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1386 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001387 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001388 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001389 }
1390
1391 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1392 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001393 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001394 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001395 }
1396
1397 void addLogicalImm32Operands(MCInst &Inst, unsigned N) const {
1398 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001399 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +00001400 uint64_t encoding =
1401 AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001402 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001403 }
1404
1405 void addLogicalImm64Operands(MCInst &Inst, unsigned N) const {
1406 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001407 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001408 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001409 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001410 }
1411
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001412 void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
1413 assert(N == 1 && "Invalid number of operands!");
1414 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1415 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
1416 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001417 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001418 }
1419
1420 void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
1421 assert(N == 1 && "Invalid number of operands!");
1422 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1423 uint64_t encoding =
1424 AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001425 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001426 }
1427
Tim Northover3b0846e2014-05-24 12:50:23 +00001428 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1429 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001430 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001431 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001432 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001433 }
1434
1435 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1436 // Branch operands don't encode the low bits, so shift them off
1437 // here. If it's a label, however, just put it on directly as there's
1438 // not enough information now to do anything.
1439 assert(N == 1 && "Invalid number of operands!");
1440 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1441 if (!MCE) {
1442 addExpr(Inst, getImm());
1443 return;
1444 }
1445 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001446 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001447 }
1448
1449 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1450 // Branch operands don't encode the low bits, so shift them off
1451 // here. If it's a label, however, just put it on directly as there's
1452 // not enough information now to do anything.
1453 assert(N == 1 && "Invalid number of operands!");
1454 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1455 if (!MCE) {
1456 addExpr(Inst, getImm());
1457 return;
1458 }
1459 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001460 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001461 }
1462
1463 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1464 // Branch operands don't encode the low bits, so shift them off
1465 // here. If it's a label, however, just put it on directly as there's
1466 // not enough information now to do anything.
1467 assert(N == 1 && "Invalid number of operands!");
1468 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1469 if (!MCE) {
1470 addExpr(Inst, getImm());
1471 return;
1472 }
1473 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001474 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001475 }
1476
1477 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1478 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001479 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001480 }
1481
1482 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1483 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001484 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001485 }
1486
1487 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1488 assert(N == 1 && "Invalid number of operands!");
1489
Jim Grosbache9119e42015-05-13 18:37:00 +00001490 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001491 }
1492
1493 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1494 assert(N == 1 && "Invalid number of operands!");
1495
Jim Grosbache9119e42015-05-13 18:37:00 +00001496 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001497 }
1498
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001499 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1500 assert(N == 1 && "Invalid number of operands!");
1501
1502 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1503 }
1504
1505 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001506 assert(N == 1 && "Invalid number of operands!");
1507
Jim Grosbache9119e42015-05-13 18:37:00 +00001508 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001509 }
1510
1511 void addSysCROperands(MCInst &Inst, unsigned N) const {
1512 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001513 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001514 }
1515
1516 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1517 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001518 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001519 }
1520
Oliver Stannarda34e4702015-12-01 10:48:51 +00001521 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1522 assert(N == 1 && "Invalid number of operands!");
1523 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1524 }
1525
Tim Northover3b0846e2014-05-24 12:50:23 +00001526 void addShifterOperands(MCInst &Inst, unsigned N) const {
1527 assert(N == 1 && "Invalid number of operands!");
1528 unsigned Imm =
1529 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001530 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001531 }
1532
1533 void addExtendOperands(MCInst &Inst, unsigned N) const {
1534 assert(N == 1 && "Invalid number of operands!");
1535 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1536 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1537 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001538 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001539 }
1540
1541 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1542 assert(N == 1 && "Invalid number of operands!");
1543 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1544 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1545 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001546 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001547 }
1548
1549 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1550 assert(N == 2 && "Invalid number of operands!");
1551 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1552 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001553 Inst.addOperand(MCOperand::createImm(IsSigned));
1554 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001555 }
1556
1557 // For 8-bit load/store instructions with a register offset, both the
1558 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1559 // they're disambiguated by whether the shift was explicit or implicit rather
1560 // than its size.
1561 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1562 assert(N == 2 && "Invalid number of operands!");
1563 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1564 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001565 Inst.addOperand(MCOperand::createImm(IsSigned));
1566 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001567 }
1568
1569 template<int Shift>
1570 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1571 assert(N == 1 && "Invalid number of operands!");
1572
1573 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1574 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001575 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001576 }
1577
1578 template<int Shift>
1579 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1580 assert(N == 1 && "Invalid number of operands!");
1581
1582 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1583 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001584 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001585 }
1586
Sam Parker5f934642017-08-31 09:27:04 +00001587 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1588 assert(N == 1 && "Invalid number of operands!");
1589 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1590 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1591 }
1592
1593 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1594 assert(N == 1 && "Invalid number of operands!");
1595 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1596 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1597 }
1598
Tim Northover3b0846e2014-05-24 12:50:23 +00001599 void print(raw_ostream &OS) const override;
1600
David Blaikie960ea3f2014-06-08 16:18:35 +00001601 static std::unique_ptr<AArch64Operand>
1602 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1603 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001604 Op->Tok.Data = Str.data();
1605 Op->Tok.Length = Str.size();
1606 Op->Tok.IsSuffix = IsSuffix;
1607 Op->StartLoc = S;
1608 Op->EndLoc = S;
1609 return Op;
1610 }
1611
David Blaikie960ea3f2014-06-08 16:18:35 +00001612 static std::unique_ptr<AArch64Operand>
Florian Hahnc4422242017-11-07 13:07:50 +00001613 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001614 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001615 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001616 Op->Reg.Kind = Kind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001617 Op->StartLoc = S;
1618 Op->EndLoc = E;
1619 return Op;
1620 }
1621
David Blaikie960ea3f2014-06-08 16:18:35 +00001622 static std::unique_ptr<AArch64Operand>
Florian Hahn91f11e52017-11-07 16:45:48 +00001623 CreateReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1624 SMLoc S, SMLoc E, MCContext &Ctx) {
1625 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1626 Op->Reg.RegNum = RegNum;
1627 Op->Reg.ElementWidth = ElementWidth;
1628 Op->Reg.Kind = Kind;
1629 Op->StartLoc = S;
1630 Op->EndLoc = E;
1631 return Op;
1632 }
1633
1634 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001635 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1636 char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1637 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001638 Op->VectorList.RegNum = RegNum;
1639 Op->VectorList.Count = Count;
1640 Op->VectorList.NumElements = NumElements;
1641 Op->VectorList.ElementKind = ElementKind;
1642 Op->StartLoc = S;
1643 Op->EndLoc = E;
1644 return Op;
1645 }
1646
David Blaikie960ea3f2014-06-08 16:18:35 +00001647 static std::unique_ptr<AArch64Operand>
1648 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1649 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001650 Op->VectorIndex.Val = Idx;
1651 Op->StartLoc = S;
1652 Op->EndLoc = E;
1653 return Op;
1654 }
1655
David Blaikie960ea3f2014-06-08 16:18:35 +00001656 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1657 SMLoc E, MCContext &Ctx) {
1658 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001659 Op->Imm.Val = Val;
1660 Op->StartLoc = S;
1661 Op->EndLoc = E;
1662 return Op;
1663 }
1664
David Blaikie960ea3f2014-06-08 16:18:35 +00001665 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1666 unsigned ShiftAmount,
1667 SMLoc S, SMLoc E,
1668 MCContext &Ctx) {
1669 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001670 Op->ShiftedImm .Val = Val;
1671 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1672 Op->StartLoc = S;
1673 Op->EndLoc = E;
1674 return Op;
1675 }
1676
David Blaikie960ea3f2014-06-08 16:18:35 +00001677 static std::unique_ptr<AArch64Operand>
1678 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1679 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001680 Op->CondCode.Code = Code;
1681 Op->StartLoc = S;
1682 Op->EndLoc = E;
1683 return Op;
1684 }
1685
David Blaikie960ea3f2014-06-08 16:18:35 +00001686 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1687 MCContext &Ctx) {
1688 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001689 Op->FPImm.Val = Val;
1690 Op->StartLoc = S;
1691 Op->EndLoc = S;
1692 return Op;
1693 }
1694
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001695 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1696 StringRef Str,
1697 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001698 MCContext &Ctx) {
1699 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001700 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001701 Op->Barrier.Data = Str.data();
1702 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001703 Op->StartLoc = S;
1704 Op->EndLoc = S;
1705 return Op;
1706 }
1707
Tim Northover7cd58932015-01-22 17:23:04 +00001708 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1709 uint32_t MRSReg,
1710 uint32_t MSRReg,
1711 uint32_t PStateField,
1712 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001713 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001714 Op->SysReg.Data = Str.data();
1715 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001716 Op->SysReg.MRSReg = MRSReg;
1717 Op->SysReg.MSRReg = MSRReg;
1718 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001719 Op->StartLoc = S;
1720 Op->EndLoc = S;
1721 return Op;
1722 }
1723
David Blaikie960ea3f2014-06-08 16:18:35 +00001724 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1725 SMLoc E, MCContext &Ctx) {
1726 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001727 Op->SysCRImm.Val = Val;
1728 Op->StartLoc = S;
1729 Op->EndLoc = E;
1730 return Op;
1731 }
1732
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001733 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1734 StringRef Str,
1735 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001736 MCContext &Ctx) {
1737 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001738 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001739 Op->Barrier.Data = Str.data();
1740 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001741 Op->StartLoc = S;
1742 Op->EndLoc = S;
1743 return Op;
1744 }
1745
Oliver Stannarda34e4702015-12-01 10:48:51 +00001746 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1747 StringRef Str,
1748 SMLoc S,
1749 MCContext &Ctx) {
1750 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1751 Op->PSBHint.Val = Val;
1752 Op->PSBHint.Data = Str.data();
1753 Op->PSBHint.Length = Str.size();
1754 Op->StartLoc = S;
1755 Op->EndLoc = S;
1756 return Op;
1757 }
1758
David Blaikie960ea3f2014-06-08 16:18:35 +00001759 static std::unique_ptr<AArch64Operand>
1760 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1761 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1762 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001763 Op->ShiftExtend.Type = ShOp;
1764 Op->ShiftExtend.Amount = Val;
1765 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1766 Op->StartLoc = S;
1767 Op->EndLoc = E;
1768 return Op;
1769 }
1770};
1771
1772} // end anonymous namespace.
1773
1774void AArch64Operand::print(raw_ostream &OS) const {
1775 switch (Kind) {
1776 case k_FPImm:
1777 OS << "<fpimm " << getFPImm() << "("
1778 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1779 break;
1780 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001781 StringRef Name = getBarrierName();
1782 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001783 OS << "<barrier " << Name << ">";
1784 else
1785 OS << "<barrier invalid #" << getBarrier() << ">";
1786 break;
1787 }
1788 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001789 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001790 break;
1791 case k_ShiftedImm: {
1792 unsigned Shift = getShiftedImmShift();
1793 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001794 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001795 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1796 break;
1797 }
1798 case k_CondCode:
1799 OS << "<condcode " << getCondCode() << ">";
1800 break;
1801 case k_Register:
1802 OS << "<register " << getReg() << ">";
1803 break;
1804 case k_VectorList: {
1805 OS << "<vectorlist ";
1806 unsigned Reg = getVectorListStart();
1807 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1808 OS << Reg + i << " ";
1809 OS << ">";
1810 break;
1811 }
1812 case k_VectorIndex:
1813 OS << "<vectorindex " << getVectorIndex() << ">";
1814 break;
1815 case k_SysReg:
1816 OS << "<sysreg: " << getSysReg() << '>';
1817 break;
1818 case k_Token:
1819 OS << "'" << getToken() << "'";
1820 break;
1821 case k_SysCR:
1822 OS << "c" << getSysCR();
1823 break;
1824 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001825 StringRef Name = getPrefetchName();
1826 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001827 OS << "<prfop " << Name << ">";
1828 else
1829 OS << "<prfop invalid #" << getPrefetch() << ">";
1830 break;
1831 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001832 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001833 OS << getPSBHintName();
1834 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001835 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001836 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1837 << getShiftExtendAmount();
1838 if (!hasShiftExtendAmount())
1839 OS << "<imp>";
1840 OS << '>';
1841 break;
1842 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001843}
1844
1845/// @name Auto-generated Match Functions
1846/// {
1847
1848static unsigned MatchRegisterName(StringRef Name);
1849
1850/// }
1851
Florian Hahnc4422242017-11-07 13:07:50 +00001852static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001853 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001854 .Case("v0", AArch64::Q0)
1855 .Case("v1", AArch64::Q1)
1856 .Case("v2", AArch64::Q2)
1857 .Case("v3", AArch64::Q3)
1858 .Case("v4", AArch64::Q4)
1859 .Case("v5", AArch64::Q5)
1860 .Case("v6", AArch64::Q6)
1861 .Case("v7", AArch64::Q7)
1862 .Case("v8", AArch64::Q8)
1863 .Case("v9", AArch64::Q9)
1864 .Case("v10", AArch64::Q10)
1865 .Case("v11", AArch64::Q11)
1866 .Case("v12", AArch64::Q12)
1867 .Case("v13", AArch64::Q13)
1868 .Case("v14", AArch64::Q14)
1869 .Case("v15", AArch64::Q15)
1870 .Case("v16", AArch64::Q16)
1871 .Case("v17", AArch64::Q17)
1872 .Case("v18", AArch64::Q18)
1873 .Case("v19", AArch64::Q19)
1874 .Case("v20", AArch64::Q20)
1875 .Case("v21", AArch64::Q21)
1876 .Case("v22", AArch64::Q22)
1877 .Case("v23", AArch64::Q23)
1878 .Case("v24", AArch64::Q24)
1879 .Case("v25", AArch64::Q25)
1880 .Case("v26", AArch64::Q26)
1881 .Case("v27", AArch64::Q27)
1882 .Case("v28", AArch64::Q28)
1883 .Case("v29", AArch64::Q29)
1884 .Case("v30", AArch64::Q30)
1885 .Case("v31", AArch64::Q31)
1886 .Default(0);
1887}
1888
1889static bool isValidVectorKind(StringRef Name) {
1890 return StringSwitch<bool>(Name.lower())
1891 .Case(".8b", true)
1892 .Case(".16b", true)
1893 .Case(".4h", true)
1894 .Case(".8h", true)
1895 .Case(".2s", true)
1896 .Case(".4s", true)
1897 .Case(".1d", true)
1898 .Case(".2d", true)
1899 .Case(".1q", true)
1900 // Accept the width neutral ones, too, for verbose syntax. If those
1901 // aren't used in the right places, the token operand won't match so
1902 // all will work out.
1903 .Case(".b", true)
1904 .Case(".h", true)
1905 .Case(".s", true)
1906 .Case(".d", true)
Oliver Stannarde4c3d212015-12-08 12:16:10 +00001907 // Needed for fp16 scalar pairwise reductions
1908 .Case(".2h", true)
Sjoerd Meijer79876332017-08-09 14:59:54 +00001909 // another special case for the ARMv8.2a dot product operand
1910 .Case(".4b", true)
Tim Northover3b0846e2014-05-24 12:50:23 +00001911 .Default(false);
1912}
1913
Florian Hahn91f11e52017-11-07 16:45:48 +00001914static unsigned matchSVEDataVectorRegName(StringRef Name) {
1915 return StringSwitch<unsigned>(Name.lower())
1916 .Case("z0", AArch64::Z0)
1917 .Case("z1", AArch64::Z1)
1918 .Case("z2", AArch64::Z2)
1919 .Case("z3", AArch64::Z3)
1920 .Case("z4", AArch64::Z4)
1921 .Case("z5", AArch64::Z5)
1922 .Case("z6", AArch64::Z6)
1923 .Case("z7", AArch64::Z7)
1924 .Case("z8", AArch64::Z8)
1925 .Case("z9", AArch64::Z9)
1926 .Case("z10", AArch64::Z10)
1927 .Case("z11", AArch64::Z11)
1928 .Case("z12", AArch64::Z12)
1929 .Case("z13", AArch64::Z13)
1930 .Case("z14", AArch64::Z14)
1931 .Case("z15", AArch64::Z15)
1932 .Case("z16", AArch64::Z16)
1933 .Case("z17", AArch64::Z17)
1934 .Case("z18", AArch64::Z18)
1935 .Case("z19", AArch64::Z19)
1936 .Case("z20", AArch64::Z20)
1937 .Case("z21", AArch64::Z21)
1938 .Case("z22", AArch64::Z22)
1939 .Case("z23", AArch64::Z23)
1940 .Case("z24", AArch64::Z24)
1941 .Case("z25", AArch64::Z25)
1942 .Case("z26", AArch64::Z26)
1943 .Case("z27", AArch64::Z27)
1944 .Case("z28", AArch64::Z28)
1945 .Case("z29", AArch64::Z29)
1946 .Case("z30", AArch64::Z30)
1947 .Case("z31", AArch64::Z31)
1948 .Default(0);
1949}
1950
Sander de Smalencd6be962017-12-20 11:02:42 +00001951static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1952 return StringSwitch<unsigned>(Name.lower())
1953 .Case("p0", AArch64::P0)
1954 .Case("p1", AArch64::P1)
1955 .Case("p2", AArch64::P2)
1956 .Case("p3", AArch64::P3)
1957 .Case("p4", AArch64::P4)
1958 .Case("p5", AArch64::P5)
1959 .Case("p6", AArch64::P6)
1960 .Case("p7", AArch64::P7)
1961 .Case("p8", AArch64::P8)
1962 .Case("p9", AArch64::P9)
1963 .Case("p10", AArch64::P10)
1964 .Case("p11", AArch64::P11)
1965 .Case("p12", AArch64::P12)
1966 .Case("p13", AArch64::P13)
1967 .Case("p14", AArch64::P14)
1968 .Case("p15", AArch64::P15)
1969 .Default(0);
1970}
1971
Florian Hahn91f11e52017-11-07 16:45:48 +00001972static bool isValidSVEKind(StringRef Name) {
1973 return StringSwitch<bool>(Name.lower())
1974 .Case(".b", true)
1975 .Case(".h", true)
1976 .Case(".s", true)
1977 .Case(".d", true)
1978 .Case(".q", true)
1979 .Default(false);
1980}
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) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002011 unsigned RegNum = 0;
2012 if ((RegNum = matchSVEDataVectorRegName(Name)))
2013 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2014
Sander de Smalencd6be962017-12-20 11:02:42 +00002015 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2016 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2017
Sander de Smalenc067c302017-12-20 09:45:45 +00002018 if ((RegNum = MatchNeonVectorRegName(Name)))
2019 return Kind == RegKind::NeonVector ? RegNum : 0;
2020
2021 // The parsed register must be of RegKind Scalar
2022 if ((RegNum = MatchRegisterName(Name)))
2023 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002024
Florian Hahnc4422242017-11-07 13:07:50 +00002025 if (!RegNum) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002026 // Check for aliases registered via .req. Canonicalize to lower case.
2027 // That's more consistent since register names are case insensitive, and
2028 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2029 auto Entry = RegisterReqs.find(Name.lower());
2030 if (Entry == RegisterReqs.end())
2031 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002032
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002033 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002034 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002035 RegNum = Entry->getValue().second;
2036 }
2037 return RegNum;
2038}
2039
Tim Northover3b0846e2014-05-24 12:50:23 +00002040/// tryParseRegister - Try to parse a register name. The token must be an
2041/// Identifier when called, and if it is a register name the token is eaten and
2042/// the register is added to the operand list.
2043int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002044 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002045 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002046 if (Tok.isNot(AsmToken::Identifier))
2047 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00002048
2049 std::string lowerCase = Tok.getString().lower();
Florian Hahnc4422242017-11-07 13:07:50 +00002050 unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
Sander de Smalenc067c302017-12-20 09:45:45 +00002051
Tim Northover3b0846e2014-05-24 12:50:23 +00002052 // Also handle a few aliases of registers.
2053 if (RegNum == 0)
2054 RegNum = StringSwitch<unsigned>(lowerCase)
2055 .Case("fp", AArch64::FP)
2056 .Case("lr", AArch64::LR)
2057 .Case("x31", AArch64::XZR)
2058 .Case("w31", AArch64::WZR)
2059 .Default(0);
2060
2061 if (RegNum == 0)
2062 return -1;
2063
2064 Parser.Lex(); // Eat identifier token.
2065 return RegNum;
2066}
2067
2068/// tryMatchVectorRegister - Try to parse a vector register name with optional
2069/// kind specifier. If it is a register specifier, eat the token and return it.
2070int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002071 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002072 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2073 TokError("vector register expected");
2074 return -1;
2075 }
2076
2077 StringRef Name = Parser.getTok().getString();
2078 // If there is a kind specifier, it's separated from the register name by
2079 // a '.'.
2080 size_t Start = 0, Next = Name.find('.');
2081 StringRef Head = Name.slice(Start, Next);
Florian Hahnc4422242017-11-07 13:07:50 +00002082 unsigned RegNum = matchRegisterNameAlias(Head, RegKind::NeonVector);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002083
Tim Northover3b0846e2014-05-24 12:50:23 +00002084 if (RegNum) {
2085 if (Next != StringRef::npos) {
2086 Kind = Name.slice(Next, StringRef::npos);
2087 if (!isValidVectorKind(Kind)) {
2088 TokError("invalid vector kind qualifier");
2089 return -1;
2090 }
2091 }
2092 Parser.Lex(); // Eat the register token.
2093 return RegNum;
2094 }
2095
2096 if (expected)
2097 TokError("vector register expected");
2098 return -1;
2099}
2100
2101/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002102OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002103AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002104 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002105 SMLoc S = getLoc();
2106
2107 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2108 Error(S, "Expected cN operand where 0 <= N <= 15");
2109 return MatchOperand_ParseFail;
2110 }
2111
2112 StringRef Tok = Parser.getTok().getIdentifier();
2113 if (Tok[0] != 'c' && Tok[0] != 'C') {
2114 Error(S, "Expected cN operand where 0 <= N <= 15");
2115 return MatchOperand_ParseFail;
2116 }
2117
2118 uint32_t CRNum;
2119 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2120 if (BadNum || CRNum > 15) {
2121 Error(S, "Expected cN operand where 0 <= N <= 15");
2122 return MatchOperand_ParseFail;
2123 }
2124
2125 Parser.Lex(); // Eat identifier token.
2126 Operands.push_back(
2127 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2128 return MatchOperand_Success;
2129}
2130
2131/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002132OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002133AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002134 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002135 SMLoc S = getLoc();
2136 const AsmToken &Tok = Parser.getTok();
2137 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002138 // Eat optional hash.
2139 if (parseOptionalToken(AsmToken::Hash) ||
2140 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002141 const MCExpr *ImmVal;
2142 if (getParser().parseExpression(ImmVal))
2143 return MatchOperand_ParseFail;
2144
2145 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2146 if (!MCE) {
2147 TokError("immediate value expected for prefetch operand");
2148 return MatchOperand_ParseFail;
2149 }
2150 unsigned prfop = MCE->getValue();
2151 if (prfop > 31) {
2152 TokError("prefetch operand out of range, [0,31] expected");
2153 return MatchOperand_ParseFail;
2154 }
2155
Tim Northovere6ae6762016-07-05 21:23:04 +00002156 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2157 Operands.push_back(AArch64Operand::CreatePrefetch(
2158 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002159 return MatchOperand_Success;
2160 }
2161
2162 if (Tok.isNot(AsmToken::Identifier)) {
2163 TokError("pre-fetch hint expected");
2164 return MatchOperand_ParseFail;
2165 }
2166
Tim Northovere6ae6762016-07-05 21:23:04 +00002167 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2168 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002169 TokError("pre-fetch hint expected");
2170 return MatchOperand_ParseFail;
2171 }
2172
2173 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002174 Operands.push_back(AArch64Operand::CreatePrefetch(
2175 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002176 return MatchOperand_Success;
2177}
2178
Oliver Stannarda34e4702015-12-01 10:48:51 +00002179/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002180OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002181AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2182 MCAsmParser &Parser = getParser();
2183 SMLoc S = getLoc();
2184 const AsmToken &Tok = Parser.getTok();
2185 if (Tok.isNot(AsmToken::Identifier)) {
2186 TokError("invalid operand for instruction");
2187 return MatchOperand_ParseFail;
2188 }
2189
Tim Northovere6ae6762016-07-05 21:23:04 +00002190 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2191 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002192 TokError("invalid operand for instruction");
2193 return MatchOperand_ParseFail;
2194 }
2195
2196 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002197 Operands.push_back(AArch64Operand::CreatePSBHint(
2198 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002199 return MatchOperand_Success;
2200}
2201
Tim Northover3b0846e2014-05-24 12:50:23 +00002202/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2203/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002204OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002205AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002206 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002207 SMLoc S = getLoc();
2208 const MCExpr *Expr;
2209
2210 if (Parser.getTok().is(AsmToken::Hash)) {
2211 Parser.Lex(); // Eat hash token.
2212 }
2213
2214 if (parseSymbolicImmVal(Expr))
2215 return MatchOperand_ParseFail;
2216
2217 AArch64MCExpr::VariantKind ELFRefKind;
2218 MCSymbolRefExpr::VariantKind DarwinRefKind;
2219 int64_t Addend;
2220 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2221 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2222 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2223 // No modifier was specified at all; this is the syntax for an ELF basic
2224 // ADRP relocation (unfortunately).
2225 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002226 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002227 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2228 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2229 Addend != 0) {
2230 Error(S, "gotpage label reference not allowed an addend");
2231 return MatchOperand_ParseFail;
2232 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2233 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2234 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2235 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2236 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2237 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2238 // The operand must be an @page or @gotpage qualified symbolref.
2239 Error(S, "page or gotpage label reference expected");
2240 return MatchOperand_ParseFail;
2241 }
2242 }
2243
2244 // We have either a label reference possibly with addend or an immediate. The
2245 // addend is a raw value here. The linker will adjust it to only reference the
2246 // page.
2247 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2248 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2249
2250 return MatchOperand_Success;
2251}
2252
2253/// tryParseAdrLabel - Parse and validate a source label for the ADR
2254/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002255OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002256AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2257 SMLoc S = getLoc();
2258 const MCExpr *Expr;
2259
Nirav Davee833c6c2016-11-08 18:31:04 +00002260 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002261 if (getParser().parseExpression(Expr))
2262 return MatchOperand_ParseFail;
2263
2264 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2265 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2266
2267 return MatchOperand_Success;
2268}
2269
2270/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002271OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002272AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002273 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002274 SMLoc S = getLoc();
2275
Nirav Davee833c6c2016-11-08 18:31:04 +00002276 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002277
2278 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002279 bool isNegative = parseOptionalToken(AsmToken::Minus);
2280
Tim Northover3b0846e2014-05-24 12:50:23 +00002281 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002282 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002283 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002284 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002285 Val = Tok.getIntVal();
2286 if (Val > 255 || Val < 0) {
2287 TokError("encoded floating point value out of range");
2288 return MatchOperand_ParseFail;
2289 }
2290 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002291 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002292 if (isNegative)
2293 RealVal.changeSign();
2294
Tim Northover3b0846e2014-05-24 12:50:23 +00002295 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002296 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002297
John Brawn5ca5daa2017-04-20 10:13:54 +00002298 // Check for out of range values. As an exception we let Zero through,
2299 // but as tokens instead of an FPImm so that it can be matched by the
2300 // appropriate alias if one exists.
2301 if (RealVal.isPosZero()) {
2302 Parser.Lex(); // Eat the token.
2303 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2304 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2305 return MatchOperand_Success;
2306 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002307 TokError("expected compatible register or floating-point constant");
2308 return MatchOperand_ParseFail;
2309 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002310 }
2311 Parser.Lex(); // Eat the token.
2312 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2313 return MatchOperand_Success;
2314 }
2315
2316 if (!Hash)
2317 return MatchOperand_NoMatch;
2318
2319 TokError("invalid floating point immediate");
2320 return MatchOperand_ParseFail;
2321}
2322
2323/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002324OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002325AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002326 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002327 SMLoc S = getLoc();
2328
2329 if (Parser.getTok().is(AsmToken::Hash))
2330 Parser.Lex(); // Eat '#'
2331 else if (Parser.getTok().isNot(AsmToken::Integer))
2332 // Operand should start from # or should be integer, emit error otherwise.
2333 return MatchOperand_NoMatch;
2334
2335 const MCExpr *Imm;
2336 if (parseSymbolicImmVal(Imm))
2337 return MatchOperand_ParseFail;
2338 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2339 uint64_t ShiftAmount = 0;
2340 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2341 if (MCE) {
2342 int64_t Val = MCE->getValue();
2343 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002344 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002345 ShiftAmount = 12;
2346 }
2347 }
2348 SMLoc E = Parser.getTok().getLoc();
2349 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2350 getContext()));
2351 return MatchOperand_Success;
2352 }
2353
2354 // Eat ','
2355 Parser.Lex();
2356
2357 // The optional operand must be "lsl #N" where N is non-negative.
2358 if (!Parser.getTok().is(AsmToken::Identifier) ||
2359 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2360 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2361 return MatchOperand_ParseFail;
2362 }
2363
2364 // Eat 'lsl'
2365 Parser.Lex();
2366
Nirav Davee833c6c2016-11-08 18:31:04 +00002367 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002368
2369 if (Parser.getTok().isNot(AsmToken::Integer)) {
2370 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2371 return MatchOperand_ParseFail;
2372 }
2373
2374 int64_t ShiftAmount = Parser.getTok().getIntVal();
2375
2376 if (ShiftAmount < 0) {
2377 Error(Parser.getTok().getLoc(), "positive shift amount required");
2378 return MatchOperand_ParseFail;
2379 }
2380 Parser.Lex(); // Eat the number
2381
2382 SMLoc E = Parser.getTok().getLoc();
2383 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2384 S, E, getContext()));
2385 return MatchOperand_Success;
2386}
2387
2388/// parseCondCodeString - Parse a Condition Code string.
2389AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2390 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2391 .Case("eq", AArch64CC::EQ)
2392 .Case("ne", AArch64CC::NE)
2393 .Case("cs", AArch64CC::HS)
2394 .Case("hs", AArch64CC::HS)
2395 .Case("cc", AArch64CC::LO)
2396 .Case("lo", AArch64CC::LO)
2397 .Case("mi", AArch64CC::MI)
2398 .Case("pl", AArch64CC::PL)
2399 .Case("vs", AArch64CC::VS)
2400 .Case("vc", AArch64CC::VC)
2401 .Case("hi", AArch64CC::HI)
2402 .Case("ls", AArch64CC::LS)
2403 .Case("ge", AArch64CC::GE)
2404 .Case("lt", AArch64CC::LT)
2405 .Case("gt", AArch64CC::GT)
2406 .Case("le", AArch64CC::LE)
2407 .Case("al", AArch64CC::AL)
2408 .Case("nv", AArch64CC::NV)
2409 .Default(AArch64CC::Invalid);
2410 return CC;
2411}
2412
2413/// parseCondCode - Parse a Condition Code operand.
2414bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2415 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002416 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002417 SMLoc S = getLoc();
2418 const AsmToken &Tok = Parser.getTok();
2419 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2420
2421 StringRef Cond = Tok.getString();
2422 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2423 if (CC == AArch64CC::Invalid)
2424 return TokError("invalid condition code");
2425 Parser.Lex(); // Eat identifier token.
2426
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002427 if (invertCondCode) {
2428 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2429 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002430 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002431 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002432
2433 Operands.push_back(
2434 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2435 return false;
2436}
2437
2438/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2439/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002440OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002441AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002442 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002443 const AsmToken &Tok = Parser.getTok();
2444 std::string LowerID = Tok.getString().lower();
2445 AArch64_AM::ShiftExtendType ShOp =
2446 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2447 .Case("lsl", AArch64_AM::LSL)
2448 .Case("lsr", AArch64_AM::LSR)
2449 .Case("asr", AArch64_AM::ASR)
2450 .Case("ror", AArch64_AM::ROR)
2451 .Case("msl", AArch64_AM::MSL)
2452 .Case("uxtb", AArch64_AM::UXTB)
2453 .Case("uxth", AArch64_AM::UXTH)
2454 .Case("uxtw", AArch64_AM::UXTW)
2455 .Case("uxtx", AArch64_AM::UXTX)
2456 .Case("sxtb", AArch64_AM::SXTB)
2457 .Case("sxth", AArch64_AM::SXTH)
2458 .Case("sxtw", AArch64_AM::SXTW)
2459 .Case("sxtx", AArch64_AM::SXTX)
2460 .Default(AArch64_AM::InvalidShiftExtend);
2461
2462 if (ShOp == AArch64_AM::InvalidShiftExtend)
2463 return MatchOperand_NoMatch;
2464
2465 SMLoc S = Tok.getLoc();
2466 Parser.Lex();
2467
Nirav Davee833c6c2016-11-08 18:31:04 +00002468 bool Hash = parseOptionalToken(AsmToken::Hash);
2469
Tim Northover3b0846e2014-05-24 12:50:23 +00002470 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2471 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2472 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2473 ShOp == AArch64_AM::MSL) {
2474 // We expect a number here.
2475 TokError("expected #imm after shift specifier");
2476 return MatchOperand_ParseFail;
2477 }
2478
Chad Rosier2ff37b82016-12-27 16:58:09 +00002479 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002480 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2481 Operands.push_back(
2482 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2483 return MatchOperand_Success;
2484 }
2485
Chad Rosier2ff37b82016-12-27 16:58:09 +00002486 // Make sure we do actually have a number, identifier or a parenthesized
2487 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002488 SMLoc E = Parser.getTok().getLoc();
2489 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002490 !Parser.getTok().is(AsmToken::LParen) &&
2491 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002492 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002493 return MatchOperand_ParseFail;
2494 }
2495
2496 const MCExpr *ImmVal;
2497 if (getParser().parseExpression(ImmVal))
2498 return MatchOperand_ParseFail;
2499
2500 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2501 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002502 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002503 return MatchOperand_ParseFail;
2504 }
2505
Jim Grosbach57fd2622014-09-23 22:16:02 +00002506 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002507 Operands.push_back(AArch64Operand::CreateShiftExtend(
2508 ShOp, MCE->getValue(), true, S, E, getContext()));
2509 return MatchOperand_Success;
2510}
2511
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002512static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2513 if (FBS[AArch64::HasV8_1aOps])
2514 Str += "ARMv8.1a";
2515 else if (FBS[AArch64::HasV8_2aOps])
2516 Str += "ARMv8.2a";
2517 else
2518 Str += "(unknown)";
2519}
2520
2521void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2522 SMLoc S) {
2523 const uint16_t Op2 = Encoding & 7;
2524 const uint16_t Cm = (Encoding & 0x78) >> 3;
2525 const uint16_t Cn = (Encoding & 0x780) >> 7;
2526 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2527
2528 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2529
2530 Operands.push_back(
2531 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2532 Operands.push_back(
2533 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2534 Operands.push_back(
2535 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2536 Expr = MCConstantExpr::create(Op2, getContext());
2537 Operands.push_back(
2538 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2539}
2540
Tim Northover3b0846e2014-05-24 12:50:23 +00002541/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2542/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2543bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2544 OperandVector &Operands) {
2545 if (Name.find('.') != StringRef::npos)
2546 return TokError("invalid operand");
2547
2548 Mnemonic = Name;
2549 Operands.push_back(
2550 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2551
Rafael Espindola961d4692014-11-11 05:18:41 +00002552 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002553 const AsmToken &Tok = Parser.getTok();
2554 StringRef Op = Tok.getString();
2555 SMLoc S = Tok.getLoc();
2556
Tim Northover3b0846e2014-05-24 12:50:23 +00002557 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002558 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2559 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002560 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002561 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2562 std::string Str("IC " + std::string(IC->Name) + " requires ");
2563 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2564 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002565 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002566 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002567 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002568 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2569 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002570 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002571 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2572 std::string Str("DC " + std::string(DC->Name) + " requires ");
2573 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2574 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002575 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002576 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002577 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002578 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2579 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002580 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002581 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2582 std::string Str("AT " + std::string(AT->Name) + " requires ");
2583 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2584 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002585 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002586 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002587 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002588 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2589 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002590 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002591 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2592 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2593 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2594 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002595 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002596 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002597 }
2598
Tim Northover3b0846e2014-05-24 12:50:23 +00002599 Parser.Lex(); // Eat operand.
2600
2601 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2602 bool HasRegister = false;
2603
2604 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002605 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002606 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2607 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002608 HasRegister = true;
2609 }
2610
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002611 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002612 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002613 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002614 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002615
Nirav Davee833c6c2016-11-08 18:31:04 +00002616 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2617 return true;
2618
Tim Northover3b0846e2014-05-24 12:50:23 +00002619 return false;
2620}
2621
Alex Bradbury58eba092016-11-01 16:32:05 +00002622OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002623AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002624 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002625 const AsmToken &Tok = Parser.getTok();
2626
2627 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002628 if (parseOptionalToken(AsmToken::Hash) ||
2629 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002630 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002631 const MCExpr *ImmVal;
2632 SMLoc ExprLoc = getLoc();
2633 if (getParser().parseExpression(ImmVal))
2634 return MatchOperand_ParseFail;
2635 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2636 if (!MCE) {
2637 Error(ExprLoc, "immediate value expected for barrier operand");
2638 return MatchOperand_ParseFail;
2639 }
2640 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2641 Error(ExprLoc, "barrier operand out of range");
2642 return MatchOperand_ParseFail;
2643 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002644 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2645 Operands.push_back(AArch64Operand::CreateBarrier(
2646 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002647 return MatchOperand_Success;
2648 }
2649
2650 if (Tok.isNot(AsmToken::Identifier)) {
2651 TokError("invalid operand for instruction");
2652 return MatchOperand_ParseFail;
2653 }
2654
Tim Northover3b0846e2014-05-24 12:50:23 +00002655 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002656 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2657 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002658 TokError("'sy' or #imm operand expected");
2659 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002660 } else if (!DB) {
2661 TokError("invalid barrier option name");
2662 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002663 }
2664
Tim Northovere6ae6762016-07-05 21:23:04 +00002665 Operands.push_back(AArch64Operand::CreateBarrier(
2666 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002667 Parser.Lex(); // Consume the option
2668
2669 return MatchOperand_Success;
2670}
2671
Alex Bradbury58eba092016-11-01 16:32:05 +00002672OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002673AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002674 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002675 const AsmToken &Tok = Parser.getTok();
2676
2677 if (Tok.isNot(AsmToken::Identifier))
2678 return MatchOperand_NoMatch;
2679
Tim Northovere6ae6762016-07-05 21:23:04 +00002680 int MRSReg, MSRReg;
2681 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2682 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2683 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2684 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2685 } else
2686 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002687
Tim Northovere6ae6762016-07-05 21:23:04 +00002688 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2689 unsigned PStateImm = -1;
2690 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2691 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002692
Tim Northovere6ae6762016-07-05 21:23:04 +00002693 Operands.push_back(
2694 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2695 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002696 Parser.Lex(); // Eat identifier
2697
2698 return MatchOperand_Success;
2699}
2700
Florian Hahnc4422242017-11-07 13:07:50 +00002701/// tryParseNeonVectorRegister - Parse a vector register operand.
2702bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002703 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002704 if (Parser.getTok().isNot(AsmToken::Identifier))
2705 return true;
2706
2707 SMLoc S = getLoc();
2708 // Check for a vector register specifier first.
2709 StringRef Kind;
2710 int64_t Reg = tryMatchVectorRegister(Kind, false);
2711 if (Reg == -1)
2712 return true;
2713 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00002714 AArch64Operand::CreateReg(Reg, RegKind::NeonVector, S, getLoc(),
2715 getContext()));
2716
Tim Northover3b0846e2014-05-24 12:50:23 +00002717 // If there was an explicit qualifier, that goes on as a literal text
2718 // operand.
2719 if (!Kind.empty())
2720 Operands.push_back(
2721 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2722
2723 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002724 SMLoc SIdx = getLoc();
2725 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002726 const MCExpr *ImmVal;
2727 if (getParser().parseExpression(ImmVal))
2728 return false;
2729 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2730 if (!MCE) {
2731 TokError("immediate value expected for vector index");
2732 return false;
2733 }
2734
2735 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002736
Nirav Davee833c6c2016-11-08 18:31:04 +00002737 if (parseToken(AsmToken::RBrac, "']' expected"))
2738 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002739
2740 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2741 E, getContext()));
2742 }
2743
2744 return false;
2745}
2746
Florian Hahn91f11e52017-11-07 16:45:48 +00002747// tryParseSVEDataVectorRegister - Try to parse a SVE vector register name with
2748// optional kind specifier. If it is a register specifier, eat the token
2749// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002750OperandMatchResultTy
2751AArch64AsmParser::tryParseSVERegister(int &Reg, StringRef &Kind,
2752 RegKind MatchKind) {
2753 MCAsmParser &Parser = getParser();
2754 const AsmToken &Tok = Parser.getTok();
2755
Florian Hahn91f11e52017-11-07 16:45:48 +00002756 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002757 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002758
2759 StringRef Name = Tok.getString();
2760 // If there is a kind specifier, it's separated from the register name by
2761 // a '.'.
2762 size_t Start = 0, Next = Name.find('.');
2763 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002764 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002765
2766 if (RegNum) {
2767 if (Next != StringRef::npos) {
2768 Kind = Name.slice(Next, StringRef::npos);
2769 if (!isValidSVEKind(Kind)) {
2770 TokError("invalid sve vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002771 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002772 }
2773 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002774 Parser.Lex(); // Eat the register token.
2775
2776 Reg = RegNum;
2777 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002778 }
2779
Sander de Smalen8e607342017-11-15 15:44:43 +00002780 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002781}
2782
Sander de Smalencd6be962017-12-20 11:02:42 +00002783/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2784OperandMatchResultTy
2785AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2786 // Check for a SVE predicate register specifier first.
2787 const SMLoc S = getLoc();
2788 StringRef Kind;
2789 int RegNum = -1;
2790 auto Res = tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
2791 if (Res != MatchOperand_Success)
2792 return Res;
2793
2794 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
2795 .Case("", -1)
2796 .Case(".b", 8)
2797 .Case(".h", 16)
2798 .Case(".s", 32)
2799 .Case(".d", 64)
2800 .Case(".q", 128)
2801 .Default(0);
2802
2803 if (!ElementWidth)
2804 return MatchOperand_NoMatch;
2805
2806 Operands.push_back(
2807 AArch64Operand::CreateReg(RegNum, RegKind::SVEPredicateVector,
2808 ElementWidth, S, getLoc(), getContext()));
2809
2810 return MatchOperand_Success;
2811}
2812
Tim Northover3b0846e2014-05-24 12:50:23 +00002813/// parseRegister - Parse a non-vector register operand.
2814bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2815 SMLoc S = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00002816 // Try for a vector (neon) register.
2817 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002818 return false;
2819
2820 // Try for a scalar register.
2821 int64_t Reg = tryParseRegister();
2822 if (Reg == -1)
2823 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002824 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2825 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002826
Tim Northover3b0846e2014-05-24 12:50:23 +00002827 return false;
2828}
2829
2830bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002831 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002832 bool HasELFModifier = false;
2833 AArch64MCExpr::VariantKind RefKind;
2834
Nirav Davee833c6c2016-11-08 18:31:04 +00002835 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002836 HasELFModifier = true;
2837
Nirav Davee833c6c2016-11-08 18:31:04 +00002838 if (Parser.getTok().isNot(AsmToken::Identifier))
2839 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002840
2841 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2842 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2843 .Case("lo12", AArch64MCExpr::VK_LO12)
2844 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2845 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2846 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2847 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2848 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2849 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2850 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2851 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2852 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2853 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2854 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2855 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2856 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2857 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2858 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2859 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2860 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2861 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2862 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2863 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2864 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2865 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2866 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2867 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2868 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2869 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2870 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2871 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2872 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2873 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2874 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2875 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2876 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2877 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2878 .Default(AArch64MCExpr::VK_INVALID);
2879
Nirav Davee833c6c2016-11-08 18:31:04 +00002880 if (RefKind == AArch64MCExpr::VK_INVALID)
2881 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002882
2883 Parser.Lex(); // Eat identifier
2884
Nirav Davee833c6c2016-11-08 18:31:04 +00002885 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002886 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002887 }
2888
2889 if (getParser().parseExpression(ImmVal))
2890 return true;
2891
2892 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002893 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002894
2895 return false;
2896}
2897
2898/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2899bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002900 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002901 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2902 SMLoc S = getLoc();
2903 Parser.Lex(); // Eat left bracket token.
2904 StringRef Kind;
2905 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2906 if (FirstReg == -1)
2907 return true;
2908 int64_t PrevReg = FirstReg;
2909 unsigned Count = 1;
2910
Nirav Davee833c6c2016-11-08 18:31:04 +00002911 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002912 SMLoc Loc = getLoc();
2913 StringRef NextKind;
2914 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2915 if (Reg == -1)
2916 return true;
2917 // Any Kind suffices must match on all regs in the list.
2918 if (Kind != NextKind)
2919 return Error(Loc, "mismatched register size suffix");
2920
2921 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2922
2923 if (Space == 0 || Space > 3) {
2924 return Error(Loc, "invalid number of vectors");
2925 }
2926
2927 Count += Space;
2928 }
2929 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002930 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002931 SMLoc Loc = getLoc();
2932 StringRef NextKind;
2933 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2934 if (Reg == -1)
2935 return true;
2936 // Any Kind suffices must match on all regs in the list.
2937 if (Kind != NextKind)
2938 return Error(Loc, "mismatched register size suffix");
2939
2940 // Registers must be incremental (with wraparound at 31)
2941 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2942 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2943 return Error(Loc, "registers must be sequential");
2944
2945 PrevReg = Reg;
2946 ++Count;
2947 }
2948 }
2949
Nirav Davee833c6c2016-11-08 18:31:04 +00002950 if (parseToken(AsmToken::RCurly, "'}' expected"))
2951 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002952
2953 if (Count > 4)
2954 return Error(S, "invalid number of vectors");
2955
2956 unsigned NumElements = 0;
2957 char ElementKind = 0;
2958 if (!Kind.empty())
2959 parseValidVectorKind(Kind, NumElements, ElementKind);
2960
2961 Operands.push_back(AArch64Operand::CreateVectorList(
2962 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
2963
2964 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002965 SMLoc SIdx = getLoc();
2966 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002967 const MCExpr *ImmVal;
2968 if (getParser().parseExpression(ImmVal))
2969 return false;
2970 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2971 if (!MCE) {
2972 TokError("immediate value expected for vector index");
2973 return false;
2974 }
2975
2976 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002977 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002978 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002979
2980 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2981 E, getContext()));
2982 }
2983 return false;
2984}
2985
Alex Bradbury58eba092016-11-01 16:32:05 +00002986OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002987AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002988 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002989 const AsmToken &Tok = Parser.getTok();
2990 if (!Tok.is(AsmToken::Identifier))
2991 return MatchOperand_NoMatch;
2992
Florian Hahnc4422242017-11-07 13:07:50 +00002993 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00002994
2995 MCContext &Ctx = getContext();
2996 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
2997 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
2998 return MatchOperand_NoMatch;
2999
3000 SMLoc S = getLoc();
3001 Parser.Lex(); // Eat register
3002
Nirav Davee833c6c2016-11-08 18:31:04 +00003003 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003004 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003005 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003006 return MatchOperand_Success;
3007 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003008
Nirav Davee833c6c2016-11-08 18:31:04 +00003009 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003010
3011 if (Parser.getTok().isNot(AsmToken::Integer)) {
3012 Error(getLoc(), "index must be absent or #0");
3013 return MatchOperand_ParseFail;
3014 }
3015
3016 const MCExpr *ImmVal;
3017 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3018 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3019 Error(getLoc(), "index must be absent or #0");
3020 return MatchOperand_ParseFail;
3021 }
3022
3023 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003024 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003025 return MatchOperand_Success;
3026}
3027
3028/// parseOperand - Parse a arm instruction operand. For now this parses the
3029/// operand regardless of the mnemonic.
3030bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3031 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003032 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003033
3034 OperandMatchResultTy ResTy =
3035 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3036
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.
Tim Northover3b0846e2014-05-24 12:50:23 +00003039 if (ResTy == MatchOperand_Success)
3040 return false;
3041 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3042 // there was a match, but an error occurred, in which case, just return that
3043 // the operand parsing failed.
3044 if (ResTy == MatchOperand_ParseFail)
3045 return true;
3046
3047 // Nothing custom, so do general case parsing.
3048 SMLoc S, E;
3049 switch (getLexer().getKind()) {
3050 default: {
3051 SMLoc S = getLoc();
3052 const MCExpr *Expr;
3053 if (parseSymbolicImmVal(Expr))
3054 return Error(S, "invalid operand");
3055
3056 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3057 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3058 return false;
3059 }
3060 case AsmToken::LBrac: {
3061 SMLoc Loc = Parser.getTok().getLoc();
3062 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3063 getContext()));
3064 Parser.Lex(); // Eat '['
3065
3066 // There's no comma after a '[', so we can parse the next operand
3067 // immediately.
3068 return parseOperand(Operands, false, false);
3069 }
3070 case AsmToken::LCurly:
3071 return parseVectorList(Operands);
3072 case AsmToken::Identifier: {
3073 // If we're expecting a Condition Code operand, then just parse that.
3074 if (isCondCode)
3075 return parseCondCode(Operands, invertCondCode);
3076
3077 // If it's a register name, parse it.
3078 if (!parseRegister(Operands))
3079 return false;
3080
3081 // This could be an optional "shift" or "extend" operand.
3082 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3083 // We can only continue if no tokens were eaten.
3084 if (GotShift != MatchOperand_NoMatch)
3085 return GotShift;
3086
3087 // This was not a register so parse other operands that start with an
3088 // identifier (like labels) as expressions and create them as immediates.
3089 const MCExpr *IdVal;
3090 S = getLoc();
3091 if (getParser().parseExpression(IdVal))
3092 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003093 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3094 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3095 return false;
3096 }
3097 case AsmToken::Integer:
3098 case AsmToken::Real:
3099 case AsmToken::Hash: {
3100 // #42 -> immediate.
3101 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003102
3103 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003104
3105 // Parse a negative sign
3106 bool isNegative = false;
3107 if (Parser.getTok().is(AsmToken::Minus)) {
3108 isNegative = true;
3109 // We need to consume this token only when we have a Real, otherwise
3110 // we let parseSymbolicImmVal take care of it
3111 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3112 Parser.Lex();
3113 }
3114
3115 // The only Real that should come through here is a literal #0.0 for
3116 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3117 // so convert the value.
3118 const AsmToken &Tok = Parser.getTok();
3119 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003120 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003121 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3122 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3123 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3124 Mnemonic != "fcmlt")
3125 return TokError("unexpected floating point literal");
3126 else if (IntVal != 0 || isNegative)
3127 return TokError("expected floating-point constant #0.0");
3128 Parser.Lex(); // Eat the token.
3129
3130 Operands.push_back(
3131 AArch64Operand::CreateToken("#0", false, S, getContext()));
3132 Operands.push_back(
3133 AArch64Operand::CreateToken(".0", false, S, getContext()));
3134 return false;
3135 }
3136
3137 const MCExpr *ImmVal;
3138 if (parseSymbolicImmVal(ImmVal))
3139 return true;
3140
3141 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3142 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3143 return false;
3144 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003145 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003146 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003147 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003148 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003149 Parser.Lex(); // Eat '='
3150 const MCExpr *SubExprVal;
3151 if (getParser().parseExpression(SubExprVal))
3152 return true;
3153
David Peixottoae5ba762014-07-18 16:05:14 +00003154 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003155 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003156 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003157
3158 bool IsXReg =
3159 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3160 Operands[1]->getReg());
3161
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003162 MCContext& Ctx = getContext();
3163 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3164 // 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 +00003165 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003166 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3167 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3168 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3169 ShiftAmt += 16;
3170 Imm >>= 16;
3171 }
3172 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3173 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3174 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003175 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003176 if (ShiftAmt)
3177 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3178 ShiftAmt, true, S, E, Ctx));
3179 return false;
3180 }
David Peixottoae5ba762014-07-18 16:05:14 +00003181 APInt Simm = APInt(64, Imm << ShiftAmt);
3182 // check if the immediate is an unsigned or signed 32-bit int for W regs
3183 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3184 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003185 }
3186 // 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 +00003187 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003188 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003189 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3190 return false;
3191 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003192 }
3193}
3194
3195/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3196/// operands.
3197bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3198 StringRef Name, SMLoc NameLoc,
3199 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003200 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003201 Name = StringSwitch<StringRef>(Name.lower())
3202 .Case("beq", "b.eq")
3203 .Case("bne", "b.ne")
3204 .Case("bhs", "b.hs")
3205 .Case("bcs", "b.cs")
3206 .Case("blo", "b.lo")
3207 .Case("bcc", "b.cc")
3208 .Case("bmi", "b.mi")
3209 .Case("bpl", "b.pl")
3210 .Case("bvs", "b.vs")
3211 .Case("bvc", "b.vc")
3212 .Case("bhi", "b.hi")
3213 .Case("bls", "b.ls")
3214 .Case("bge", "b.ge")
3215 .Case("blt", "b.lt")
3216 .Case("bgt", "b.gt")
3217 .Case("ble", "b.le")
3218 .Case("bal", "b.al")
3219 .Case("bnv", "b.nv")
3220 .Default(Name);
3221
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003222 // First check for the AArch64-specific .req directive.
3223 if (Parser.getTok().is(AsmToken::Identifier) &&
3224 Parser.getTok().getIdentifier() == ".req") {
3225 parseDirectiveReq(Name, NameLoc);
3226 // We always return 'error' for this, as we're done with this
3227 // statement and don't need to match the 'instruction."
3228 return true;
3229 }
3230
Tim Northover3b0846e2014-05-24 12:50:23 +00003231 // Create the leading tokens for the mnemonic, split by '.' characters.
3232 size_t Start = 0, Next = Name.find('.');
3233 StringRef Head = Name.slice(Start, Next);
3234
3235 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003236 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3237 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003238
3239 Operands.push_back(
3240 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3241 Mnemonic = Head;
3242
3243 // Handle condition codes for a branch mnemonic
3244 if (Head == "b" && Next != StringRef::npos) {
3245 Start = Next;
3246 Next = Name.find('.', Start + 1);
3247 Head = Name.slice(Start + 1, Next);
3248
3249 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3250 (Head.data() - Name.data()));
3251 AArch64CC::CondCode CC = parseCondCodeString(Head);
3252 if (CC == AArch64CC::Invalid)
3253 return Error(SuffixLoc, "invalid condition code");
3254 Operands.push_back(
3255 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3256 Operands.push_back(
3257 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3258 }
3259
3260 // Add the remaining tokens in the mnemonic.
3261 while (Next != StringRef::npos) {
3262 Start = Next;
3263 Next = Name.find('.', Start + 1);
3264 Head = Name.slice(Start, Next);
3265 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3266 (Head.data() - Name.data()) + 1);
3267 Operands.push_back(
3268 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3269 }
3270
3271 // Conditional compare instructions have a Condition Code operand, which needs
3272 // to be parsed and an immediate operand created.
3273 bool condCodeFourthOperand =
3274 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3275 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3276 Head == "csinc" || Head == "csinv" || Head == "csneg");
3277
3278 // These instructions are aliases to some of the conditional select
3279 // instructions. However, the condition code is inverted in the aliased
3280 // instruction.
3281 //
3282 // FIXME: Is this the correct way to handle these? Or should the parser
3283 // generate the aliased instructions directly?
3284 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3285 bool condCodeThirdOperand =
3286 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3287
3288 // Read the remaining operands.
3289 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3290 // Read the first operand.
3291 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003292 return true;
3293 }
3294
3295 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003296 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003297 // Parse and remember the operand.
3298 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3299 (N == 3 && condCodeThirdOperand) ||
3300 (N == 2 && condCodeSecondOperand),
3301 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003302 return true;
3303 }
3304
3305 // After successfully parsing some operands there are two special cases to
3306 // consider (i.e. notional operands not separated by commas). Both are due
3307 // to memory specifiers:
3308 // + An RBrac will end an address for load/store/prefetch
3309 // + An '!' will indicate a pre-indexed operation.
3310 //
3311 // It's someone else's responsibility to make sure these tokens are sane
3312 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003313
Nirav Davee833c6c2016-11-08 18:31:04 +00003314 SMLoc RLoc = Parser.getTok().getLoc();
3315 if (parseOptionalToken(AsmToken::RBrac))
3316 Operands.push_back(
3317 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3318 SMLoc ELoc = Parser.getTok().getLoc();
3319 if (parseOptionalToken(AsmToken::Exclaim))
3320 Operands.push_back(
3321 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003322
3323 ++N;
3324 }
3325 }
3326
Nirav Davee833c6c2016-11-08 18:31:04 +00003327 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3328 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003329
Tim Northover3b0846e2014-05-24 12:50:23 +00003330 return false;
3331}
3332
3333// FIXME: This entire function is a giant hack to provide us with decent
3334// operand range validation/diagnostics until TableGen/MC can be extended
3335// to support autogeneration of this kind of validation.
3336bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3337 SmallVectorImpl<SMLoc> &Loc) {
3338 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3339 // Check for indexed addressing modes w/ the base register being the
3340 // same as a destination/source register or pair load where
3341 // the Rt == Rt2. All of those are undefined behaviour.
3342 switch (Inst.getOpcode()) {
3343 case AArch64::LDPSWpre:
3344 case AArch64::LDPWpost:
3345 case AArch64::LDPWpre:
3346 case AArch64::LDPXpost:
3347 case AArch64::LDPXpre: {
3348 unsigned Rt = Inst.getOperand(1).getReg();
3349 unsigned Rt2 = Inst.getOperand(2).getReg();
3350 unsigned Rn = Inst.getOperand(3).getReg();
3351 if (RI->isSubRegisterEq(Rn, Rt))
3352 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3353 "is also a destination");
3354 if (RI->isSubRegisterEq(Rn, Rt2))
3355 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3356 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003357 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003358 }
3359 case AArch64::LDPDi:
3360 case AArch64::LDPQi:
3361 case AArch64::LDPSi:
3362 case AArch64::LDPSWi:
3363 case AArch64::LDPWi:
3364 case AArch64::LDPXi: {
3365 unsigned Rt = Inst.getOperand(0).getReg();
3366 unsigned Rt2 = Inst.getOperand(1).getReg();
3367 if (Rt == Rt2)
3368 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3369 break;
3370 }
3371 case AArch64::LDPDpost:
3372 case AArch64::LDPDpre:
3373 case AArch64::LDPQpost:
3374 case AArch64::LDPQpre:
3375 case AArch64::LDPSpost:
3376 case AArch64::LDPSpre:
3377 case AArch64::LDPSWpost: {
3378 unsigned Rt = Inst.getOperand(1).getReg();
3379 unsigned Rt2 = Inst.getOperand(2).getReg();
3380 if (Rt == Rt2)
3381 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3382 break;
3383 }
3384 case AArch64::STPDpost:
3385 case AArch64::STPDpre:
3386 case AArch64::STPQpost:
3387 case AArch64::STPQpre:
3388 case AArch64::STPSpost:
3389 case AArch64::STPSpre:
3390 case AArch64::STPWpost:
3391 case AArch64::STPWpre:
3392 case AArch64::STPXpost:
3393 case AArch64::STPXpre: {
3394 unsigned Rt = Inst.getOperand(1).getReg();
3395 unsigned Rt2 = Inst.getOperand(2).getReg();
3396 unsigned Rn = Inst.getOperand(3).getReg();
3397 if (RI->isSubRegisterEq(Rn, Rt))
3398 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3399 "is also a source");
3400 if (RI->isSubRegisterEq(Rn, Rt2))
3401 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3402 "is also a source");
3403 break;
3404 }
3405 case AArch64::LDRBBpre:
3406 case AArch64::LDRBpre:
3407 case AArch64::LDRHHpre:
3408 case AArch64::LDRHpre:
3409 case AArch64::LDRSBWpre:
3410 case AArch64::LDRSBXpre:
3411 case AArch64::LDRSHWpre:
3412 case AArch64::LDRSHXpre:
3413 case AArch64::LDRSWpre:
3414 case AArch64::LDRWpre:
3415 case AArch64::LDRXpre:
3416 case AArch64::LDRBBpost:
3417 case AArch64::LDRBpost:
3418 case AArch64::LDRHHpost:
3419 case AArch64::LDRHpost:
3420 case AArch64::LDRSBWpost:
3421 case AArch64::LDRSBXpost:
3422 case AArch64::LDRSHWpost:
3423 case AArch64::LDRSHXpost:
3424 case AArch64::LDRSWpost:
3425 case AArch64::LDRWpost:
3426 case AArch64::LDRXpost: {
3427 unsigned Rt = Inst.getOperand(1).getReg();
3428 unsigned Rn = Inst.getOperand(2).getReg();
3429 if (RI->isSubRegisterEq(Rn, Rt))
3430 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3431 "is also a source");
3432 break;
3433 }
3434 case AArch64::STRBBpost:
3435 case AArch64::STRBpost:
3436 case AArch64::STRHHpost:
3437 case AArch64::STRHpost:
3438 case AArch64::STRWpost:
3439 case AArch64::STRXpost:
3440 case AArch64::STRBBpre:
3441 case AArch64::STRBpre:
3442 case AArch64::STRHHpre:
3443 case AArch64::STRHpre:
3444 case AArch64::STRWpre:
3445 case AArch64::STRXpre: {
3446 unsigned Rt = Inst.getOperand(1).getReg();
3447 unsigned Rn = Inst.getOperand(2).getReg();
3448 if (RI->isSubRegisterEq(Rn, Rt))
3449 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3450 "is also a source");
3451 break;
3452 }
3453 }
3454
3455 // Now check immediate ranges. Separate from the above as there is overlap
3456 // in the instructions being checked and this keeps the nested conditionals
3457 // to a minimum.
3458 switch (Inst.getOpcode()) {
3459 case AArch64::ADDSWri:
3460 case AArch64::ADDSXri:
3461 case AArch64::ADDWri:
3462 case AArch64::ADDXri:
3463 case AArch64::SUBSWri:
3464 case AArch64::SUBSXri:
3465 case AArch64::SUBWri:
3466 case AArch64::SUBXri: {
3467 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3468 // some slight duplication here.
3469 if (Inst.getOperand(2).isExpr()) {
3470 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3471 AArch64MCExpr::VariantKind ELFRefKind;
3472 MCSymbolRefExpr::VariantKind DarwinRefKind;
3473 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003474 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3475
3476 // Only allow these with ADDXri.
3477 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3478 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3479 Inst.getOpcode() == AArch64::ADDXri)
3480 return false;
3481
3482 // Only allow these with ADDXri/ADDWri
3483 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3484 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3485 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3486 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3487 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3488 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3489 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3490 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3491 (Inst.getOpcode() == AArch64::ADDXri ||
3492 Inst.getOpcode() == AArch64::ADDWri))
3493 return false;
3494
3495 // Don't allow symbol refs in the immediate field otherwise
3496 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3497 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3498 // 'cmp w0, 'borked')
3499 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003500 }
Diana Picusc93518d2016-10-11 09:17:47 +00003501 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003502 }
3503 return false;
3504 }
3505 default:
3506 return false;
3507 }
3508}
3509
Craig Topper05515562017-10-26 06:46:41 +00003510static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3511 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003512
3513bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3514 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003515 switch (ErrCode) {
3516 case Match_MissingFeature:
3517 return Error(Loc,
3518 "instruction requires a CPU feature not currently enabled");
3519 case Match_InvalidOperand:
3520 return Error(Loc, "invalid operand for instruction");
3521 case Match_InvalidSuffix:
3522 return Error(Loc, "invalid type suffix for instruction");
3523 case Match_InvalidCondCode:
3524 return Error(Loc, "expected AArch64 condition code");
3525 case Match_AddSubRegExtendSmall:
3526 return Error(Loc,
3527 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3528 case Match_AddSubRegExtendLarge:
3529 return Error(Loc,
3530 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3531 case Match_AddSubSecondSource:
3532 return Error(Loc,
3533 "expected compatible register, symbol or integer in range [0, 4095]");
3534 case Match_LogicalSecondSource:
3535 return Error(Loc, "expected compatible register or logical immediate");
3536 case Match_InvalidMovImm32Shift:
3537 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3538 case Match_InvalidMovImm64Shift:
3539 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3540 case Match_AddSubRegShift32:
3541 return Error(Loc,
3542 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3543 case Match_AddSubRegShift64:
3544 return Error(Loc,
3545 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3546 case Match_InvalidFPImm:
3547 return Error(Loc,
3548 "expected compatible register or floating-point constant");
3549 case Match_InvalidMemoryIndexedSImm9:
3550 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003551 case Match_InvalidMemoryIndexedSImm10:
3552 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003553 case Match_InvalidMemoryIndexed4SImm7:
3554 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3555 case Match_InvalidMemoryIndexed8SImm7:
3556 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3557 case Match_InvalidMemoryIndexed16SImm7:
3558 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3559 case Match_InvalidMemoryWExtend8:
3560 return Error(Loc,
3561 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3562 case Match_InvalidMemoryWExtend16:
3563 return Error(Loc,
3564 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3565 case Match_InvalidMemoryWExtend32:
3566 return Error(Loc,
3567 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3568 case Match_InvalidMemoryWExtend64:
3569 return Error(Loc,
3570 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3571 case Match_InvalidMemoryWExtend128:
3572 return Error(Loc,
3573 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3574 case Match_InvalidMemoryXExtend8:
3575 return Error(Loc,
3576 "expected 'lsl' or 'sxtx' with optional shift of #0");
3577 case Match_InvalidMemoryXExtend16:
3578 return Error(Loc,
3579 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3580 case Match_InvalidMemoryXExtend32:
3581 return Error(Loc,
3582 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3583 case Match_InvalidMemoryXExtend64:
3584 return Error(Loc,
3585 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3586 case Match_InvalidMemoryXExtend128:
3587 return Error(Loc,
3588 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3589 case Match_InvalidMemoryIndexed1:
3590 return Error(Loc, "index must be an integer in range [0, 4095].");
3591 case Match_InvalidMemoryIndexed2:
3592 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3593 case Match_InvalidMemoryIndexed4:
3594 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3595 case Match_InvalidMemoryIndexed8:
3596 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3597 case Match_InvalidMemoryIndexed16:
3598 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003599 case Match_InvalidImm0_1:
3600 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003601 case Match_InvalidImm0_7:
3602 return Error(Loc, "immediate must be an integer in range [0, 7].");
3603 case Match_InvalidImm0_15:
3604 return Error(Loc, "immediate must be an integer in range [0, 15].");
3605 case Match_InvalidImm0_31:
3606 return Error(Loc, "immediate must be an integer in range [0, 31].");
3607 case Match_InvalidImm0_63:
3608 return Error(Loc, "immediate must be an integer in range [0, 63].");
3609 case Match_InvalidImm0_127:
3610 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003611 case Match_InvalidImm0_255:
3612 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003613 case Match_InvalidImm0_65535:
3614 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3615 case Match_InvalidImm1_8:
3616 return Error(Loc, "immediate must be an integer in range [1, 8].");
3617 case Match_InvalidImm1_16:
3618 return Error(Loc, "immediate must be an integer in range [1, 16].");
3619 case Match_InvalidImm1_32:
3620 return Error(Loc, "immediate must be an integer in range [1, 32].");
3621 case Match_InvalidImm1_64:
3622 return Error(Loc, "immediate must be an integer in range [1, 64].");
3623 case Match_InvalidIndex1:
3624 return Error(Loc, "expected lane specifier '[1]'");
3625 case Match_InvalidIndexB:
3626 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3627 case Match_InvalidIndexH:
3628 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3629 case Match_InvalidIndexS:
3630 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3631 case Match_InvalidIndexD:
3632 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3633 case Match_InvalidLabel:
3634 return Error(Loc, "expected label or encodable integer pc offset");
3635 case Match_MRS:
3636 return Error(Loc, "expected readable system register");
3637 case Match_MSR:
3638 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003639 case Match_InvalidComplexRotationEven:
3640 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3641 case Match_InvalidComplexRotationOdd:
3642 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003643 case Match_MnemonicFail: {
3644 std::string Suggestion = AArch64MnemonicSpellCheck(
3645 ((AArch64Operand &)*Operands[0]).getToken(),
3646 ComputeAvailableFeatures(STI->getFeatureBits()));
3647 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3648 }
Sander de Smalencd6be962017-12-20 11:02:42 +00003649 case Match_InvalidSVEPredicateAnyReg:
3650 case Match_InvalidSVEPredicateBReg:
3651 case Match_InvalidSVEPredicateHReg:
3652 case Match_InvalidSVEPredicateSReg:
3653 case Match_InvalidSVEPredicateDReg:
3654 return Error(Loc, "invalid predicate register.");
Tim Northover3b0846e2014-05-24 12:50:23 +00003655 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003656 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003657 }
3658}
3659
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003660static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003661
3662bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3663 OperandVector &Operands,
3664 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003665 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003666 bool MatchingInlineAsm) {
3667 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003668 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3669 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003670
David Blaikie960ea3f2014-06-08 16:18:35 +00003671 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003672 unsigned NumOperands = Operands.size();
3673
3674 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003675 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3676 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003677 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003678 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003679 if (Op3CE) {
3680 uint64_t Op3Val = Op3CE->getValue();
3681 uint64_t NewOp3Val = 0;
3682 uint64_t NewOp4Val = 0;
3683 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003684 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003685 NewOp3Val = (32 - Op3Val) & 0x1f;
3686 NewOp4Val = 31 - Op3Val;
3687 } else {
3688 NewOp3Val = (64 - Op3Val) & 0x3f;
3689 NewOp4Val = 63 - Op3Val;
3690 }
3691
Jim Grosbach13760bd2015-05-30 01:25:56 +00003692 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3693 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003694
3695 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003696 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003697 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003698 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3699 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3700 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003701 }
3702 }
Tim Northover03b99f62015-04-30 18:28:58 +00003703 } else if (NumOperands == 4 && Tok == "bfc") {
3704 // FIXME: Horrible hack to handle BFC->BFM alias.
3705 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3706 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3707 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3708
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003709 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003710 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3711 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3712
3713 if (LSBCE && WidthCE) {
3714 uint64_t LSB = LSBCE->getValue();
3715 uint64_t Width = WidthCE->getValue();
3716
3717 uint64_t RegWidth = 0;
3718 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3719 Op1.getReg()))
3720 RegWidth = 64;
3721 else
3722 RegWidth = 32;
3723
3724 if (LSB >= RegWidth)
3725 return Error(LSBOp.getStartLoc(),
3726 "expected integer in range [0, 31]");
3727 if (Width < 1 || Width > RegWidth)
3728 return Error(WidthOp.getStartLoc(),
3729 "expected integer in range [1, 32]");
3730
3731 uint64_t ImmR = 0;
3732 if (RegWidth == 32)
3733 ImmR = (32 - LSB) & 0x1f;
3734 else
3735 ImmR = (64 - LSB) & 0x3f;
3736
3737 uint64_t ImmS = Width - 1;
3738
3739 if (ImmR != 0 && ImmS >= ImmR)
3740 return Error(WidthOp.getStartLoc(),
3741 "requested insert overflows register");
3742
Jim Grosbach13760bd2015-05-30 01:25:56 +00003743 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3744 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003745 Operands[0] = AArch64Operand::CreateToken(
3746 "bfm", false, Op.getStartLoc(), getContext());
3747 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003748 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3749 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003750 Operands[3] = AArch64Operand::CreateImm(
3751 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3752 Operands.emplace_back(
3753 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3754 WidthOp.getEndLoc(), getContext()));
3755 }
3756 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003757 } else if (NumOperands == 5) {
3758 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3759 // UBFIZ -> UBFM aliases.
3760 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003761 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3762 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3763 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003764
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003765 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003766 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3767 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003768
3769 if (Op3CE && Op4CE) {
3770 uint64_t Op3Val = Op3CE->getValue();
3771 uint64_t Op4Val = Op4CE->getValue();
3772
3773 uint64_t RegWidth = 0;
3774 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003775 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003776 RegWidth = 64;
3777 else
3778 RegWidth = 32;
3779
3780 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003781 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003782 "expected integer in range [0, 31]");
3783 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003784 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003785 "expected integer in range [1, 32]");
3786
3787 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003788 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003789 NewOp3Val = (32 - Op3Val) & 0x1f;
3790 else
3791 NewOp3Val = (64 - Op3Val) & 0x3f;
3792
3793 uint64_t NewOp4Val = Op4Val - 1;
3794
3795 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003796 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003797 "requested insert overflows register");
3798
3799 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003800 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003801 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003802 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003803 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003804 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003805 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003806 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003807 if (Tok == "bfi")
3808 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003809 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003810 else if (Tok == "sbfiz")
3811 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003812 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003813 else if (Tok == "ubfiz")
3814 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003815 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003816 else
3817 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003818 }
3819 }
3820
3821 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3822 // UBFX -> UBFM aliases.
3823 } else if (NumOperands == 5 &&
3824 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003825 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3826 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3827 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003828
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003829 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003830 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3831 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003832
3833 if (Op3CE && Op4CE) {
3834 uint64_t Op3Val = Op3CE->getValue();
3835 uint64_t Op4Val = Op4CE->getValue();
3836
3837 uint64_t RegWidth = 0;
3838 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003839 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003840 RegWidth = 64;
3841 else
3842 RegWidth = 32;
3843
3844 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003845 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003846 "expected integer in range [0, 31]");
3847 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003848 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003849 "expected integer in range [1, 32]");
3850
3851 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3852
3853 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003854 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003855 "requested extract overflows register");
3856
3857 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003858 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003859 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003860 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003861 if (Tok == "bfxil")
3862 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003863 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003864 else if (Tok == "sbfx")
3865 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003866 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003867 else if (Tok == "ubfx")
3868 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003869 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003870 else
3871 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003872 }
3873 }
3874 }
3875 }
Tim Northover9097a072017-12-18 10:36:00 +00003876
3877 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
3878 // instruction for FP registers correctly in some rare circumstances. Convert
3879 // it to a safe instruction and warn (because silently changing someone's
3880 // assembly is rude).
3881 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
3882 NumOperands == 4 && Tok == "movi") {
3883 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3884 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3885 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3886 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
3887 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
3888 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
3889 if (Suffix.lower() == ".2d" &&
3890 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
3891 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
3892 " correctly on this CPU, converting to equivalent movi.16b");
3893 // Switch the suffix to .16b.
3894 unsigned Idx = Op1.isToken() ? 1 : 2;
3895 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
3896 getContext());
3897 }
3898 }
3899 }
3900
Tim Northover3b0846e2014-05-24 12:50:23 +00003901 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3902 // InstAlias can't quite handle this since the reg classes aren't
3903 // subclasses.
3904 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3905 // The source register can be Wn here, but the matcher expects a
3906 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003907 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003908 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003909 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003910 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3911 Op.getStartLoc(), Op.getEndLoc(),
3912 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003913 }
3914 }
3915 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3916 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003917 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003918 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003919 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003920 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003921 // The source register can be Wn here, but the matcher expects a
3922 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003923 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003924 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003925 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003926 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3927 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003928 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003929 }
3930 }
3931 }
3932 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3933 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003934 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003935 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003936 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003937 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003938 // The source register can be Wn here, but the matcher expects a
3939 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003940 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003941 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003942 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003943 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3944 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003945 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003946 }
3947 }
3948 }
3949
Tim Northover3b0846e2014-05-24 12:50:23 +00003950 MCInst Inst;
3951 // First try to match against the secondary set of tables containing the
3952 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3953 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003954 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003955
3956 // If that fails, try against the alternate table containing long-form NEON:
3957 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003958 if (MatchResult != Match_Success) {
3959 // But first, save the short-form match result: we can use it in case the
3960 // long-form match also fails.
3961 auto ShortFormNEONErrorInfo = ErrorInfo;
3962 auto ShortFormNEONMatchResult = MatchResult;
3963
Tim Northover3b0846e2014-05-24 12:50:23 +00003964 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003965 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003966
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003967 // Now, both matches failed, and the long-form match failed on the mnemonic
3968 // suffix token operand. The short-form match failure is probably more
3969 // relevant: use it instead.
3970 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003971 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003972 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3973 MatchResult = ShortFormNEONMatchResult;
3974 ErrorInfo = ShortFormNEONErrorInfo;
3975 }
3976 }
3977
Tim Northover3b0846e2014-05-24 12:50:23 +00003978 switch (MatchResult) {
3979 case Match_Success: {
3980 // Perform range checking and other semantic validations
3981 SmallVector<SMLoc, 8> OperandLocs;
3982 NumOperands = Operands.size();
3983 for (unsigned i = 1; i < NumOperands; ++i)
3984 OperandLocs.push_back(Operands[i]->getStartLoc());
3985 if (validateInstruction(Inst, OperandLocs))
3986 return true;
3987
3988 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003989 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00003990 return false;
3991 }
3992 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003993 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003994 // Special case the error message for the very common case where only
3995 // a single subtarget feature is missing (neon, e.g.).
3996 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003997 uint64_t Mask = 1;
3998 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
3999 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004000 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004001 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004002 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004003 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004004 }
4005 return Error(IDLoc, Msg);
4006 }
4007 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004008 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004009 case Match_InvalidOperand: {
4010 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004011
Tim Northover26bb14e2014-08-18 11:49:42 +00004012 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004013 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004014 return Error(IDLoc, "too few operands for instruction",
4015 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004016
David Blaikie960ea3f2014-06-08 16:18:35 +00004017 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004018 if (ErrorLoc == SMLoc())
4019 ErrorLoc = IDLoc;
4020 }
4021 // If the match failed on a suffix token operand, tweak the diagnostic
4022 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004023 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4024 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004025 MatchResult = Match_InvalidSuffix;
4026
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004027 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004028 }
4029 case Match_InvalidMemoryIndexed1:
4030 case Match_InvalidMemoryIndexed2:
4031 case Match_InvalidMemoryIndexed4:
4032 case Match_InvalidMemoryIndexed8:
4033 case Match_InvalidMemoryIndexed16:
4034 case Match_InvalidCondCode:
4035 case Match_AddSubRegExtendSmall:
4036 case Match_AddSubRegExtendLarge:
4037 case Match_AddSubSecondSource:
4038 case Match_LogicalSecondSource:
4039 case Match_AddSubRegShift32:
4040 case Match_AddSubRegShift64:
4041 case Match_InvalidMovImm32Shift:
4042 case Match_InvalidMovImm64Shift:
4043 case Match_InvalidFPImm:
4044 case Match_InvalidMemoryWExtend8:
4045 case Match_InvalidMemoryWExtend16:
4046 case Match_InvalidMemoryWExtend32:
4047 case Match_InvalidMemoryWExtend64:
4048 case Match_InvalidMemoryWExtend128:
4049 case Match_InvalidMemoryXExtend8:
4050 case Match_InvalidMemoryXExtend16:
4051 case Match_InvalidMemoryXExtend32:
4052 case Match_InvalidMemoryXExtend64:
4053 case Match_InvalidMemoryXExtend128:
4054 case Match_InvalidMemoryIndexed4SImm7:
4055 case Match_InvalidMemoryIndexed8SImm7:
4056 case Match_InvalidMemoryIndexed16SImm7:
4057 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004058 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004059 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004060 case Match_InvalidImm0_7:
4061 case Match_InvalidImm0_15:
4062 case Match_InvalidImm0_31:
4063 case Match_InvalidImm0_63:
4064 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004065 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004066 case Match_InvalidImm0_65535:
4067 case Match_InvalidImm1_8:
4068 case Match_InvalidImm1_16:
4069 case Match_InvalidImm1_32:
4070 case Match_InvalidImm1_64:
4071 case Match_InvalidIndex1:
4072 case Match_InvalidIndexB:
4073 case Match_InvalidIndexH:
4074 case Match_InvalidIndexS:
4075 case Match_InvalidIndexD:
4076 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004077 case Match_InvalidComplexRotationEven:
4078 case Match_InvalidComplexRotationOdd:
Sander de Smalencd6be962017-12-20 11:02:42 +00004079 case Match_InvalidSVEPredicateAnyReg:
4080 case Match_InvalidSVEPredicateBReg:
4081 case Match_InvalidSVEPredicateHReg:
4082 case Match_InvalidSVEPredicateSReg:
4083 case Match_InvalidSVEPredicateDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004084 case Match_MSR:
4085 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004086 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004087 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004088 // Any time we get here, there's nothing fancy to do. Just get the
4089 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004090 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004091 if (ErrorLoc == SMLoc())
4092 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004093 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004094 }
4095 }
4096
4097 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004098}
4099
4100/// ParseDirective parses the arm specific directives
4101bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004102 const MCObjectFileInfo::Environment Format =
4103 getContext().getObjectFileInfo()->getObjectFileType();
4104 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4105 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004106
Tim Northover3b0846e2014-05-24 12:50:23 +00004107 StringRef IDVal = DirectiveID.getIdentifier();
4108 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004109 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004110 parseDirectiveArch(Loc);
4111 else if (IDVal == ".cpu")
4112 parseDirectiveCPU(Loc);
4113 else if (IDVal == ".hword")
4114 parseDirectiveWord(2, Loc);
4115 else if (IDVal == ".word")
4116 parseDirectiveWord(4, Loc);
4117 else if (IDVal == ".xword")
4118 parseDirectiveWord(8, Loc);
4119 else if (IDVal == ".tlsdesccall")
4120 parseDirectiveTLSDescCall(Loc);
4121 else if (IDVal == ".ltorg" || IDVal == ".pool")
4122 parseDirectiveLtorg(Loc);
4123 else if (IDVal == ".unreq")
4124 parseDirectiveUnreq(Loc);
4125 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004126 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004127 parseDirectiveInst(Loc);
4128 else
4129 return true;
4130 } else if (IDVal == MCLOHDirectiveName())
4131 parseDirectiveLOH(IDVal, Loc);
4132 else
4133 return true;
4134 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004135}
4136
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004137static const struct {
4138 const char *Name;
4139 const FeatureBitset Features;
4140} ExtensionMap[] = {
4141 { "crc", {AArch64::FeatureCRC} },
4142 { "crypto", {AArch64::FeatureCrypto} },
4143 { "fp", {AArch64::FeatureFPARMv8} },
4144 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004145 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004146 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004147
4148 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004149 { "pan", {} },
4150 { "lor", {} },
4151 { "rdma", {} },
4152 { "profile", {} },
4153};
4154
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004155/// parseDirectiveArch
4156/// ::= .arch token
4157bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4158 SMLoc ArchLoc = getLoc();
4159
4160 StringRef Arch, ExtensionString;
4161 std::tie(Arch, ExtensionString) =
4162 getParser().parseStringToEndOfStatement().trim().split('+');
4163
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004164 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4165 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004166 return Error(ArchLoc, "unknown arch name");
4167
4168 if (parseToken(AsmToken::EndOfStatement))
4169 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004170
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004171 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004172 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004173 AArch64::getArchFeatures(ID, AArch64Features);
4174 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4175 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004176
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004177 MCSubtargetInfo &STI = copySTI();
4178 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4179 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4180
4181 SmallVector<StringRef, 4> RequestedExtensions;
4182 if (!ExtensionString.empty())
4183 ExtensionString.split(RequestedExtensions, '+');
4184
4185 FeatureBitset Features = STI.getFeatureBits();
4186 for (auto Name : RequestedExtensions) {
4187 bool EnableFeature = true;
4188
4189 if (Name.startswith_lower("no")) {
4190 EnableFeature = false;
4191 Name = Name.substr(2);
4192 }
4193
4194 for (const auto &Extension : ExtensionMap) {
4195 if (Extension.Name != Name)
4196 continue;
4197
4198 if (Extension.Features.none())
4199 report_fatal_error("unsupported architectural extension: " + Name);
4200
4201 FeatureBitset ToggleFeatures = EnableFeature
4202 ? (~Features & Extension.Features)
4203 : ( Features & Extension.Features);
4204 uint64_t Features =
4205 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4206 setAvailableFeatures(Features);
4207 break;
4208 }
4209 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004210 return false;
4211}
4212
Tim Northover8b96c7e2017-05-15 19:42:15 +00004213static SMLoc incrementLoc(SMLoc L, int Offset) {
4214 return SMLoc::getFromPointer(L.getPointer() + Offset);
4215}
4216
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004217/// parseDirectiveCPU
4218/// ::= .cpu id
4219bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004220 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004221
4222 StringRef CPU, ExtensionString;
4223 std::tie(CPU, ExtensionString) =
4224 getParser().parseStringToEndOfStatement().trim().split('+');
4225
Nirav Davee833c6c2016-11-08 18:31:04 +00004226 if (parseToken(AsmToken::EndOfStatement))
4227 return true;
4228
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004229 SmallVector<StringRef, 4> RequestedExtensions;
4230 if (!ExtensionString.empty())
4231 ExtensionString.split(RequestedExtensions, '+');
4232
4233 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4234 // once that is tablegen'ed
4235 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004236 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004237 return false;
4238 }
4239
4240 MCSubtargetInfo &STI = copySTI();
4241 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004242 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004243
4244 FeatureBitset Features = STI.getFeatureBits();
4245 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004246 // Advance source location past '+'.
4247 CurLoc = incrementLoc(CurLoc, 1);
4248
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004249 bool EnableFeature = true;
4250
4251 if (Name.startswith_lower("no")) {
4252 EnableFeature = false;
4253 Name = Name.substr(2);
4254 }
4255
Tim Northover8b96c7e2017-05-15 19:42:15 +00004256 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004257 for (const auto &Extension : ExtensionMap) {
4258 if (Extension.Name != Name)
4259 continue;
4260
4261 if (Extension.Features.none())
4262 report_fatal_error("unsupported architectural extension: " + Name);
4263
4264 FeatureBitset ToggleFeatures = EnableFeature
4265 ? (~Features & Extension.Features)
4266 : ( Features & Extension.Features);
4267 uint64_t Features =
4268 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4269 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004270 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004271
4272 break;
4273 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004274
4275 if (!FoundExtension)
4276 Error(CurLoc, "unsupported architectural extension");
4277
4278 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004279 }
4280 return false;
4281}
4282
Tim Northover3b0846e2014-05-24 12:50:23 +00004283/// parseDirectiveWord
4284/// ::= .word [ expression (, expression)* ]
4285bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004286 auto parseOp = [&]() -> bool {
4287 const MCExpr *Value;
4288 if (getParser().parseExpression(Value))
4289 return true;
4290 getParser().getStreamer().EmitValue(Value, Size, L);
4291 return false;
4292 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004293
Nirav Davee833c6c2016-11-08 18:31:04 +00004294 if (parseMany(parseOp))
4295 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004296 return false;
4297}
4298
Chad Rosierdcd2a302014-10-22 20:35:57 +00004299/// parseDirectiveInst
4300/// ::= .inst opcode [, ...]
4301bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004302 if (getLexer().is(AsmToken::EndOfStatement))
4303 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004304
Nirav Davee833c6c2016-11-08 18:31:04 +00004305 auto parseOp = [&]() -> bool {
4306 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004307 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004308 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4309 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004310 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004311 if (check(!Value, L, "expected constant expression"))
4312 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004313 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004314 return false;
4315 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004316
Nirav Davee833c6c2016-11-08 18:31:04 +00004317 if (parseMany(parseOp))
4318 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004319 return false;
4320}
4321
Tim Northover3b0846e2014-05-24 12:50:23 +00004322// parseDirectiveTLSDescCall:
4323// ::= .tlsdesccall symbol
4324bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4325 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004326 if (check(getParser().parseIdentifier(Name), L,
4327 "expected symbol after directive") ||
4328 parseToken(AsmToken::EndOfStatement))
4329 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004330
Jim Grosbach6f482002015-05-18 18:43:14 +00004331 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004332 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4333 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004334
4335 MCInst Inst;
4336 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004337 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004338
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004339 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004340 return false;
4341}
4342
4343/// ::= .loh <lohName | lohId> label1, ..., labelN
4344/// The number of arguments depends on the loh identifier.
4345bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004346 MCLOHType Kind;
4347 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4348 if (getParser().getTok().isNot(AsmToken::Integer))
4349 return TokError("expected an identifier or a number in directive");
4350 // We successfully get a numeric value for the identifier.
4351 // Check if it is valid.
4352 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004353 if (Id <= -1U && !isValidMCLOHType(Id))
4354 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004355 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004356 } else {
4357 StringRef Name = getTok().getIdentifier();
4358 // We successfully parse an identifier.
4359 // Check if it is a recognized one.
4360 int Id = MCLOHNameToId(Name);
4361
4362 if (Id == -1)
4363 return TokError("invalid identifier in directive");
4364 Kind = (MCLOHType)Id;
4365 }
4366 // Consume the identifier.
4367 Lex();
4368 // Get the number of arguments of this LOH.
4369 int NbArgs = MCLOHIdToNbArgs(Kind);
4370
4371 assert(NbArgs != -1 && "Invalid number of arguments");
4372
4373 SmallVector<MCSymbol *, 3> Args;
4374 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4375 StringRef Name;
4376 if (getParser().parseIdentifier(Name))
4377 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004378 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004379
4380 if (Idx + 1 == NbArgs)
4381 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004382 if (parseToken(AsmToken::Comma,
4383 "unexpected token in '" + Twine(IDVal) + "' directive"))
4384 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004385 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004386 if (parseToken(AsmToken::EndOfStatement,
4387 "unexpected token in '" + Twine(IDVal) + "' directive"))
4388 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004389
4390 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4391 return false;
4392}
4393
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004394/// parseDirectiveLtorg
4395/// ::= .ltorg | .pool
4396bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004397 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4398 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004399 getTargetStreamer().emitCurrentConstantPool();
4400 return false;
4401}
4402
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004403/// parseDirectiveReq
4404/// ::= name .req registername
4405bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004406 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004407 Parser.Lex(); // Eat the '.req' token.
4408 SMLoc SRegLoc = getLoc();
Sander de Smalen8e607342017-11-15 15:44:43 +00004409 int RegNum = tryParseRegister();
Florian Hahnc4422242017-11-07 13:07:50 +00004410 RegKind RegisterKind = RegKind::Scalar;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004411
Sander de Smalen8e607342017-11-15 15:44:43 +00004412 if (RegNum == -1) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004413 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004414 RegisterKind = RegKind::NeonVector;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004415 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004416 if (!Kind.empty())
4417 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004418 }
4419
Sander de Smalen8e607342017-11-15 15:44:43 +00004420 if (RegNum == -1) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004421 StringRef Kind;
4422 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen8e607342017-11-15 15:44:43 +00004423 OperandMatchResultTy Res =
4424 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4425
4426 if (Res == MatchOperand_ParseFail)
4427 return true;
4428
4429 if (Res == MatchOperand_Success && !Kind.empty())
4430 return Error(SRegLoc,
4431 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004432 }
4433
Sander de Smalencd6be962017-12-20 11:02:42 +00004434 if (RegNum == -1) {
4435 StringRef Kind;
4436 RegisterKind = RegKind::SVEPredicateVector;
4437 OperandMatchResultTy Res =
4438 tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
4439
4440 if (Res == MatchOperand_ParseFail)
4441 return true;
4442
4443 if (Res == MatchOperand_Success && !Kind.empty())
4444 return Error(SRegLoc,
4445 "sve predicate register without type specifier expected");
4446 }
4447
Sander de Smalen8e607342017-11-15 15:44:43 +00004448 if (RegNum == -1)
Nirav Dave2364748a2016-09-16 18:30:20 +00004449 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004450
4451 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004452 if (parseToken(AsmToken::EndOfStatement,
4453 "unexpected input in .req directive"))
4454 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004455
Sander de Smalen8e607342017-11-15 15:44:43 +00004456 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004457 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004458 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4459
Nirav Dave2364748a2016-09-16 18:30:20 +00004460 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004461}
4462
4463/// parseDirectiveUneq
4464/// ::= .unreq registername
4465bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004466 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004467 if (getTok().isNot(AsmToken::Identifier))
4468 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004469 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4470 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004471 if (parseToken(AsmToken::EndOfStatement))
4472 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004473 return false;
4474}
4475
Tim Northover3b0846e2014-05-24 12:50:23 +00004476bool
4477AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4478 AArch64MCExpr::VariantKind &ELFRefKind,
4479 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4480 int64_t &Addend) {
4481 ELFRefKind = AArch64MCExpr::VK_INVALID;
4482 DarwinRefKind = MCSymbolRefExpr::VK_None;
4483 Addend = 0;
4484
4485 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4486 ELFRefKind = AE->getKind();
4487 Expr = AE->getSubExpr();
4488 }
4489
4490 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4491 if (SE) {
4492 // It's a simple symbol reference with no addend.
4493 DarwinRefKind = SE->getKind();
4494 return true;
4495 }
4496
4497 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4498 if (!BE)
4499 return false;
4500
4501 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4502 if (!SE)
4503 return false;
4504 DarwinRefKind = SE->getKind();
4505
4506 if (BE->getOpcode() != MCBinaryExpr::Add &&
4507 BE->getOpcode() != MCBinaryExpr::Sub)
4508 return false;
4509
4510 // See if the addend is is a constant, otherwise there's more going
4511 // on here than we can deal with.
4512 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4513 if (!AddendExpr)
4514 return false;
4515
4516 Addend = AddendExpr->getValue();
4517 if (BE->getOpcode() == MCBinaryExpr::Sub)
4518 Addend = -Addend;
4519
4520 // It's some symbol reference + a constant addend, but really
4521 // shouldn't use both Darwin and ELF syntax.
4522 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4523 DarwinRefKind == MCSymbolRefExpr::VK_None;
4524}
4525
4526/// Force static initialization.
4527extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004528 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4529 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4530 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004531}
4532
4533#define GET_REGISTER_MATCHER
4534#define GET_SUBTARGET_FEATURE_NAME
4535#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004536#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004537#include "AArch64GenAsmMatcher.inc"
4538
4539// Define this matcher function after the auto-generated include so we
4540// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004541unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004542 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004543 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004544 // If the kind is a token for a literal immediate, check if our asm
4545 // operand matches. This is for InstAliases which have a fixed-value
4546 // immediate in the syntax.
4547 int64_t ExpectedVal;
4548 switch (Kind) {
4549 default:
4550 return Match_InvalidOperand;
4551 case MCK__35_0:
4552 ExpectedVal = 0;
4553 break;
4554 case MCK__35_1:
4555 ExpectedVal = 1;
4556 break;
4557 case MCK__35_12:
4558 ExpectedVal = 12;
4559 break;
4560 case MCK__35_16:
4561 ExpectedVal = 16;
4562 break;
4563 case MCK__35_2:
4564 ExpectedVal = 2;
4565 break;
4566 case MCK__35_24:
4567 ExpectedVal = 24;
4568 break;
4569 case MCK__35_3:
4570 ExpectedVal = 3;
4571 break;
4572 case MCK__35_32:
4573 ExpectedVal = 32;
4574 break;
4575 case MCK__35_4:
4576 ExpectedVal = 4;
4577 break;
4578 case MCK__35_48:
4579 ExpectedVal = 48;
4580 break;
4581 case MCK__35_6:
4582 ExpectedVal = 6;
4583 break;
4584 case MCK__35_64:
4585 ExpectedVal = 64;
4586 break;
4587 case MCK__35_8:
4588 ExpectedVal = 8;
4589 break;
4590 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004591 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004592 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004593 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004594 if (!CE)
4595 return Match_InvalidOperand;
4596 if (CE->getValue() == ExpectedVal)
4597 return Match_Success;
4598 return Match_InvalidOperand;
4599}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004600
Alex Bradbury58eba092016-11-01 16:32:05 +00004601OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004602AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4603
4604 SMLoc S = getLoc();
4605
4606 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4607 Error(S, "expected register");
4608 return MatchOperand_ParseFail;
4609 }
4610
4611 int FirstReg = tryParseRegister();
4612 if (FirstReg == -1) {
4613 return MatchOperand_ParseFail;
4614 }
4615 const MCRegisterClass &WRegClass =
4616 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4617 const MCRegisterClass &XRegClass =
4618 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4619
4620 bool isXReg = XRegClass.contains(FirstReg),
4621 isWReg = WRegClass.contains(FirstReg);
4622 if (!isXReg && !isWReg) {
4623 Error(S, "expected first even register of a "
4624 "consecutive same-size even/odd register pair");
4625 return MatchOperand_ParseFail;
4626 }
4627
4628 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4629 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4630
4631 if (FirstEncoding & 0x1) {
4632 Error(S, "expected first even register of a "
4633 "consecutive same-size even/odd register pair");
4634 return MatchOperand_ParseFail;
4635 }
4636
4637 SMLoc M = getLoc();
4638 if (getParser().getTok().isNot(AsmToken::Comma)) {
4639 Error(M, "expected comma");
4640 return MatchOperand_ParseFail;
4641 }
4642 // Eat the comma
4643 getParser().Lex();
4644
4645 SMLoc E = getLoc();
4646 int SecondReg = tryParseRegister();
4647 if (SecondReg ==-1) {
4648 return MatchOperand_ParseFail;
4649 }
4650
Eugene Zelenko049b0172017-01-06 00:30:53 +00004651 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004652 (isXReg && !XRegClass.contains(SecondReg)) ||
4653 (isWReg && !WRegClass.contains(SecondReg))) {
4654 Error(E,"expected second odd register of a "
4655 "consecutive same-size even/odd register pair");
4656 return MatchOperand_ParseFail;
4657 }
Joel Jones504bf332016-10-24 13:37:13 +00004658
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004659 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004660 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004661 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4662 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4663 } else {
4664 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4665 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4666 }
4667
Florian Hahnc4422242017-11-07 13:07:50 +00004668 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4669 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004670
4671 return MatchOperand_Success;
4672}
Florian Hahn91f11e52017-11-07 16:45:48 +00004673
4674template <bool ParseSuffix>
4675OperandMatchResultTy
4676AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004677 const SMLoc S = getLoc();
4678 // Check for a SVE vector register specifier first.
Sander de Smalen8e607342017-11-15 15:44:43 +00004679 int RegNum = -1;
Florian Hahn91f11e52017-11-07 16:45:48 +00004680 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004681
Sander de Smalen8e607342017-11-15 15:44:43 +00004682 OperandMatchResultTy Res =
4683 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4684
4685 if (Res != MatchOperand_Success)
4686 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004687
4688 if (ParseSuffix && Kind.empty())
4689 return MatchOperand_NoMatch;
4690
4691 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
4692 .Case("", -1)
4693 .Case(".b", 8)
4694 .Case(".h", 16)
4695 .Case(".s", 32)
4696 .Case(".d", 64)
4697 .Case(".q", 128)
4698 .Default(0);
4699 if (!ElementWidth)
4700 return MatchOperand_NoMatch;
4701
4702 Operands.push_back(
4703 AArch64Operand::CreateReg(RegNum, RegKind::SVEDataVector, ElementWidth,
4704 S, S, getContext()));
4705
4706 return MatchOperand_Success;
4707}