blob: 6efa8bede29d5ce99cba297c1efab272dda36f94 [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:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000846 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000847 RK = RegKind::SVEPredicateVector;
848 break;
849 default:
850 llvm_unreachable("Unsupport register class");
851 }
852
853 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000854 AArch64MCRegisterClasses[Class].contains(getReg());
855 }
856
Sander de Smalencd6be962017-12-20 11:02:42 +0000857 template <int ElementWidth, unsigned Class>
858 bool isSVEVectorRegOfWidth() const {
859 return isSVEVectorReg<Class>() &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000860 (ElementWidth == -1 || Reg.ElementWidth == ElementWidth);
861 }
862
Tim Northover3b0846e2014-05-24 12:50:23 +0000863 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000864 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000865 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
866 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000867
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000868 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000869 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000870 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
871 Reg.RegNum);
872 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000873
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000874 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000875 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000876 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
877 Reg.RegNum);
878 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000879
880 bool isGPR64sp0() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000881 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000882 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
883 }
884
Sam Parker5f934642017-08-31 09:27:04 +0000885 template<int64_t Angle, int64_t Remainder>
886 bool isComplexRotation() const {
887 if (!isImm()) return false;
888
889 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
890 if (!CE) return false;
891 uint64_t Value = CE->getValue();
892
893 return (Value % Angle == Remainder && Value <= 270);
894 }
895
Tim Northover3b0846e2014-05-24 12:50:23 +0000896 /// Is this a vector list with the type implicit (presumably attached to the
897 /// instruction itself)?
898 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
899 return Kind == k_VectorList && VectorList.Count == NumRegs &&
900 !VectorList.ElementKind;
901 }
902
903 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
904 bool isTypedVectorList() const {
905 if (Kind != k_VectorList)
906 return false;
907 if (VectorList.Count != NumRegs)
908 return false;
909 if (VectorList.ElementKind != ElementKind)
910 return false;
911 return VectorList.NumElements == NumElements;
912 }
913
914 bool isVectorIndex1() const {
915 return Kind == k_VectorIndex && VectorIndex.Val == 1;
916 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000917
Tim Northover3b0846e2014-05-24 12:50:23 +0000918 bool isVectorIndexB() const {
919 return Kind == k_VectorIndex && VectorIndex.Val < 16;
920 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000921
Tim Northover3b0846e2014-05-24 12:50:23 +0000922 bool isVectorIndexH() const {
923 return Kind == k_VectorIndex && VectorIndex.Val < 8;
924 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000925
Tim Northover3b0846e2014-05-24 12:50:23 +0000926 bool isVectorIndexS() const {
927 return Kind == k_VectorIndex && VectorIndex.Val < 4;
928 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000929
Tim Northover3b0846e2014-05-24 12:50:23 +0000930 bool isVectorIndexD() const {
931 return Kind == k_VectorIndex && VectorIndex.Val < 2;
932 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000933
Tim Northover3b0846e2014-05-24 12:50:23 +0000934 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000935
Tim Northover3b0846e2014-05-24 12:50:23 +0000936 bool isTokenEqual(StringRef Str) const {
937 return Kind == k_Token && getToken() == Str;
938 }
939 bool isSysCR() const { return Kind == k_SysCR; }
940 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000941 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000942 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
943 bool isShifter() const {
944 if (!isShiftExtend())
945 return false;
946
947 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
948 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
949 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
950 ST == AArch64_AM::MSL);
951 }
952 bool isExtend() const {
953 if (!isShiftExtend())
954 return false;
955
956 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
957 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
958 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
959 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
960 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
961 ET == AArch64_AM::LSL) &&
962 getShiftExtendAmount() <= 4;
963 }
964
965 bool isExtend64() const {
966 if (!isExtend())
967 return false;
968 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
969 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
970 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
971 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000972
Tim Northover3b0846e2014-05-24 12:50:23 +0000973 bool isExtendLSL64() const {
974 if (!isExtend())
975 return false;
976 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
977 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
978 ET == AArch64_AM::LSL) &&
979 getShiftExtendAmount() <= 4;
980 }
981
982 template<int Width> bool isMemXExtend() const {
983 if (!isExtend())
984 return false;
985 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
986 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
987 (getShiftExtendAmount() == Log2_32(Width / 8) ||
988 getShiftExtendAmount() == 0);
989 }
990
991 template<int Width> bool isMemWExtend() const {
992 if (!isExtend())
993 return false;
994 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
995 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
996 (getShiftExtendAmount() == Log2_32(Width / 8) ||
997 getShiftExtendAmount() == 0);
998 }
999
1000 template <unsigned width>
1001 bool isArithmeticShifter() const {
1002 if (!isShifter())
1003 return false;
1004
1005 // An arithmetic shifter is LSL, LSR, or ASR.
1006 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1007 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1008 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1009 }
1010
1011 template <unsigned width>
1012 bool isLogicalShifter() const {
1013 if (!isShifter())
1014 return false;
1015
1016 // A logical shifter is LSL, LSR, ASR or ROR.
1017 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1018 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1019 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1020 getShiftExtendAmount() < width;
1021 }
1022
1023 bool isMovImm32Shifter() const {
1024 if (!isShifter())
1025 return false;
1026
1027 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1028 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1029 if (ST != AArch64_AM::LSL)
1030 return false;
1031 uint64_t Val = getShiftExtendAmount();
1032 return (Val == 0 || Val == 16);
1033 }
1034
1035 bool isMovImm64Shifter() const {
1036 if (!isShifter())
1037 return false;
1038
1039 // A MOVi shifter is LSL of 0 or 16.
1040 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1041 if (ST != AArch64_AM::LSL)
1042 return false;
1043 uint64_t Val = getShiftExtendAmount();
1044 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1045 }
1046
1047 bool isLogicalVecShifter() const {
1048 if (!isShifter())
1049 return false;
1050
1051 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1052 unsigned Shift = getShiftExtendAmount();
1053 return getShiftExtendType() == AArch64_AM::LSL &&
1054 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1055 }
1056
1057 bool isLogicalVecHalfWordShifter() const {
1058 if (!isLogicalVecShifter())
1059 return false;
1060
1061 // A logical vector shifter is a left shift by 0 or 8.
1062 unsigned Shift = getShiftExtendAmount();
1063 return getShiftExtendType() == AArch64_AM::LSL &&
1064 (Shift == 0 || Shift == 8);
1065 }
1066
1067 bool isMoveVecShifter() const {
1068 if (!isShiftExtend())
1069 return false;
1070
1071 // A logical vector shifter is a left shift by 8 or 16.
1072 unsigned Shift = getShiftExtendAmount();
1073 return getShiftExtendType() == AArch64_AM::MSL &&
1074 (Shift == 8 || Shift == 16);
1075 }
1076
1077 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1078 // to LDUR/STUR when the offset is not legal for the former but is for
1079 // the latter. As such, in addition to checking for being a legal unscaled
1080 // address, also check that it is not a legal scaled address. This avoids
1081 // ambiguity in the matcher.
1082 template<int Width>
1083 bool isSImm9OffsetFB() const {
1084 return isSImm9() && !isUImm12Offset<Width / 8>();
1085 }
1086
1087 bool isAdrpLabel() const {
1088 // Validation was handled during parsing, so we just sanity check that
1089 // something didn't go haywire.
1090 if (!isImm())
1091 return false;
1092
1093 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1094 int64_t Val = CE->getValue();
1095 int64_t Min = - (4096 * (1LL << (21 - 1)));
1096 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1097 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1098 }
1099
1100 return true;
1101 }
1102
1103 bool isAdrLabel() const {
1104 // Validation was handled during parsing, so we just sanity check that
1105 // something didn't go haywire.
1106 if (!isImm())
1107 return false;
1108
1109 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1110 int64_t Val = CE->getValue();
1111 int64_t Min = - (1LL << (21 - 1));
1112 int64_t Max = ((1LL << (21 - 1)) - 1);
1113 return Val >= Min && Val <= Max;
1114 }
1115
1116 return true;
1117 }
1118
1119 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1120 // Add as immediates when possible. Null MCExpr = 0.
1121 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001122 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001123 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001124 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001125 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001126 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001127 }
1128
1129 void addRegOperands(MCInst &Inst, unsigned N) const {
1130 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001131 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001132 }
1133
1134 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1135 assert(N == 1 && "Invalid number of operands!");
1136 assert(
1137 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1138
1139 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1140 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1141 RI->getEncodingValue(getReg()));
1142
Jim Grosbache9119e42015-05-13 18:37:00 +00001143 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001144 }
1145
1146 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1147 assert(N == 1 && "Invalid number of operands!");
1148 assert(
1149 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001150 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001151 }
1152
1153 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1154 assert(N == 1 && "Invalid number of operands!");
1155 assert(
1156 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001157 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001158 }
1159
1160 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1161 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001162 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001163 }
1164
1165 template <unsigned NumRegs>
1166 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1167 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001168 static const unsigned FirstRegs[] = { AArch64::D0,
1169 AArch64::D0_D1,
1170 AArch64::D0_D1_D2,
1171 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001172 unsigned FirstReg = FirstRegs[NumRegs - 1];
1173
1174 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001175 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001176 }
1177
1178 template <unsigned NumRegs>
1179 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1180 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001181 static const unsigned FirstRegs[] = { AArch64::Q0,
1182 AArch64::Q0_Q1,
1183 AArch64::Q0_Q1_Q2,
1184 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001185 unsigned FirstReg = FirstRegs[NumRegs - 1];
1186
1187 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001188 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001189 }
1190
1191 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1192 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001193 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001194 }
1195
1196 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1197 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001198 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001199 }
1200
1201 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1202 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001203 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001204 }
1205
1206 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1207 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001208 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001209 }
1210
1211 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1212 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001213 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001214 }
1215
1216 void addImmOperands(MCInst &Inst, unsigned N) const {
1217 assert(N == 1 && "Invalid number of operands!");
1218 // If this is a pageoff symrefexpr with an addend, adjust the addend
1219 // to be only the page-offset portion. Otherwise, just add the expr
1220 // as-is.
1221 addExpr(Inst, getImm());
1222 }
1223
1224 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1225 assert(N == 2 && "Invalid number of operands!");
1226 if (isShiftedImm()) {
1227 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001228 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001229 } else {
1230 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001231 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001232 }
1233 }
1234
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001235 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1236 assert(N == 2 && "Invalid number of operands!");
1237
1238 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1239 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1240 int64_t Val = -CE->getValue();
1241 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1242
1243 Inst.addOperand(MCOperand::createImm(Val));
1244 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1245 }
1246
Tim Northover3b0846e2014-05-24 12:50:23 +00001247 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1248 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001249 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001250 }
1251
1252 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1253 assert(N == 1 && "Invalid number of operands!");
1254 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1255 if (!MCE)
1256 addExpr(Inst, getImm());
1257 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001258 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001259 }
1260
1261 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1262 addImmOperands(Inst, N);
1263 }
1264
1265 template<int Scale>
1266 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1267 assert(N == 1 && "Invalid number of operands!");
1268 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1269
1270 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001271 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001272 return;
1273 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001274 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001275 }
1276
1277 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1278 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001279 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001280 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001281 }
1282
Sam Parker6d42de72017-08-11 13:14:00 +00001283 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1284 assert(N == 1 && "Invalid number of operands!");
1285 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1286 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1287 }
1288
Tim Northover3b0846e2014-05-24 12:50:23 +00001289 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1290 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001291 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001292 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001293 }
1294
1295 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1296 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001297 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001298 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001299 }
1300
1301 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1302 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001303 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001304 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001305 }
1306
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001307 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1308 assert(N == 1 && "Invalid number of operands!");
1309 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1310 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1311 }
1312
Tim Northover3b0846e2014-05-24 12:50:23 +00001313 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1314 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001315 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001316 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001317 }
1318
1319 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1320 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001321 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001322 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001323 }
1324
1325 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1326 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001327 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001328 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001329 }
1330
1331 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1332 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001333 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001334 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001335 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001336 }
1337
1338 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1339 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001340 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001341 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001342 }
1343
1344 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1345 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001346 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001347 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001348 }
1349
1350 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1351 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001352 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001353 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001354 }
1355
1356 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1357 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001358 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001359 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001360 }
1361
1362 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1363 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001364 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001365 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001366 }
1367
1368 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1369 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001370 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001371 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001372 }
1373
1374 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1375 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001376 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001377 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001378 }
1379
1380 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1381 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001382 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001383 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001384 }
1385
1386 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1387 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001388 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001389 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001390 }
1391
1392 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1393 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001394 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001395 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001396 }
1397
1398 void addLogicalImm32Operands(MCInst &Inst, unsigned N) const {
1399 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001400 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +00001401 uint64_t encoding =
1402 AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001403 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001404 }
1405
1406 void addLogicalImm64Operands(MCInst &Inst, unsigned N) const {
1407 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001408 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001409 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001410 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001411 }
1412
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001413 void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
1414 assert(N == 1 && "Invalid number of operands!");
1415 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1416 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
1417 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001418 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001419 }
1420
1421 void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
1422 assert(N == 1 && "Invalid number of operands!");
1423 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1424 uint64_t encoding =
1425 AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001426 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001427 }
1428
Tim Northover3b0846e2014-05-24 12:50:23 +00001429 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1430 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001431 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001432 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001433 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 }
1435
1436 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1437 // Branch operands don't encode the low bits, so shift them off
1438 // here. If it's a label, however, just put it on directly as there's
1439 // not enough information now to do anything.
1440 assert(N == 1 && "Invalid number of operands!");
1441 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1442 if (!MCE) {
1443 addExpr(Inst, getImm());
1444 return;
1445 }
1446 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001447 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001448 }
1449
1450 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1451 // Branch operands don't encode the low bits, so shift them off
1452 // here. If it's a label, however, just put it on directly as there's
1453 // not enough information now to do anything.
1454 assert(N == 1 && "Invalid number of operands!");
1455 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1456 if (!MCE) {
1457 addExpr(Inst, getImm());
1458 return;
1459 }
1460 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001461 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001462 }
1463
1464 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1465 // Branch operands don't encode the low bits, so shift them off
1466 // here. If it's a label, however, just put it on directly as there's
1467 // not enough information now to do anything.
1468 assert(N == 1 && "Invalid number of operands!");
1469 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1470 if (!MCE) {
1471 addExpr(Inst, getImm());
1472 return;
1473 }
1474 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001475 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001476 }
1477
1478 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1479 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001480 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001481 }
1482
1483 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1484 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001485 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001486 }
1487
1488 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1489 assert(N == 1 && "Invalid number of operands!");
1490
Jim Grosbache9119e42015-05-13 18:37:00 +00001491 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001492 }
1493
1494 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1495 assert(N == 1 && "Invalid number of operands!");
1496
Jim Grosbache9119e42015-05-13 18:37:00 +00001497 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001498 }
1499
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001500 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1501 assert(N == 1 && "Invalid number of operands!");
1502
1503 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1504 }
1505
1506 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001507 assert(N == 1 && "Invalid number of operands!");
1508
Jim Grosbache9119e42015-05-13 18:37:00 +00001509 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001510 }
1511
1512 void addSysCROperands(MCInst &Inst, unsigned N) const {
1513 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001514 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001515 }
1516
1517 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1518 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001519 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001520 }
1521
Oliver Stannarda34e4702015-12-01 10:48:51 +00001522 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1523 assert(N == 1 && "Invalid number of operands!");
1524 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1525 }
1526
Tim Northover3b0846e2014-05-24 12:50:23 +00001527 void addShifterOperands(MCInst &Inst, unsigned N) const {
1528 assert(N == 1 && "Invalid number of operands!");
1529 unsigned Imm =
1530 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001531 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001532 }
1533
1534 void addExtendOperands(MCInst &Inst, unsigned N) const {
1535 assert(N == 1 && "Invalid number of operands!");
1536 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1537 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1538 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001539 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001540 }
1541
1542 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1543 assert(N == 1 && "Invalid number of operands!");
1544 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1545 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1546 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001547 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001548 }
1549
1550 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1551 assert(N == 2 && "Invalid number of operands!");
1552 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1553 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001554 Inst.addOperand(MCOperand::createImm(IsSigned));
1555 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001556 }
1557
1558 // For 8-bit load/store instructions with a register offset, both the
1559 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1560 // they're disambiguated by whether the shift was explicit or implicit rather
1561 // than its size.
1562 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1563 assert(N == 2 && "Invalid number of operands!");
1564 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1565 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001566 Inst.addOperand(MCOperand::createImm(IsSigned));
1567 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001568 }
1569
1570 template<int Shift>
1571 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1572 assert(N == 1 && "Invalid number of operands!");
1573
1574 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1575 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001576 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001577 }
1578
1579 template<int Shift>
1580 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1581 assert(N == 1 && "Invalid number of operands!");
1582
1583 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1584 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001585 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001586 }
1587
Sam Parker5f934642017-08-31 09:27:04 +00001588 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1589 assert(N == 1 && "Invalid number of operands!");
1590 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1591 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1592 }
1593
1594 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1595 assert(N == 1 && "Invalid number of operands!");
1596 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1597 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1598 }
1599
Tim Northover3b0846e2014-05-24 12:50:23 +00001600 void print(raw_ostream &OS) const override;
1601
David Blaikie960ea3f2014-06-08 16:18:35 +00001602 static std::unique_ptr<AArch64Operand>
1603 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1604 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001605 Op->Tok.Data = Str.data();
1606 Op->Tok.Length = Str.size();
1607 Op->Tok.IsSuffix = IsSuffix;
1608 Op->StartLoc = S;
1609 Op->EndLoc = S;
1610 return Op;
1611 }
1612
David Blaikie960ea3f2014-06-08 16:18:35 +00001613 static std::unique_ptr<AArch64Operand>
Florian Hahnc4422242017-11-07 13:07:50 +00001614 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001615 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001616 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001617 Op->Reg.Kind = Kind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001618 Op->StartLoc = S;
1619 Op->EndLoc = E;
1620 return Op;
1621 }
1622
David Blaikie960ea3f2014-06-08 16:18:35 +00001623 static std::unique_ptr<AArch64Operand>
Florian Hahn91f11e52017-11-07 16:45:48 +00001624 CreateReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1625 SMLoc S, SMLoc E, MCContext &Ctx) {
1626 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1627 Op->Reg.RegNum = RegNum;
1628 Op->Reg.ElementWidth = ElementWidth;
1629 Op->Reg.Kind = Kind;
1630 Op->StartLoc = S;
1631 Op->EndLoc = E;
1632 return Op;
1633 }
1634
1635 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001636 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1637 char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1638 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001639 Op->VectorList.RegNum = RegNum;
1640 Op->VectorList.Count = Count;
1641 Op->VectorList.NumElements = NumElements;
1642 Op->VectorList.ElementKind = ElementKind;
1643 Op->StartLoc = S;
1644 Op->EndLoc = E;
1645 return Op;
1646 }
1647
David Blaikie960ea3f2014-06-08 16:18:35 +00001648 static std::unique_ptr<AArch64Operand>
1649 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1650 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001651 Op->VectorIndex.Val = Idx;
1652 Op->StartLoc = S;
1653 Op->EndLoc = E;
1654 return Op;
1655 }
1656
David Blaikie960ea3f2014-06-08 16:18:35 +00001657 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1658 SMLoc E, MCContext &Ctx) {
1659 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001660 Op->Imm.Val = Val;
1661 Op->StartLoc = S;
1662 Op->EndLoc = E;
1663 return Op;
1664 }
1665
David Blaikie960ea3f2014-06-08 16:18:35 +00001666 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1667 unsigned ShiftAmount,
1668 SMLoc S, SMLoc E,
1669 MCContext &Ctx) {
1670 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001671 Op->ShiftedImm .Val = Val;
1672 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1673 Op->StartLoc = S;
1674 Op->EndLoc = E;
1675 return Op;
1676 }
1677
David Blaikie960ea3f2014-06-08 16:18:35 +00001678 static std::unique_ptr<AArch64Operand>
1679 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1680 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001681 Op->CondCode.Code = Code;
1682 Op->StartLoc = S;
1683 Op->EndLoc = E;
1684 return Op;
1685 }
1686
David Blaikie960ea3f2014-06-08 16:18:35 +00001687 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1688 MCContext &Ctx) {
1689 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001690 Op->FPImm.Val = Val;
1691 Op->StartLoc = S;
1692 Op->EndLoc = S;
1693 return Op;
1694 }
1695
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001696 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1697 StringRef Str,
1698 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001699 MCContext &Ctx) {
1700 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001701 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001702 Op->Barrier.Data = Str.data();
1703 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001704 Op->StartLoc = S;
1705 Op->EndLoc = S;
1706 return Op;
1707 }
1708
Tim Northover7cd58932015-01-22 17:23:04 +00001709 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1710 uint32_t MRSReg,
1711 uint32_t MSRReg,
1712 uint32_t PStateField,
1713 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001714 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001715 Op->SysReg.Data = Str.data();
1716 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001717 Op->SysReg.MRSReg = MRSReg;
1718 Op->SysReg.MSRReg = MSRReg;
1719 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001720 Op->StartLoc = S;
1721 Op->EndLoc = S;
1722 return Op;
1723 }
1724
David Blaikie960ea3f2014-06-08 16:18:35 +00001725 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1726 SMLoc E, MCContext &Ctx) {
1727 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001728 Op->SysCRImm.Val = Val;
1729 Op->StartLoc = S;
1730 Op->EndLoc = E;
1731 return Op;
1732 }
1733
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001734 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1735 StringRef Str,
1736 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001737 MCContext &Ctx) {
1738 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001739 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001740 Op->Barrier.Data = Str.data();
1741 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001742 Op->StartLoc = S;
1743 Op->EndLoc = S;
1744 return Op;
1745 }
1746
Oliver Stannarda34e4702015-12-01 10:48:51 +00001747 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1748 StringRef Str,
1749 SMLoc S,
1750 MCContext &Ctx) {
1751 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1752 Op->PSBHint.Val = Val;
1753 Op->PSBHint.Data = Str.data();
1754 Op->PSBHint.Length = Str.size();
1755 Op->StartLoc = S;
1756 Op->EndLoc = S;
1757 return Op;
1758 }
1759
David Blaikie960ea3f2014-06-08 16:18:35 +00001760 static std::unique_ptr<AArch64Operand>
1761 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1762 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1763 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001764 Op->ShiftExtend.Type = ShOp;
1765 Op->ShiftExtend.Amount = Val;
1766 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1767 Op->StartLoc = S;
1768 Op->EndLoc = E;
1769 return Op;
1770 }
1771};
1772
1773} // end anonymous namespace.
1774
1775void AArch64Operand::print(raw_ostream &OS) const {
1776 switch (Kind) {
1777 case k_FPImm:
1778 OS << "<fpimm " << getFPImm() << "("
1779 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1780 break;
1781 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001782 StringRef Name = getBarrierName();
1783 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001784 OS << "<barrier " << Name << ">";
1785 else
1786 OS << "<barrier invalid #" << getBarrier() << ">";
1787 break;
1788 }
1789 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001790 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001791 break;
1792 case k_ShiftedImm: {
1793 unsigned Shift = getShiftedImmShift();
1794 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001795 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001796 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1797 break;
1798 }
1799 case k_CondCode:
1800 OS << "<condcode " << getCondCode() << ">";
1801 break;
1802 case k_Register:
1803 OS << "<register " << getReg() << ">";
1804 break;
1805 case k_VectorList: {
1806 OS << "<vectorlist ";
1807 unsigned Reg = getVectorListStart();
1808 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1809 OS << Reg + i << " ";
1810 OS << ">";
1811 break;
1812 }
1813 case k_VectorIndex:
1814 OS << "<vectorindex " << getVectorIndex() << ">";
1815 break;
1816 case k_SysReg:
1817 OS << "<sysreg: " << getSysReg() << '>';
1818 break;
1819 case k_Token:
1820 OS << "'" << getToken() << "'";
1821 break;
1822 case k_SysCR:
1823 OS << "c" << getSysCR();
1824 break;
1825 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001826 StringRef Name = getPrefetchName();
1827 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001828 OS << "<prfop " << Name << ">";
1829 else
1830 OS << "<prfop invalid #" << getPrefetch() << ">";
1831 break;
1832 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001833 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001834 OS << getPSBHintName();
1835 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001836 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001837 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1838 << getShiftExtendAmount();
1839 if (!hasShiftExtendAmount())
1840 OS << "<imp>";
1841 OS << '>';
1842 break;
1843 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001844}
1845
1846/// @name Auto-generated Match Functions
1847/// {
1848
1849static unsigned MatchRegisterName(StringRef Name);
1850
1851/// }
1852
Florian Hahnc4422242017-11-07 13:07:50 +00001853static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001854 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001855 .Case("v0", AArch64::Q0)
1856 .Case("v1", AArch64::Q1)
1857 .Case("v2", AArch64::Q2)
1858 .Case("v3", AArch64::Q3)
1859 .Case("v4", AArch64::Q4)
1860 .Case("v5", AArch64::Q5)
1861 .Case("v6", AArch64::Q6)
1862 .Case("v7", AArch64::Q7)
1863 .Case("v8", AArch64::Q8)
1864 .Case("v9", AArch64::Q9)
1865 .Case("v10", AArch64::Q10)
1866 .Case("v11", AArch64::Q11)
1867 .Case("v12", AArch64::Q12)
1868 .Case("v13", AArch64::Q13)
1869 .Case("v14", AArch64::Q14)
1870 .Case("v15", AArch64::Q15)
1871 .Case("v16", AArch64::Q16)
1872 .Case("v17", AArch64::Q17)
1873 .Case("v18", AArch64::Q18)
1874 .Case("v19", AArch64::Q19)
1875 .Case("v20", AArch64::Q20)
1876 .Case("v21", AArch64::Q21)
1877 .Case("v22", AArch64::Q22)
1878 .Case("v23", AArch64::Q23)
1879 .Case("v24", AArch64::Q24)
1880 .Case("v25", AArch64::Q25)
1881 .Case("v26", AArch64::Q26)
1882 .Case("v27", AArch64::Q27)
1883 .Case("v28", AArch64::Q28)
1884 .Case("v29", AArch64::Q29)
1885 .Case("v30", AArch64::Q30)
1886 .Case("v31", AArch64::Q31)
1887 .Default(0);
1888}
1889
1890static bool isValidVectorKind(StringRef Name) {
1891 return StringSwitch<bool>(Name.lower())
1892 .Case(".8b", true)
1893 .Case(".16b", true)
1894 .Case(".4h", true)
1895 .Case(".8h", true)
1896 .Case(".2s", true)
1897 .Case(".4s", true)
1898 .Case(".1d", true)
1899 .Case(".2d", true)
1900 .Case(".1q", true)
1901 // Accept the width neutral ones, too, for verbose syntax. If those
1902 // aren't used in the right places, the token operand won't match so
1903 // all will work out.
1904 .Case(".b", true)
1905 .Case(".h", true)
1906 .Case(".s", true)
1907 .Case(".d", true)
Oliver Stannarde4c3d212015-12-08 12:16:10 +00001908 // Needed for fp16 scalar pairwise reductions
1909 .Case(".2h", true)
Sjoerd Meijer79876332017-08-09 14:59:54 +00001910 // another special case for the ARMv8.2a dot product operand
1911 .Case(".4b", true)
Tim Northover3b0846e2014-05-24 12:50:23 +00001912 .Default(false);
1913}
1914
Florian Hahn91f11e52017-11-07 16:45:48 +00001915static unsigned matchSVEDataVectorRegName(StringRef Name) {
1916 return StringSwitch<unsigned>(Name.lower())
1917 .Case("z0", AArch64::Z0)
1918 .Case("z1", AArch64::Z1)
1919 .Case("z2", AArch64::Z2)
1920 .Case("z3", AArch64::Z3)
1921 .Case("z4", AArch64::Z4)
1922 .Case("z5", AArch64::Z5)
1923 .Case("z6", AArch64::Z6)
1924 .Case("z7", AArch64::Z7)
1925 .Case("z8", AArch64::Z8)
1926 .Case("z9", AArch64::Z9)
1927 .Case("z10", AArch64::Z10)
1928 .Case("z11", AArch64::Z11)
1929 .Case("z12", AArch64::Z12)
1930 .Case("z13", AArch64::Z13)
1931 .Case("z14", AArch64::Z14)
1932 .Case("z15", AArch64::Z15)
1933 .Case("z16", AArch64::Z16)
1934 .Case("z17", AArch64::Z17)
1935 .Case("z18", AArch64::Z18)
1936 .Case("z19", AArch64::Z19)
1937 .Case("z20", AArch64::Z20)
1938 .Case("z21", AArch64::Z21)
1939 .Case("z22", AArch64::Z22)
1940 .Case("z23", AArch64::Z23)
1941 .Case("z24", AArch64::Z24)
1942 .Case("z25", AArch64::Z25)
1943 .Case("z26", AArch64::Z26)
1944 .Case("z27", AArch64::Z27)
1945 .Case("z28", AArch64::Z28)
1946 .Case("z29", AArch64::Z29)
1947 .Case("z30", AArch64::Z30)
1948 .Case("z31", AArch64::Z31)
1949 .Default(0);
1950}
1951
Sander de Smalencd6be962017-12-20 11:02:42 +00001952static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1953 return StringSwitch<unsigned>(Name.lower())
1954 .Case("p0", AArch64::P0)
1955 .Case("p1", AArch64::P1)
1956 .Case("p2", AArch64::P2)
1957 .Case("p3", AArch64::P3)
1958 .Case("p4", AArch64::P4)
1959 .Case("p5", AArch64::P5)
1960 .Case("p6", AArch64::P6)
1961 .Case("p7", AArch64::P7)
1962 .Case("p8", AArch64::P8)
1963 .Case("p9", AArch64::P9)
1964 .Case("p10", AArch64::P10)
1965 .Case("p11", AArch64::P11)
1966 .Case("p12", AArch64::P12)
1967 .Case("p13", AArch64::P13)
1968 .Case("p14", AArch64::P14)
1969 .Case("p15", AArch64::P15)
1970 .Default(0);
1971}
1972
Florian Hahn91f11e52017-11-07 16:45:48 +00001973static bool isValidSVEKind(StringRef Name) {
1974 return StringSwitch<bool>(Name.lower())
1975 .Case(".b", true)
1976 .Case(".h", true)
1977 .Case(".s", true)
1978 .Case(".d", true)
1979 .Case(".q", true)
1980 .Default(false);
1981}
1982
Tim Northover3b0846e2014-05-24 12:50:23 +00001983static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1984 char &ElementKind) {
1985 assert(isValidVectorKind(Name));
1986
1987 ElementKind = Name.lower()[Name.size() - 1];
1988 NumElements = 0;
1989
1990 if (Name.size() == 2)
1991 return;
1992
1993 // Parse the lane count
1994 Name = Name.drop_front();
1995 while (isdigit(Name.front())) {
1996 NumElements = 10 * NumElements + (Name.front() - '0');
1997 Name = Name.drop_front();
1998 }
1999}
2000
2001bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2002 SMLoc &EndLoc) {
2003 StartLoc = getLoc();
2004 RegNo = tryParseRegister();
2005 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2006 return (RegNo == (unsigned)-1);
2007}
2008
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002009// Matches a register name or register alias previously defined by '.req'
2010unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002011 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002012 unsigned RegNum = 0;
2013 if ((RegNum = matchSVEDataVectorRegName(Name)))
2014 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2015
Sander de Smalencd6be962017-12-20 11:02:42 +00002016 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2017 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2018
Sander de Smalenc067c302017-12-20 09:45:45 +00002019 if ((RegNum = MatchNeonVectorRegName(Name)))
2020 return Kind == RegKind::NeonVector ? RegNum : 0;
2021
2022 // The parsed register must be of RegKind Scalar
2023 if ((RegNum = MatchRegisterName(Name)))
2024 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002025
Florian Hahnc4422242017-11-07 13:07:50 +00002026 if (!RegNum) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002027 // Check for aliases registered via .req. Canonicalize to lower case.
2028 // That's more consistent since register names are case insensitive, and
2029 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2030 auto Entry = RegisterReqs.find(Name.lower());
2031 if (Entry == RegisterReqs.end())
2032 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002033
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002034 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002035 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002036 RegNum = Entry->getValue().second;
2037 }
2038 return RegNum;
2039}
2040
Tim Northover3b0846e2014-05-24 12:50:23 +00002041/// tryParseRegister - Try to parse a register name. The token must be an
2042/// Identifier when called, and if it is a register name the token is eaten and
2043/// the register is added to the operand list.
2044int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002045 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002046 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002047 if (Tok.isNot(AsmToken::Identifier))
2048 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00002049
2050 std::string lowerCase = Tok.getString().lower();
Florian Hahnc4422242017-11-07 13:07:50 +00002051 unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
Sander de Smalenc067c302017-12-20 09:45:45 +00002052
Tim Northover3b0846e2014-05-24 12:50:23 +00002053 // Also handle a few aliases of registers.
2054 if (RegNum == 0)
2055 RegNum = StringSwitch<unsigned>(lowerCase)
2056 .Case("fp", AArch64::FP)
2057 .Case("lr", AArch64::LR)
2058 .Case("x31", AArch64::XZR)
2059 .Case("w31", AArch64::WZR)
2060 .Default(0);
2061
2062 if (RegNum == 0)
2063 return -1;
2064
2065 Parser.Lex(); // Eat identifier token.
2066 return RegNum;
2067}
2068
2069/// tryMatchVectorRegister - Try to parse a vector register name with optional
2070/// kind specifier. If it is a register specifier, eat the token and return it.
2071int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002072 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002073 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2074 TokError("vector register expected");
2075 return -1;
2076 }
2077
2078 StringRef Name = Parser.getTok().getString();
2079 // If there is a kind specifier, it's separated from the register name by
2080 // a '.'.
2081 size_t Start = 0, Next = Name.find('.');
2082 StringRef Head = Name.slice(Start, Next);
Florian Hahnc4422242017-11-07 13:07:50 +00002083 unsigned RegNum = matchRegisterNameAlias(Head, RegKind::NeonVector);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002084
Tim Northover3b0846e2014-05-24 12:50:23 +00002085 if (RegNum) {
2086 if (Next != StringRef::npos) {
2087 Kind = Name.slice(Next, StringRef::npos);
2088 if (!isValidVectorKind(Kind)) {
2089 TokError("invalid vector kind qualifier");
2090 return -1;
2091 }
2092 }
2093 Parser.Lex(); // Eat the register token.
2094 return RegNum;
2095 }
2096
2097 if (expected)
2098 TokError("vector register expected");
2099 return -1;
2100}
2101
2102/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002103OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002104AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002105 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002106 SMLoc S = getLoc();
2107
2108 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2109 Error(S, "Expected cN operand where 0 <= N <= 15");
2110 return MatchOperand_ParseFail;
2111 }
2112
2113 StringRef Tok = Parser.getTok().getIdentifier();
2114 if (Tok[0] != 'c' && Tok[0] != 'C') {
2115 Error(S, "Expected cN operand where 0 <= N <= 15");
2116 return MatchOperand_ParseFail;
2117 }
2118
2119 uint32_t CRNum;
2120 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2121 if (BadNum || CRNum > 15) {
2122 Error(S, "Expected cN operand where 0 <= N <= 15");
2123 return MatchOperand_ParseFail;
2124 }
2125
2126 Parser.Lex(); // Eat identifier token.
2127 Operands.push_back(
2128 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2129 return MatchOperand_Success;
2130}
2131
2132/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002133OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002134AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002135 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002136 SMLoc S = getLoc();
2137 const AsmToken &Tok = Parser.getTok();
2138 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002139 // Eat optional hash.
2140 if (parseOptionalToken(AsmToken::Hash) ||
2141 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002142 const MCExpr *ImmVal;
2143 if (getParser().parseExpression(ImmVal))
2144 return MatchOperand_ParseFail;
2145
2146 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2147 if (!MCE) {
2148 TokError("immediate value expected for prefetch operand");
2149 return MatchOperand_ParseFail;
2150 }
2151 unsigned prfop = MCE->getValue();
2152 if (prfop > 31) {
2153 TokError("prefetch operand out of range, [0,31] expected");
2154 return MatchOperand_ParseFail;
2155 }
2156
Tim Northovere6ae6762016-07-05 21:23:04 +00002157 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2158 Operands.push_back(AArch64Operand::CreatePrefetch(
2159 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002160 return MatchOperand_Success;
2161 }
2162
2163 if (Tok.isNot(AsmToken::Identifier)) {
2164 TokError("pre-fetch hint expected");
2165 return MatchOperand_ParseFail;
2166 }
2167
Tim Northovere6ae6762016-07-05 21:23:04 +00002168 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2169 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002170 TokError("pre-fetch hint expected");
2171 return MatchOperand_ParseFail;
2172 }
2173
2174 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002175 Operands.push_back(AArch64Operand::CreatePrefetch(
2176 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002177 return MatchOperand_Success;
2178}
2179
Oliver Stannarda34e4702015-12-01 10:48:51 +00002180/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002181OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002182AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2183 MCAsmParser &Parser = getParser();
2184 SMLoc S = getLoc();
2185 const AsmToken &Tok = Parser.getTok();
2186 if (Tok.isNot(AsmToken::Identifier)) {
2187 TokError("invalid operand for instruction");
2188 return MatchOperand_ParseFail;
2189 }
2190
Tim Northovere6ae6762016-07-05 21:23:04 +00002191 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2192 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002193 TokError("invalid operand for instruction");
2194 return MatchOperand_ParseFail;
2195 }
2196
2197 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002198 Operands.push_back(AArch64Operand::CreatePSBHint(
2199 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002200 return MatchOperand_Success;
2201}
2202
Tim Northover3b0846e2014-05-24 12:50:23 +00002203/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2204/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002205OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002206AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002207 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002208 SMLoc S = getLoc();
2209 const MCExpr *Expr;
2210
2211 if (Parser.getTok().is(AsmToken::Hash)) {
2212 Parser.Lex(); // Eat hash token.
2213 }
2214
2215 if (parseSymbolicImmVal(Expr))
2216 return MatchOperand_ParseFail;
2217
2218 AArch64MCExpr::VariantKind ELFRefKind;
2219 MCSymbolRefExpr::VariantKind DarwinRefKind;
2220 int64_t Addend;
2221 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2222 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2223 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2224 // No modifier was specified at all; this is the syntax for an ELF basic
2225 // ADRP relocation (unfortunately).
2226 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002227 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002228 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2229 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2230 Addend != 0) {
2231 Error(S, "gotpage label reference not allowed an addend");
2232 return MatchOperand_ParseFail;
2233 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2234 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2235 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2236 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2237 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2238 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2239 // The operand must be an @page or @gotpage qualified symbolref.
2240 Error(S, "page or gotpage label reference expected");
2241 return MatchOperand_ParseFail;
2242 }
2243 }
2244
2245 // We have either a label reference possibly with addend or an immediate. The
2246 // addend is a raw value here. The linker will adjust it to only reference the
2247 // page.
2248 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2249 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2250
2251 return MatchOperand_Success;
2252}
2253
2254/// tryParseAdrLabel - Parse and validate a source label for the ADR
2255/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002256OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002257AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2258 SMLoc S = getLoc();
2259 const MCExpr *Expr;
2260
Nirav Davee833c6c2016-11-08 18:31:04 +00002261 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002262 if (getParser().parseExpression(Expr))
2263 return MatchOperand_ParseFail;
2264
2265 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2266 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2267
2268 return MatchOperand_Success;
2269}
2270
2271/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002272OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002273AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002274 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002275 SMLoc S = getLoc();
2276
Nirav Davee833c6c2016-11-08 18:31:04 +00002277 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002278
2279 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002280 bool isNegative = parseOptionalToken(AsmToken::Minus);
2281
Tim Northover3b0846e2014-05-24 12:50:23 +00002282 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002283 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002284 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002285 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002286 Val = Tok.getIntVal();
2287 if (Val > 255 || Val < 0) {
2288 TokError("encoded floating point value out of range");
2289 return MatchOperand_ParseFail;
2290 }
2291 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002292 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002293 if (isNegative)
2294 RealVal.changeSign();
2295
Tim Northover3b0846e2014-05-24 12:50:23 +00002296 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002297 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002298
John Brawn5ca5daa2017-04-20 10:13:54 +00002299 // Check for out of range values. As an exception we let Zero through,
2300 // but as tokens instead of an FPImm so that it can be matched by the
2301 // appropriate alias if one exists.
2302 if (RealVal.isPosZero()) {
2303 Parser.Lex(); // Eat the token.
2304 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2305 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2306 return MatchOperand_Success;
2307 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002308 TokError("expected compatible register or floating-point constant");
2309 return MatchOperand_ParseFail;
2310 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002311 }
2312 Parser.Lex(); // Eat the token.
2313 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2314 return MatchOperand_Success;
2315 }
2316
2317 if (!Hash)
2318 return MatchOperand_NoMatch;
2319
2320 TokError("invalid floating point immediate");
2321 return MatchOperand_ParseFail;
2322}
2323
2324/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002325OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002326AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002327 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002328 SMLoc S = getLoc();
2329
2330 if (Parser.getTok().is(AsmToken::Hash))
2331 Parser.Lex(); // Eat '#'
2332 else if (Parser.getTok().isNot(AsmToken::Integer))
2333 // Operand should start from # or should be integer, emit error otherwise.
2334 return MatchOperand_NoMatch;
2335
2336 const MCExpr *Imm;
2337 if (parseSymbolicImmVal(Imm))
2338 return MatchOperand_ParseFail;
2339 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2340 uint64_t ShiftAmount = 0;
2341 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2342 if (MCE) {
2343 int64_t Val = MCE->getValue();
2344 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002345 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002346 ShiftAmount = 12;
2347 }
2348 }
2349 SMLoc E = Parser.getTok().getLoc();
2350 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2351 getContext()));
2352 return MatchOperand_Success;
2353 }
2354
2355 // Eat ','
2356 Parser.Lex();
2357
2358 // The optional operand must be "lsl #N" where N is non-negative.
2359 if (!Parser.getTok().is(AsmToken::Identifier) ||
2360 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2361 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2362 return MatchOperand_ParseFail;
2363 }
2364
2365 // Eat 'lsl'
2366 Parser.Lex();
2367
Nirav Davee833c6c2016-11-08 18:31:04 +00002368 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002369
2370 if (Parser.getTok().isNot(AsmToken::Integer)) {
2371 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2372 return MatchOperand_ParseFail;
2373 }
2374
2375 int64_t ShiftAmount = Parser.getTok().getIntVal();
2376
2377 if (ShiftAmount < 0) {
2378 Error(Parser.getTok().getLoc(), "positive shift amount required");
2379 return MatchOperand_ParseFail;
2380 }
2381 Parser.Lex(); // Eat the number
2382
2383 SMLoc E = Parser.getTok().getLoc();
2384 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2385 S, E, getContext()));
2386 return MatchOperand_Success;
2387}
2388
2389/// parseCondCodeString - Parse a Condition Code string.
2390AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2391 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2392 .Case("eq", AArch64CC::EQ)
2393 .Case("ne", AArch64CC::NE)
2394 .Case("cs", AArch64CC::HS)
2395 .Case("hs", AArch64CC::HS)
2396 .Case("cc", AArch64CC::LO)
2397 .Case("lo", AArch64CC::LO)
2398 .Case("mi", AArch64CC::MI)
2399 .Case("pl", AArch64CC::PL)
2400 .Case("vs", AArch64CC::VS)
2401 .Case("vc", AArch64CC::VC)
2402 .Case("hi", AArch64CC::HI)
2403 .Case("ls", AArch64CC::LS)
2404 .Case("ge", AArch64CC::GE)
2405 .Case("lt", AArch64CC::LT)
2406 .Case("gt", AArch64CC::GT)
2407 .Case("le", AArch64CC::LE)
2408 .Case("al", AArch64CC::AL)
2409 .Case("nv", AArch64CC::NV)
2410 .Default(AArch64CC::Invalid);
2411 return CC;
2412}
2413
2414/// parseCondCode - Parse a Condition Code operand.
2415bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2416 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002417 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002418 SMLoc S = getLoc();
2419 const AsmToken &Tok = Parser.getTok();
2420 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2421
2422 StringRef Cond = Tok.getString();
2423 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2424 if (CC == AArch64CC::Invalid)
2425 return TokError("invalid condition code");
2426 Parser.Lex(); // Eat identifier token.
2427
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002428 if (invertCondCode) {
2429 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2430 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002431 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002432 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002433
2434 Operands.push_back(
2435 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2436 return false;
2437}
2438
2439/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2440/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002441OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002442AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002443 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002444 const AsmToken &Tok = Parser.getTok();
2445 std::string LowerID = Tok.getString().lower();
2446 AArch64_AM::ShiftExtendType ShOp =
2447 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2448 .Case("lsl", AArch64_AM::LSL)
2449 .Case("lsr", AArch64_AM::LSR)
2450 .Case("asr", AArch64_AM::ASR)
2451 .Case("ror", AArch64_AM::ROR)
2452 .Case("msl", AArch64_AM::MSL)
2453 .Case("uxtb", AArch64_AM::UXTB)
2454 .Case("uxth", AArch64_AM::UXTH)
2455 .Case("uxtw", AArch64_AM::UXTW)
2456 .Case("uxtx", AArch64_AM::UXTX)
2457 .Case("sxtb", AArch64_AM::SXTB)
2458 .Case("sxth", AArch64_AM::SXTH)
2459 .Case("sxtw", AArch64_AM::SXTW)
2460 .Case("sxtx", AArch64_AM::SXTX)
2461 .Default(AArch64_AM::InvalidShiftExtend);
2462
2463 if (ShOp == AArch64_AM::InvalidShiftExtend)
2464 return MatchOperand_NoMatch;
2465
2466 SMLoc S = Tok.getLoc();
2467 Parser.Lex();
2468
Nirav Davee833c6c2016-11-08 18:31:04 +00002469 bool Hash = parseOptionalToken(AsmToken::Hash);
2470
Tim Northover3b0846e2014-05-24 12:50:23 +00002471 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2472 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2473 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2474 ShOp == AArch64_AM::MSL) {
2475 // We expect a number here.
2476 TokError("expected #imm after shift specifier");
2477 return MatchOperand_ParseFail;
2478 }
2479
Chad Rosier2ff37b82016-12-27 16:58:09 +00002480 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002481 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2482 Operands.push_back(
2483 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2484 return MatchOperand_Success;
2485 }
2486
Chad Rosier2ff37b82016-12-27 16:58:09 +00002487 // Make sure we do actually have a number, identifier or a parenthesized
2488 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002489 SMLoc E = Parser.getTok().getLoc();
2490 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002491 !Parser.getTok().is(AsmToken::LParen) &&
2492 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002493 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002494 return MatchOperand_ParseFail;
2495 }
2496
2497 const MCExpr *ImmVal;
2498 if (getParser().parseExpression(ImmVal))
2499 return MatchOperand_ParseFail;
2500
2501 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2502 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002503 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002504 return MatchOperand_ParseFail;
2505 }
2506
Jim Grosbach57fd2622014-09-23 22:16:02 +00002507 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002508 Operands.push_back(AArch64Operand::CreateShiftExtend(
2509 ShOp, MCE->getValue(), true, S, E, getContext()));
2510 return MatchOperand_Success;
2511}
2512
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002513static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2514 if (FBS[AArch64::HasV8_1aOps])
2515 Str += "ARMv8.1a";
2516 else if (FBS[AArch64::HasV8_2aOps])
2517 Str += "ARMv8.2a";
2518 else
2519 Str += "(unknown)";
2520}
2521
2522void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2523 SMLoc S) {
2524 const uint16_t Op2 = Encoding & 7;
2525 const uint16_t Cm = (Encoding & 0x78) >> 3;
2526 const uint16_t Cn = (Encoding & 0x780) >> 7;
2527 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2528
2529 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2530
2531 Operands.push_back(
2532 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2533 Operands.push_back(
2534 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2535 Operands.push_back(
2536 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2537 Expr = MCConstantExpr::create(Op2, getContext());
2538 Operands.push_back(
2539 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2540}
2541
Tim Northover3b0846e2014-05-24 12:50:23 +00002542/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2543/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2544bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2545 OperandVector &Operands) {
2546 if (Name.find('.') != StringRef::npos)
2547 return TokError("invalid operand");
2548
2549 Mnemonic = Name;
2550 Operands.push_back(
2551 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2552
Rafael Espindola961d4692014-11-11 05:18:41 +00002553 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002554 const AsmToken &Tok = Parser.getTok();
2555 StringRef Op = Tok.getString();
2556 SMLoc S = Tok.getLoc();
2557
Tim Northover3b0846e2014-05-24 12:50:23 +00002558 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002559 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2560 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002561 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002562 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2563 std::string Str("IC " + std::string(IC->Name) + " requires ");
2564 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2565 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002566 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002567 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002568 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002569 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2570 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002571 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002572 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2573 std::string Str("DC " + std::string(DC->Name) + " requires ");
2574 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2575 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002576 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002577 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002578 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002579 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2580 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002581 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002582 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2583 std::string Str("AT " + std::string(AT->Name) + " requires ");
2584 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2585 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002586 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002587 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002588 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002589 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2590 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002591 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002592 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2593 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2594 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2595 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002596 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002597 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002598 }
2599
Tim Northover3b0846e2014-05-24 12:50:23 +00002600 Parser.Lex(); // Eat operand.
2601
2602 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2603 bool HasRegister = false;
2604
2605 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002606 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002607 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2608 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002609 HasRegister = true;
2610 }
2611
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002612 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002613 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002614 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002615 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002616
Nirav Davee833c6c2016-11-08 18:31:04 +00002617 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2618 return true;
2619
Tim Northover3b0846e2014-05-24 12:50:23 +00002620 return false;
2621}
2622
Alex Bradbury58eba092016-11-01 16:32:05 +00002623OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002624AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002625 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002626 const AsmToken &Tok = Parser.getTok();
2627
2628 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002629 if (parseOptionalToken(AsmToken::Hash) ||
2630 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002631 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002632 const MCExpr *ImmVal;
2633 SMLoc ExprLoc = getLoc();
2634 if (getParser().parseExpression(ImmVal))
2635 return MatchOperand_ParseFail;
2636 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2637 if (!MCE) {
2638 Error(ExprLoc, "immediate value expected for barrier operand");
2639 return MatchOperand_ParseFail;
2640 }
2641 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2642 Error(ExprLoc, "barrier operand out of range");
2643 return MatchOperand_ParseFail;
2644 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002645 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2646 Operands.push_back(AArch64Operand::CreateBarrier(
2647 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002648 return MatchOperand_Success;
2649 }
2650
2651 if (Tok.isNot(AsmToken::Identifier)) {
2652 TokError("invalid operand for instruction");
2653 return MatchOperand_ParseFail;
2654 }
2655
Tim Northover3b0846e2014-05-24 12:50:23 +00002656 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002657 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2658 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002659 TokError("'sy' or #imm operand expected");
2660 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002661 } else if (!DB) {
2662 TokError("invalid barrier option name");
2663 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002664 }
2665
Tim Northovere6ae6762016-07-05 21:23:04 +00002666 Operands.push_back(AArch64Operand::CreateBarrier(
2667 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002668 Parser.Lex(); // Consume the option
2669
2670 return MatchOperand_Success;
2671}
2672
Alex Bradbury58eba092016-11-01 16:32:05 +00002673OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002674AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002675 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002676 const AsmToken &Tok = Parser.getTok();
2677
2678 if (Tok.isNot(AsmToken::Identifier))
2679 return MatchOperand_NoMatch;
2680
Tim Northovere6ae6762016-07-05 21:23:04 +00002681 int MRSReg, MSRReg;
2682 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2683 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2684 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2685 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2686 } else
2687 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002688
Tim Northovere6ae6762016-07-05 21:23:04 +00002689 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2690 unsigned PStateImm = -1;
2691 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2692 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002693
Tim Northovere6ae6762016-07-05 21:23:04 +00002694 Operands.push_back(
2695 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2696 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002697 Parser.Lex(); // Eat identifier
2698
2699 return MatchOperand_Success;
2700}
2701
Florian Hahnc4422242017-11-07 13:07:50 +00002702/// tryParseNeonVectorRegister - Parse a vector register operand.
2703bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002704 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002705 if (Parser.getTok().isNot(AsmToken::Identifier))
2706 return true;
2707
2708 SMLoc S = getLoc();
2709 // Check for a vector register specifier first.
2710 StringRef Kind;
2711 int64_t Reg = tryMatchVectorRegister(Kind, false);
2712 if (Reg == -1)
2713 return true;
2714 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00002715 AArch64Operand::CreateReg(Reg, RegKind::NeonVector, S, getLoc(),
2716 getContext()));
2717
Tim Northover3b0846e2014-05-24 12:50:23 +00002718 // If there was an explicit qualifier, that goes on as a literal text
2719 // operand.
2720 if (!Kind.empty())
2721 Operands.push_back(
2722 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2723
2724 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002725 SMLoc SIdx = getLoc();
2726 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002727 const MCExpr *ImmVal;
2728 if (getParser().parseExpression(ImmVal))
2729 return false;
2730 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2731 if (!MCE) {
2732 TokError("immediate value expected for vector index");
2733 return false;
2734 }
2735
2736 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002737
Nirav Davee833c6c2016-11-08 18:31:04 +00002738 if (parseToken(AsmToken::RBrac, "']' expected"))
2739 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002740
2741 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2742 E, getContext()));
2743 }
2744
2745 return false;
2746}
2747
Florian Hahn91f11e52017-11-07 16:45:48 +00002748// tryParseSVEDataVectorRegister - Try to parse a SVE vector register name with
2749// optional kind specifier. If it is a register specifier, eat the token
2750// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002751OperandMatchResultTy
2752AArch64AsmParser::tryParseSVERegister(int &Reg, StringRef &Kind,
2753 RegKind MatchKind) {
2754 MCAsmParser &Parser = getParser();
2755 const AsmToken &Tok = Parser.getTok();
2756
Florian Hahn91f11e52017-11-07 16:45:48 +00002757 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002758 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002759
2760 StringRef Name = Tok.getString();
2761 // If there is a kind specifier, it's separated from the register name by
2762 // a '.'.
2763 size_t Start = 0, Next = Name.find('.');
2764 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002765 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002766
2767 if (RegNum) {
2768 if (Next != StringRef::npos) {
2769 Kind = Name.slice(Next, StringRef::npos);
2770 if (!isValidSVEKind(Kind)) {
2771 TokError("invalid sve vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002772 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002773 }
2774 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002775 Parser.Lex(); // Eat the register token.
2776
2777 Reg = RegNum;
2778 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002779 }
2780
Sander de Smalen8e607342017-11-15 15:44:43 +00002781 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002782}
2783
Sander de Smalencd6be962017-12-20 11:02:42 +00002784/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2785OperandMatchResultTy
2786AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2787 // Check for a SVE predicate register specifier first.
2788 const SMLoc S = getLoc();
2789 StringRef Kind;
2790 int RegNum = -1;
2791 auto Res = tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
2792 if (Res != MatchOperand_Success)
2793 return Res;
2794
2795 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
2796 .Case("", -1)
2797 .Case(".b", 8)
2798 .Case(".h", 16)
2799 .Case(".s", 32)
2800 .Case(".d", 64)
2801 .Case(".q", 128)
2802 .Default(0);
2803
2804 if (!ElementWidth)
2805 return MatchOperand_NoMatch;
2806
2807 Operands.push_back(
2808 AArch64Operand::CreateReg(RegNum, RegKind::SVEPredicateVector,
2809 ElementWidth, S, getLoc(), getContext()));
2810
Sander de Smalen7868e742018-01-09 11:17:06 +00002811 // Not all predicates are followed by a '/m' or '/z'.
2812 MCAsmParser &Parser = getParser();
2813 if (Parser.getTok().isNot(AsmToken::Slash))
2814 return MatchOperand_Success;
2815
2816 // But when they do they shouldn't have an element type suffix.
2817 if (!Kind.empty()) {
2818 Error(S, "not expecting size suffix");
2819 return MatchOperand_ParseFail;
2820 }
2821
2822 // Add a literal slash as operand
2823 Operands.push_back(
2824 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2825
2826 Parser.Lex(); // Eat the slash.
2827
2828 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002829 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002830 if (Pred != "z" && Pred != "m") {
2831 Error(getLoc(), "expecting 'm' or 'z' predication");
2832 return MatchOperand_ParseFail;
2833 }
2834
2835 // Add zero/merge token.
2836 const char *ZM = Pred == "z" ? "z" : "m";
2837 Operands.push_back(
2838 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2839
2840 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002841 return MatchOperand_Success;
2842}
2843
Tim Northover3b0846e2014-05-24 12:50:23 +00002844/// parseRegister - Parse a non-vector register operand.
2845bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2846 SMLoc S = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00002847 // Try for a vector (neon) register.
2848 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002849 return false;
2850
2851 // Try for a scalar register.
2852 int64_t Reg = tryParseRegister();
2853 if (Reg == -1)
2854 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002855 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2856 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002857
Tim Northover3b0846e2014-05-24 12:50:23 +00002858 return false;
2859}
2860
2861bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002862 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002863 bool HasELFModifier = false;
2864 AArch64MCExpr::VariantKind RefKind;
2865
Nirav Davee833c6c2016-11-08 18:31:04 +00002866 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002867 HasELFModifier = true;
2868
Nirav Davee833c6c2016-11-08 18:31:04 +00002869 if (Parser.getTok().isNot(AsmToken::Identifier))
2870 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002871
2872 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2873 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2874 .Case("lo12", AArch64MCExpr::VK_LO12)
2875 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2876 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2877 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2878 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2879 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2880 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2881 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2882 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2883 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2884 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2885 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2886 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2887 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2888 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2889 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2890 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2891 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2892 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2893 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2894 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2895 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2896 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2897 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2898 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2899 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2900 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2901 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2902 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2903 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2904 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2905 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2906 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2907 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2908 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2909 .Default(AArch64MCExpr::VK_INVALID);
2910
Nirav Davee833c6c2016-11-08 18:31:04 +00002911 if (RefKind == AArch64MCExpr::VK_INVALID)
2912 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002913
2914 Parser.Lex(); // Eat identifier
2915
Nirav Davee833c6c2016-11-08 18:31:04 +00002916 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002917 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002918 }
2919
2920 if (getParser().parseExpression(ImmVal))
2921 return true;
2922
2923 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002924 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002925
2926 return false;
2927}
2928
2929/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2930bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002931 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002932 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2933 SMLoc S = getLoc();
2934 Parser.Lex(); // Eat left bracket token.
2935 StringRef Kind;
2936 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2937 if (FirstReg == -1)
2938 return true;
2939 int64_t PrevReg = FirstReg;
2940 unsigned Count = 1;
2941
Nirav Davee833c6c2016-11-08 18:31:04 +00002942 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002943 SMLoc Loc = getLoc();
2944 StringRef NextKind;
2945 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2946 if (Reg == -1)
2947 return true;
2948 // Any Kind suffices must match on all regs in the list.
2949 if (Kind != NextKind)
2950 return Error(Loc, "mismatched register size suffix");
2951
2952 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2953
2954 if (Space == 0 || Space > 3) {
2955 return Error(Loc, "invalid number of vectors");
2956 }
2957
2958 Count += Space;
2959 }
2960 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002961 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002962 SMLoc Loc = getLoc();
2963 StringRef NextKind;
2964 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2965 if (Reg == -1)
2966 return true;
2967 // Any Kind suffices must match on all regs in the list.
2968 if (Kind != NextKind)
2969 return Error(Loc, "mismatched register size suffix");
2970
2971 // Registers must be incremental (with wraparound at 31)
2972 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2973 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2974 return Error(Loc, "registers must be sequential");
2975
2976 PrevReg = Reg;
2977 ++Count;
2978 }
2979 }
2980
Nirav Davee833c6c2016-11-08 18:31:04 +00002981 if (parseToken(AsmToken::RCurly, "'}' expected"))
2982 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002983
2984 if (Count > 4)
2985 return Error(S, "invalid number of vectors");
2986
2987 unsigned NumElements = 0;
2988 char ElementKind = 0;
2989 if (!Kind.empty())
2990 parseValidVectorKind(Kind, NumElements, ElementKind);
2991
2992 Operands.push_back(AArch64Operand::CreateVectorList(
2993 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
2994
2995 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002996 SMLoc SIdx = getLoc();
2997 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002998 const MCExpr *ImmVal;
2999 if (getParser().parseExpression(ImmVal))
3000 return false;
3001 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3002 if (!MCE) {
3003 TokError("immediate value expected for vector index");
3004 return false;
3005 }
3006
3007 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003008 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003009 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003010
3011 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
3012 E, getContext()));
3013 }
3014 return false;
3015}
3016
Alex Bradbury58eba092016-11-01 16:32:05 +00003017OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003018AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003019 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003020 const AsmToken &Tok = Parser.getTok();
3021 if (!Tok.is(AsmToken::Identifier))
3022 return MatchOperand_NoMatch;
3023
Florian Hahnc4422242017-11-07 13:07:50 +00003024 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00003025
3026 MCContext &Ctx = getContext();
3027 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
3028 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
3029 return MatchOperand_NoMatch;
3030
3031 SMLoc S = getLoc();
3032 Parser.Lex(); // Eat register
3033
Nirav Davee833c6c2016-11-08 18:31:04 +00003034 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003035 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003036 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003037 return MatchOperand_Success;
3038 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003039
Nirav Davee833c6c2016-11-08 18:31:04 +00003040 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003041
3042 if (Parser.getTok().isNot(AsmToken::Integer)) {
3043 Error(getLoc(), "index must be absent or #0");
3044 return MatchOperand_ParseFail;
3045 }
3046
3047 const MCExpr *ImmVal;
3048 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3049 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3050 Error(getLoc(), "index must be absent or #0");
3051 return MatchOperand_ParseFail;
3052 }
3053
3054 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003055 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003056 return MatchOperand_Success;
3057}
3058
3059/// parseOperand - Parse a arm instruction operand. For now this parses the
3060/// operand regardless of the mnemonic.
3061bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3062 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003063 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003064
3065 OperandMatchResultTy ResTy =
3066 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3067
Tim Northover3b0846e2014-05-24 12:50:23 +00003068 // Check if the current operand has a custom associated parser, if so, try to
3069 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003070 if (ResTy == MatchOperand_Success)
3071 return false;
3072 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3073 // there was a match, but an error occurred, in which case, just return that
3074 // the operand parsing failed.
3075 if (ResTy == MatchOperand_ParseFail)
3076 return true;
3077
3078 // Nothing custom, so do general case parsing.
3079 SMLoc S, E;
3080 switch (getLexer().getKind()) {
3081 default: {
3082 SMLoc S = getLoc();
3083 const MCExpr *Expr;
3084 if (parseSymbolicImmVal(Expr))
3085 return Error(S, "invalid operand");
3086
3087 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3088 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3089 return false;
3090 }
3091 case AsmToken::LBrac: {
3092 SMLoc Loc = Parser.getTok().getLoc();
3093 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3094 getContext()));
3095 Parser.Lex(); // Eat '['
3096
3097 // There's no comma after a '[', so we can parse the next operand
3098 // immediately.
3099 return parseOperand(Operands, false, false);
3100 }
3101 case AsmToken::LCurly:
3102 return parseVectorList(Operands);
3103 case AsmToken::Identifier: {
3104 // If we're expecting a Condition Code operand, then just parse that.
3105 if (isCondCode)
3106 return parseCondCode(Operands, invertCondCode);
3107
3108 // If it's a register name, parse it.
3109 if (!parseRegister(Operands))
3110 return false;
3111
3112 // This could be an optional "shift" or "extend" operand.
3113 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3114 // We can only continue if no tokens were eaten.
3115 if (GotShift != MatchOperand_NoMatch)
3116 return GotShift;
3117
3118 // This was not a register so parse other operands that start with an
3119 // identifier (like labels) as expressions and create them as immediates.
3120 const MCExpr *IdVal;
3121 S = getLoc();
3122 if (getParser().parseExpression(IdVal))
3123 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003124 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3125 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3126 return false;
3127 }
3128 case AsmToken::Integer:
3129 case AsmToken::Real:
3130 case AsmToken::Hash: {
3131 // #42 -> immediate.
3132 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003133
3134 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003135
3136 // Parse a negative sign
3137 bool isNegative = false;
3138 if (Parser.getTok().is(AsmToken::Minus)) {
3139 isNegative = true;
3140 // We need to consume this token only when we have a Real, otherwise
3141 // we let parseSymbolicImmVal take care of it
3142 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3143 Parser.Lex();
3144 }
3145
3146 // The only Real that should come through here is a literal #0.0 for
3147 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3148 // so convert the value.
3149 const AsmToken &Tok = Parser.getTok();
3150 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003151 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003152 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3153 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3154 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3155 Mnemonic != "fcmlt")
3156 return TokError("unexpected floating point literal");
3157 else if (IntVal != 0 || isNegative)
3158 return TokError("expected floating-point constant #0.0");
3159 Parser.Lex(); // Eat the token.
3160
3161 Operands.push_back(
3162 AArch64Operand::CreateToken("#0", false, S, getContext()));
3163 Operands.push_back(
3164 AArch64Operand::CreateToken(".0", false, S, getContext()));
3165 return false;
3166 }
3167
3168 const MCExpr *ImmVal;
3169 if (parseSymbolicImmVal(ImmVal))
3170 return true;
3171
3172 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3173 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3174 return false;
3175 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003176 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003177 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003178 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003179 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003180 Parser.Lex(); // Eat '='
3181 const MCExpr *SubExprVal;
3182 if (getParser().parseExpression(SubExprVal))
3183 return true;
3184
David Peixottoae5ba762014-07-18 16:05:14 +00003185 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003186 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003187 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003188
3189 bool IsXReg =
3190 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3191 Operands[1]->getReg());
3192
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003193 MCContext& Ctx = getContext();
3194 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3195 // 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 +00003196 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003197 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3198 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3199 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3200 ShiftAmt += 16;
3201 Imm >>= 16;
3202 }
3203 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3204 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3205 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003206 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003207 if (ShiftAmt)
3208 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3209 ShiftAmt, true, S, E, Ctx));
3210 return false;
3211 }
David Peixottoae5ba762014-07-18 16:05:14 +00003212 APInt Simm = APInt(64, Imm << ShiftAmt);
3213 // check if the immediate is an unsigned or signed 32-bit int for W regs
3214 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3215 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003216 }
3217 // 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 +00003218 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003219 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003220 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3221 return false;
3222 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003223 }
3224}
3225
3226/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3227/// operands.
3228bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3229 StringRef Name, SMLoc NameLoc,
3230 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003231 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003232 Name = StringSwitch<StringRef>(Name.lower())
3233 .Case("beq", "b.eq")
3234 .Case("bne", "b.ne")
3235 .Case("bhs", "b.hs")
3236 .Case("bcs", "b.cs")
3237 .Case("blo", "b.lo")
3238 .Case("bcc", "b.cc")
3239 .Case("bmi", "b.mi")
3240 .Case("bpl", "b.pl")
3241 .Case("bvs", "b.vs")
3242 .Case("bvc", "b.vc")
3243 .Case("bhi", "b.hi")
3244 .Case("bls", "b.ls")
3245 .Case("bge", "b.ge")
3246 .Case("blt", "b.lt")
3247 .Case("bgt", "b.gt")
3248 .Case("ble", "b.le")
3249 .Case("bal", "b.al")
3250 .Case("bnv", "b.nv")
3251 .Default(Name);
3252
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003253 // First check for the AArch64-specific .req directive.
3254 if (Parser.getTok().is(AsmToken::Identifier) &&
3255 Parser.getTok().getIdentifier() == ".req") {
3256 parseDirectiveReq(Name, NameLoc);
3257 // We always return 'error' for this, as we're done with this
3258 // statement and don't need to match the 'instruction."
3259 return true;
3260 }
3261
Tim Northover3b0846e2014-05-24 12:50:23 +00003262 // Create the leading tokens for the mnemonic, split by '.' characters.
3263 size_t Start = 0, Next = Name.find('.');
3264 StringRef Head = Name.slice(Start, Next);
3265
3266 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003267 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3268 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003269
3270 Operands.push_back(
3271 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3272 Mnemonic = Head;
3273
3274 // Handle condition codes for a branch mnemonic
3275 if (Head == "b" && Next != StringRef::npos) {
3276 Start = Next;
3277 Next = Name.find('.', Start + 1);
3278 Head = Name.slice(Start + 1, Next);
3279
3280 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3281 (Head.data() - Name.data()));
3282 AArch64CC::CondCode CC = parseCondCodeString(Head);
3283 if (CC == AArch64CC::Invalid)
3284 return Error(SuffixLoc, "invalid condition code");
3285 Operands.push_back(
3286 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3287 Operands.push_back(
3288 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3289 }
3290
3291 // Add the remaining tokens in the mnemonic.
3292 while (Next != StringRef::npos) {
3293 Start = Next;
3294 Next = Name.find('.', Start + 1);
3295 Head = Name.slice(Start, Next);
3296 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3297 (Head.data() - Name.data()) + 1);
3298 Operands.push_back(
3299 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3300 }
3301
3302 // Conditional compare instructions have a Condition Code operand, which needs
3303 // to be parsed and an immediate operand created.
3304 bool condCodeFourthOperand =
3305 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3306 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3307 Head == "csinc" || Head == "csinv" || Head == "csneg");
3308
3309 // These instructions are aliases to some of the conditional select
3310 // instructions. However, the condition code is inverted in the aliased
3311 // instruction.
3312 //
3313 // FIXME: Is this the correct way to handle these? Or should the parser
3314 // generate the aliased instructions directly?
3315 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3316 bool condCodeThirdOperand =
3317 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3318
3319 // Read the remaining operands.
3320 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3321 // Read the first operand.
3322 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003323 return true;
3324 }
3325
3326 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003327 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003328 // Parse and remember the operand.
3329 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3330 (N == 3 && condCodeThirdOperand) ||
3331 (N == 2 && condCodeSecondOperand),
3332 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003333 return true;
3334 }
3335
3336 // After successfully parsing some operands there are two special cases to
3337 // consider (i.e. notional operands not separated by commas). Both are due
3338 // to memory specifiers:
3339 // + An RBrac will end an address for load/store/prefetch
3340 // + An '!' will indicate a pre-indexed operation.
3341 //
3342 // It's someone else's responsibility to make sure these tokens are sane
3343 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003344
Nirav Davee833c6c2016-11-08 18:31:04 +00003345 SMLoc RLoc = Parser.getTok().getLoc();
3346 if (parseOptionalToken(AsmToken::RBrac))
3347 Operands.push_back(
3348 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3349 SMLoc ELoc = Parser.getTok().getLoc();
3350 if (parseOptionalToken(AsmToken::Exclaim))
3351 Operands.push_back(
3352 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003353
3354 ++N;
3355 }
3356 }
3357
Nirav Davee833c6c2016-11-08 18:31:04 +00003358 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3359 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003360
Tim Northover3b0846e2014-05-24 12:50:23 +00003361 return false;
3362}
3363
3364// FIXME: This entire function is a giant hack to provide us with decent
3365// operand range validation/diagnostics until TableGen/MC can be extended
3366// to support autogeneration of this kind of validation.
3367bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3368 SmallVectorImpl<SMLoc> &Loc) {
3369 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3370 // Check for indexed addressing modes w/ the base register being the
3371 // same as a destination/source register or pair load where
3372 // the Rt == Rt2. All of those are undefined behaviour.
3373 switch (Inst.getOpcode()) {
3374 case AArch64::LDPSWpre:
3375 case AArch64::LDPWpost:
3376 case AArch64::LDPWpre:
3377 case AArch64::LDPXpost:
3378 case AArch64::LDPXpre: {
3379 unsigned Rt = Inst.getOperand(1).getReg();
3380 unsigned Rt2 = Inst.getOperand(2).getReg();
3381 unsigned Rn = Inst.getOperand(3).getReg();
3382 if (RI->isSubRegisterEq(Rn, Rt))
3383 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3384 "is also a destination");
3385 if (RI->isSubRegisterEq(Rn, Rt2))
3386 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3387 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003388 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003389 }
3390 case AArch64::LDPDi:
3391 case AArch64::LDPQi:
3392 case AArch64::LDPSi:
3393 case AArch64::LDPSWi:
3394 case AArch64::LDPWi:
3395 case AArch64::LDPXi: {
3396 unsigned Rt = Inst.getOperand(0).getReg();
3397 unsigned Rt2 = Inst.getOperand(1).getReg();
3398 if (Rt == Rt2)
3399 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3400 break;
3401 }
3402 case AArch64::LDPDpost:
3403 case AArch64::LDPDpre:
3404 case AArch64::LDPQpost:
3405 case AArch64::LDPQpre:
3406 case AArch64::LDPSpost:
3407 case AArch64::LDPSpre:
3408 case AArch64::LDPSWpost: {
3409 unsigned Rt = Inst.getOperand(1).getReg();
3410 unsigned Rt2 = Inst.getOperand(2).getReg();
3411 if (Rt == Rt2)
3412 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3413 break;
3414 }
3415 case AArch64::STPDpost:
3416 case AArch64::STPDpre:
3417 case AArch64::STPQpost:
3418 case AArch64::STPQpre:
3419 case AArch64::STPSpost:
3420 case AArch64::STPSpre:
3421 case AArch64::STPWpost:
3422 case AArch64::STPWpre:
3423 case AArch64::STPXpost:
3424 case AArch64::STPXpre: {
3425 unsigned Rt = Inst.getOperand(1).getReg();
3426 unsigned Rt2 = Inst.getOperand(2).getReg();
3427 unsigned Rn = Inst.getOperand(3).getReg();
3428 if (RI->isSubRegisterEq(Rn, Rt))
3429 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3430 "is also a source");
3431 if (RI->isSubRegisterEq(Rn, Rt2))
3432 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3433 "is also a source");
3434 break;
3435 }
3436 case AArch64::LDRBBpre:
3437 case AArch64::LDRBpre:
3438 case AArch64::LDRHHpre:
3439 case AArch64::LDRHpre:
3440 case AArch64::LDRSBWpre:
3441 case AArch64::LDRSBXpre:
3442 case AArch64::LDRSHWpre:
3443 case AArch64::LDRSHXpre:
3444 case AArch64::LDRSWpre:
3445 case AArch64::LDRWpre:
3446 case AArch64::LDRXpre:
3447 case AArch64::LDRBBpost:
3448 case AArch64::LDRBpost:
3449 case AArch64::LDRHHpost:
3450 case AArch64::LDRHpost:
3451 case AArch64::LDRSBWpost:
3452 case AArch64::LDRSBXpost:
3453 case AArch64::LDRSHWpost:
3454 case AArch64::LDRSHXpost:
3455 case AArch64::LDRSWpost:
3456 case AArch64::LDRWpost:
3457 case AArch64::LDRXpost: {
3458 unsigned Rt = Inst.getOperand(1).getReg();
3459 unsigned Rn = Inst.getOperand(2).getReg();
3460 if (RI->isSubRegisterEq(Rn, Rt))
3461 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3462 "is also a source");
3463 break;
3464 }
3465 case AArch64::STRBBpost:
3466 case AArch64::STRBpost:
3467 case AArch64::STRHHpost:
3468 case AArch64::STRHpost:
3469 case AArch64::STRWpost:
3470 case AArch64::STRXpost:
3471 case AArch64::STRBBpre:
3472 case AArch64::STRBpre:
3473 case AArch64::STRHHpre:
3474 case AArch64::STRHpre:
3475 case AArch64::STRWpre:
3476 case AArch64::STRXpre: {
3477 unsigned Rt = Inst.getOperand(1).getReg();
3478 unsigned Rn = Inst.getOperand(2).getReg();
3479 if (RI->isSubRegisterEq(Rn, Rt))
3480 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3481 "is also a source");
3482 break;
3483 }
3484 }
3485
3486 // Now check immediate ranges. Separate from the above as there is overlap
3487 // in the instructions being checked and this keeps the nested conditionals
3488 // to a minimum.
3489 switch (Inst.getOpcode()) {
3490 case AArch64::ADDSWri:
3491 case AArch64::ADDSXri:
3492 case AArch64::ADDWri:
3493 case AArch64::ADDXri:
3494 case AArch64::SUBSWri:
3495 case AArch64::SUBSXri:
3496 case AArch64::SUBWri:
3497 case AArch64::SUBXri: {
3498 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3499 // some slight duplication here.
3500 if (Inst.getOperand(2).isExpr()) {
3501 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3502 AArch64MCExpr::VariantKind ELFRefKind;
3503 MCSymbolRefExpr::VariantKind DarwinRefKind;
3504 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003505 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3506
3507 // Only allow these with ADDXri.
3508 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3509 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3510 Inst.getOpcode() == AArch64::ADDXri)
3511 return false;
3512
3513 // Only allow these with ADDXri/ADDWri
3514 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3515 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3516 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3517 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3518 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3519 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3520 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3521 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3522 (Inst.getOpcode() == AArch64::ADDXri ||
3523 Inst.getOpcode() == AArch64::ADDWri))
3524 return false;
3525
3526 // Don't allow symbol refs in the immediate field otherwise
3527 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3528 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3529 // 'cmp w0, 'borked')
3530 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003531 }
Diana Picusc93518d2016-10-11 09:17:47 +00003532 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003533 }
3534 return false;
3535 }
3536 default:
3537 return false;
3538 }
3539}
3540
Craig Topper05515562017-10-26 06:46:41 +00003541static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3542 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003543
3544bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3545 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003546 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003547 case Match_InvalidTiedOperand:
3548 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003549 case Match_MissingFeature:
3550 return Error(Loc,
3551 "instruction requires a CPU feature not currently enabled");
3552 case Match_InvalidOperand:
3553 return Error(Loc, "invalid operand for instruction");
3554 case Match_InvalidSuffix:
3555 return Error(Loc, "invalid type suffix for instruction");
3556 case Match_InvalidCondCode:
3557 return Error(Loc, "expected AArch64 condition code");
3558 case Match_AddSubRegExtendSmall:
3559 return Error(Loc,
3560 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3561 case Match_AddSubRegExtendLarge:
3562 return Error(Loc,
3563 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3564 case Match_AddSubSecondSource:
3565 return Error(Loc,
3566 "expected compatible register, symbol or integer in range [0, 4095]");
3567 case Match_LogicalSecondSource:
3568 return Error(Loc, "expected compatible register or logical immediate");
3569 case Match_InvalidMovImm32Shift:
3570 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3571 case Match_InvalidMovImm64Shift:
3572 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3573 case Match_AddSubRegShift32:
3574 return Error(Loc,
3575 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3576 case Match_AddSubRegShift64:
3577 return Error(Loc,
3578 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3579 case Match_InvalidFPImm:
3580 return Error(Loc,
3581 "expected compatible register or floating-point constant");
3582 case Match_InvalidMemoryIndexedSImm9:
3583 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003584 case Match_InvalidMemoryIndexedSImm10:
3585 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003586 case Match_InvalidMemoryIndexed4SImm7:
3587 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3588 case Match_InvalidMemoryIndexed8SImm7:
3589 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3590 case Match_InvalidMemoryIndexed16SImm7:
3591 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3592 case Match_InvalidMemoryWExtend8:
3593 return Error(Loc,
3594 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3595 case Match_InvalidMemoryWExtend16:
3596 return Error(Loc,
3597 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3598 case Match_InvalidMemoryWExtend32:
3599 return Error(Loc,
3600 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3601 case Match_InvalidMemoryWExtend64:
3602 return Error(Loc,
3603 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3604 case Match_InvalidMemoryWExtend128:
3605 return Error(Loc,
3606 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3607 case Match_InvalidMemoryXExtend8:
3608 return Error(Loc,
3609 "expected 'lsl' or 'sxtx' with optional shift of #0");
3610 case Match_InvalidMemoryXExtend16:
3611 return Error(Loc,
3612 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3613 case Match_InvalidMemoryXExtend32:
3614 return Error(Loc,
3615 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3616 case Match_InvalidMemoryXExtend64:
3617 return Error(Loc,
3618 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3619 case Match_InvalidMemoryXExtend128:
3620 return Error(Loc,
3621 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3622 case Match_InvalidMemoryIndexed1:
3623 return Error(Loc, "index must be an integer in range [0, 4095].");
3624 case Match_InvalidMemoryIndexed2:
3625 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3626 case Match_InvalidMemoryIndexed4:
3627 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3628 case Match_InvalidMemoryIndexed8:
3629 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3630 case Match_InvalidMemoryIndexed16:
3631 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003632 case Match_InvalidImm0_1:
3633 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003634 case Match_InvalidImm0_7:
3635 return Error(Loc, "immediate must be an integer in range [0, 7].");
3636 case Match_InvalidImm0_15:
3637 return Error(Loc, "immediate must be an integer in range [0, 15].");
3638 case Match_InvalidImm0_31:
3639 return Error(Loc, "immediate must be an integer in range [0, 31].");
3640 case Match_InvalidImm0_63:
3641 return Error(Loc, "immediate must be an integer in range [0, 63].");
3642 case Match_InvalidImm0_127:
3643 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003644 case Match_InvalidImm0_255:
3645 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003646 case Match_InvalidImm0_65535:
3647 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3648 case Match_InvalidImm1_8:
3649 return Error(Loc, "immediate must be an integer in range [1, 8].");
3650 case Match_InvalidImm1_16:
3651 return Error(Loc, "immediate must be an integer in range [1, 16].");
3652 case Match_InvalidImm1_32:
3653 return Error(Loc, "immediate must be an integer in range [1, 32].");
3654 case Match_InvalidImm1_64:
3655 return Error(Loc, "immediate must be an integer in range [1, 64].");
3656 case Match_InvalidIndex1:
3657 return Error(Loc, "expected lane specifier '[1]'");
3658 case Match_InvalidIndexB:
3659 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3660 case Match_InvalidIndexH:
3661 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3662 case Match_InvalidIndexS:
3663 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3664 case Match_InvalidIndexD:
3665 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3666 case Match_InvalidLabel:
3667 return Error(Loc, "expected label or encodable integer pc offset");
3668 case Match_MRS:
3669 return Error(Loc, "expected readable system register");
3670 case Match_MSR:
3671 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003672 case Match_InvalidComplexRotationEven:
3673 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3674 case Match_InvalidComplexRotationOdd:
3675 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003676 case Match_MnemonicFail: {
3677 std::string Suggestion = AArch64MnemonicSpellCheck(
3678 ((AArch64Operand &)*Operands[0]).getToken(),
3679 ComputeAvailableFeatures(STI->getFeatureBits()));
3680 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3681 }
Sander de Smalencd6be962017-12-20 11:02:42 +00003682 case Match_InvalidSVEPredicateAnyReg:
3683 case Match_InvalidSVEPredicateBReg:
3684 case Match_InvalidSVEPredicateHReg:
3685 case Match_InvalidSVEPredicateSReg:
3686 case Match_InvalidSVEPredicateDReg:
3687 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003688 case Match_InvalidSVEPredicate3bAnyReg:
3689 case Match_InvalidSVEPredicate3bBReg:
3690 case Match_InvalidSVEPredicate3bHReg:
3691 case Match_InvalidSVEPredicate3bSReg:
3692 case Match_InvalidSVEPredicate3bDReg:
3693 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003694 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003695 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003696 }
3697}
3698
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003699static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003700
3701bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3702 OperandVector &Operands,
3703 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003704 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003705 bool MatchingInlineAsm) {
3706 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003707 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3708 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003709
David Blaikie960ea3f2014-06-08 16:18:35 +00003710 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003711 unsigned NumOperands = Operands.size();
3712
3713 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003714 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3715 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003716 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003717 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003718 if (Op3CE) {
3719 uint64_t Op3Val = Op3CE->getValue();
3720 uint64_t NewOp3Val = 0;
3721 uint64_t NewOp4Val = 0;
3722 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003723 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003724 NewOp3Val = (32 - Op3Val) & 0x1f;
3725 NewOp4Val = 31 - Op3Val;
3726 } else {
3727 NewOp3Val = (64 - Op3Val) & 0x3f;
3728 NewOp4Val = 63 - Op3Val;
3729 }
3730
Jim Grosbach13760bd2015-05-30 01:25:56 +00003731 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3732 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003733
3734 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003735 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003736 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003737 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3738 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3739 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003740 }
3741 }
Tim Northover03b99f62015-04-30 18:28:58 +00003742 } else if (NumOperands == 4 && Tok == "bfc") {
3743 // FIXME: Horrible hack to handle BFC->BFM alias.
3744 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3745 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3746 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3747
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003748 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003749 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3750 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3751
3752 if (LSBCE && WidthCE) {
3753 uint64_t LSB = LSBCE->getValue();
3754 uint64_t Width = WidthCE->getValue();
3755
3756 uint64_t RegWidth = 0;
3757 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3758 Op1.getReg()))
3759 RegWidth = 64;
3760 else
3761 RegWidth = 32;
3762
3763 if (LSB >= RegWidth)
3764 return Error(LSBOp.getStartLoc(),
3765 "expected integer in range [0, 31]");
3766 if (Width < 1 || Width > RegWidth)
3767 return Error(WidthOp.getStartLoc(),
3768 "expected integer in range [1, 32]");
3769
3770 uint64_t ImmR = 0;
3771 if (RegWidth == 32)
3772 ImmR = (32 - LSB) & 0x1f;
3773 else
3774 ImmR = (64 - LSB) & 0x3f;
3775
3776 uint64_t ImmS = Width - 1;
3777
3778 if (ImmR != 0 && ImmS >= ImmR)
3779 return Error(WidthOp.getStartLoc(),
3780 "requested insert overflows register");
3781
Jim Grosbach13760bd2015-05-30 01:25:56 +00003782 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3783 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003784 Operands[0] = AArch64Operand::CreateToken(
3785 "bfm", false, Op.getStartLoc(), getContext());
3786 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003787 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3788 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003789 Operands[3] = AArch64Operand::CreateImm(
3790 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3791 Operands.emplace_back(
3792 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3793 WidthOp.getEndLoc(), getContext()));
3794 }
3795 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003796 } else if (NumOperands == 5) {
3797 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3798 // UBFIZ -> UBFM aliases.
3799 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003800 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3801 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3802 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003803
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003804 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003805 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3806 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003807
3808 if (Op3CE && Op4CE) {
3809 uint64_t Op3Val = Op3CE->getValue();
3810 uint64_t Op4Val = Op4CE->getValue();
3811
3812 uint64_t RegWidth = 0;
3813 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003814 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003815 RegWidth = 64;
3816 else
3817 RegWidth = 32;
3818
3819 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003820 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003821 "expected integer in range [0, 31]");
3822 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003823 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003824 "expected integer in range [1, 32]");
3825
3826 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003827 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003828 NewOp3Val = (32 - Op3Val) & 0x1f;
3829 else
3830 NewOp3Val = (64 - Op3Val) & 0x3f;
3831
3832 uint64_t NewOp4Val = Op4Val - 1;
3833
3834 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003835 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003836 "requested insert overflows register");
3837
3838 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003839 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003840 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003841 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003842 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003843 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003844 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003845 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003846 if (Tok == "bfi")
3847 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003848 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003849 else if (Tok == "sbfiz")
3850 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003851 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003852 else if (Tok == "ubfiz")
3853 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003854 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003855 else
3856 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003857 }
3858 }
3859
3860 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3861 // UBFX -> UBFM aliases.
3862 } else if (NumOperands == 5 &&
3863 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003864 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3865 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3866 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003867
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003868 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003869 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3870 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003871
3872 if (Op3CE && Op4CE) {
3873 uint64_t Op3Val = Op3CE->getValue();
3874 uint64_t Op4Val = Op4CE->getValue();
3875
3876 uint64_t RegWidth = 0;
3877 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003878 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003879 RegWidth = 64;
3880 else
3881 RegWidth = 32;
3882
3883 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003884 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003885 "expected integer in range [0, 31]");
3886 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003887 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003888 "expected integer in range [1, 32]");
3889
3890 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3891
3892 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003893 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003894 "requested extract overflows register");
3895
3896 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003897 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003898 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003899 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003900 if (Tok == "bfxil")
3901 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003902 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003903 else if (Tok == "sbfx")
3904 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003905 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003906 else if (Tok == "ubfx")
3907 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003908 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003909 else
3910 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003911 }
3912 }
3913 }
3914 }
Tim Northover9097a072017-12-18 10:36:00 +00003915
3916 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
3917 // instruction for FP registers correctly in some rare circumstances. Convert
3918 // it to a safe instruction and warn (because silently changing someone's
3919 // assembly is rude).
3920 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
3921 NumOperands == 4 && Tok == "movi") {
3922 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3923 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3924 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3925 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
3926 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
3927 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
3928 if (Suffix.lower() == ".2d" &&
3929 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
3930 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
3931 " correctly on this CPU, converting to equivalent movi.16b");
3932 // Switch the suffix to .16b.
3933 unsigned Idx = Op1.isToken() ? 1 : 2;
3934 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
3935 getContext());
3936 }
3937 }
3938 }
3939
Tim Northover3b0846e2014-05-24 12:50:23 +00003940 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3941 // InstAlias can't quite handle this since the reg classes aren't
3942 // subclasses.
3943 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3944 // The source register can be Wn here, but the matcher expects a
3945 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003946 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003947 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003948 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003949 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3950 Op.getStartLoc(), Op.getEndLoc(),
3951 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003952 }
3953 }
3954 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3955 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003956 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003957 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003958 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003959 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003960 // The source register can be Wn here, but the matcher expects a
3961 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003962 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003963 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003964 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003965 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3966 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003967 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003968 }
3969 }
3970 }
3971 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3972 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003973 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003974 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003975 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003976 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003977 // The source register can be Wn here, but the matcher expects a
3978 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003979 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003980 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003981 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003982 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3983 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003984 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003985 }
3986 }
3987 }
3988
Tim Northover3b0846e2014-05-24 12:50:23 +00003989 MCInst Inst;
3990 // First try to match against the secondary set of tables containing the
3991 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3992 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003993 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003994
3995 // If that fails, try against the alternate table containing long-form NEON:
3996 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003997 if (MatchResult != Match_Success) {
3998 // But first, save the short-form match result: we can use it in case the
3999 // long-form match also fails.
4000 auto ShortFormNEONErrorInfo = ErrorInfo;
4001 auto ShortFormNEONMatchResult = MatchResult;
4002
Tim Northover3b0846e2014-05-24 12:50:23 +00004003 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004004 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004005
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004006 // Now, both matches failed, and the long-form match failed on the mnemonic
4007 // suffix token operand. The short-form match failure is probably more
4008 // relevant: use it instead.
4009 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004010 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004011 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4012 MatchResult = ShortFormNEONMatchResult;
4013 ErrorInfo = ShortFormNEONErrorInfo;
4014 }
4015 }
4016
Tim Northover3b0846e2014-05-24 12:50:23 +00004017 switch (MatchResult) {
4018 case Match_Success: {
4019 // Perform range checking and other semantic validations
4020 SmallVector<SMLoc, 8> OperandLocs;
4021 NumOperands = Operands.size();
4022 for (unsigned i = 1; i < NumOperands; ++i)
4023 OperandLocs.push_back(Operands[i]->getStartLoc());
4024 if (validateInstruction(Inst, OperandLocs))
4025 return true;
4026
4027 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004028 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004029 return false;
4030 }
4031 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004032 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004033 // Special case the error message for the very common case where only
4034 // a single subtarget feature is missing (neon, e.g.).
4035 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004036 uint64_t Mask = 1;
4037 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4038 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004039 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004040 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004041 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004042 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004043 }
4044 return Error(IDLoc, Msg);
4045 }
4046 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004047 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004048 case Match_InvalidOperand: {
4049 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004050
Tim Northover26bb14e2014-08-18 11:49:42 +00004051 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004052 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004053 return Error(IDLoc, "too few operands for instruction",
4054 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004055
David Blaikie960ea3f2014-06-08 16:18:35 +00004056 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004057 if (ErrorLoc == SMLoc())
4058 ErrorLoc = IDLoc;
4059 }
4060 // If the match failed on a suffix token operand, tweak the diagnostic
4061 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004062 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4063 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004064 MatchResult = Match_InvalidSuffix;
4065
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004066 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004067 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004068 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004069 case Match_InvalidMemoryIndexed1:
4070 case Match_InvalidMemoryIndexed2:
4071 case Match_InvalidMemoryIndexed4:
4072 case Match_InvalidMemoryIndexed8:
4073 case Match_InvalidMemoryIndexed16:
4074 case Match_InvalidCondCode:
4075 case Match_AddSubRegExtendSmall:
4076 case Match_AddSubRegExtendLarge:
4077 case Match_AddSubSecondSource:
4078 case Match_LogicalSecondSource:
4079 case Match_AddSubRegShift32:
4080 case Match_AddSubRegShift64:
4081 case Match_InvalidMovImm32Shift:
4082 case Match_InvalidMovImm64Shift:
4083 case Match_InvalidFPImm:
4084 case Match_InvalidMemoryWExtend8:
4085 case Match_InvalidMemoryWExtend16:
4086 case Match_InvalidMemoryWExtend32:
4087 case Match_InvalidMemoryWExtend64:
4088 case Match_InvalidMemoryWExtend128:
4089 case Match_InvalidMemoryXExtend8:
4090 case Match_InvalidMemoryXExtend16:
4091 case Match_InvalidMemoryXExtend32:
4092 case Match_InvalidMemoryXExtend64:
4093 case Match_InvalidMemoryXExtend128:
4094 case Match_InvalidMemoryIndexed4SImm7:
4095 case Match_InvalidMemoryIndexed8SImm7:
4096 case Match_InvalidMemoryIndexed16SImm7:
4097 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004098 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004099 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004100 case Match_InvalidImm0_7:
4101 case Match_InvalidImm0_15:
4102 case Match_InvalidImm0_31:
4103 case Match_InvalidImm0_63:
4104 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004105 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004106 case Match_InvalidImm0_65535:
4107 case Match_InvalidImm1_8:
4108 case Match_InvalidImm1_16:
4109 case Match_InvalidImm1_32:
4110 case Match_InvalidImm1_64:
4111 case Match_InvalidIndex1:
4112 case Match_InvalidIndexB:
4113 case Match_InvalidIndexH:
4114 case Match_InvalidIndexS:
4115 case Match_InvalidIndexD:
4116 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004117 case Match_InvalidComplexRotationEven:
4118 case Match_InvalidComplexRotationOdd:
Sander de Smalencd6be962017-12-20 11:02:42 +00004119 case Match_InvalidSVEPredicateAnyReg:
4120 case Match_InvalidSVEPredicateBReg:
4121 case Match_InvalidSVEPredicateHReg:
4122 case Match_InvalidSVEPredicateSReg:
4123 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004124 case Match_InvalidSVEPredicate3bAnyReg:
4125 case Match_InvalidSVEPredicate3bBReg:
4126 case Match_InvalidSVEPredicate3bHReg:
4127 case Match_InvalidSVEPredicate3bSReg:
4128 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004129 case Match_MSR:
4130 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004131 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004132 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004133 // Any time we get here, there's nothing fancy to do. Just get the
4134 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004135 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004136 if (ErrorLoc == SMLoc())
4137 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004138 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004139 }
4140 }
4141
4142 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004143}
4144
4145/// ParseDirective parses the arm specific directives
4146bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004147 const MCObjectFileInfo::Environment Format =
4148 getContext().getObjectFileInfo()->getObjectFileType();
4149 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4150 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004151
Tim Northover3b0846e2014-05-24 12:50:23 +00004152 StringRef IDVal = DirectiveID.getIdentifier();
4153 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004154 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004155 parseDirectiveArch(Loc);
4156 else if (IDVal == ".cpu")
4157 parseDirectiveCPU(Loc);
4158 else if (IDVal == ".hword")
4159 parseDirectiveWord(2, Loc);
4160 else if (IDVal == ".word")
4161 parseDirectiveWord(4, Loc);
4162 else if (IDVal == ".xword")
4163 parseDirectiveWord(8, Loc);
4164 else if (IDVal == ".tlsdesccall")
4165 parseDirectiveTLSDescCall(Loc);
4166 else if (IDVal == ".ltorg" || IDVal == ".pool")
4167 parseDirectiveLtorg(Loc);
4168 else if (IDVal == ".unreq")
4169 parseDirectiveUnreq(Loc);
4170 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004171 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004172 parseDirectiveInst(Loc);
4173 else
4174 return true;
4175 } else if (IDVal == MCLOHDirectiveName())
4176 parseDirectiveLOH(IDVal, Loc);
4177 else
4178 return true;
4179 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004180}
4181
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004182static const struct {
4183 const char *Name;
4184 const FeatureBitset Features;
4185} ExtensionMap[] = {
4186 { "crc", {AArch64::FeatureCRC} },
4187 { "crypto", {AArch64::FeatureCrypto} },
4188 { "fp", {AArch64::FeatureFPARMv8} },
4189 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004190 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004191 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004192
4193 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004194 { "pan", {} },
4195 { "lor", {} },
4196 { "rdma", {} },
4197 { "profile", {} },
4198};
4199
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004200/// parseDirectiveArch
4201/// ::= .arch token
4202bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4203 SMLoc ArchLoc = getLoc();
4204
4205 StringRef Arch, ExtensionString;
4206 std::tie(Arch, ExtensionString) =
4207 getParser().parseStringToEndOfStatement().trim().split('+');
4208
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004209 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4210 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004211 return Error(ArchLoc, "unknown arch name");
4212
4213 if (parseToken(AsmToken::EndOfStatement))
4214 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004215
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004216 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004217 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004218 AArch64::getArchFeatures(ID, AArch64Features);
4219 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4220 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004221
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004222 MCSubtargetInfo &STI = copySTI();
4223 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4224 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4225
4226 SmallVector<StringRef, 4> RequestedExtensions;
4227 if (!ExtensionString.empty())
4228 ExtensionString.split(RequestedExtensions, '+');
4229
4230 FeatureBitset Features = STI.getFeatureBits();
4231 for (auto Name : RequestedExtensions) {
4232 bool EnableFeature = true;
4233
4234 if (Name.startswith_lower("no")) {
4235 EnableFeature = false;
4236 Name = Name.substr(2);
4237 }
4238
4239 for (const auto &Extension : ExtensionMap) {
4240 if (Extension.Name != Name)
4241 continue;
4242
4243 if (Extension.Features.none())
4244 report_fatal_error("unsupported architectural extension: " + Name);
4245
4246 FeatureBitset ToggleFeatures = EnableFeature
4247 ? (~Features & Extension.Features)
4248 : ( Features & Extension.Features);
4249 uint64_t Features =
4250 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4251 setAvailableFeatures(Features);
4252 break;
4253 }
4254 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004255 return false;
4256}
4257
Tim Northover8b96c7e2017-05-15 19:42:15 +00004258static SMLoc incrementLoc(SMLoc L, int Offset) {
4259 return SMLoc::getFromPointer(L.getPointer() + Offset);
4260}
4261
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004262/// parseDirectiveCPU
4263/// ::= .cpu id
4264bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004265 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004266
4267 StringRef CPU, ExtensionString;
4268 std::tie(CPU, ExtensionString) =
4269 getParser().parseStringToEndOfStatement().trim().split('+');
4270
Nirav Davee833c6c2016-11-08 18:31:04 +00004271 if (parseToken(AsmToken::EndOfStatement))
4272 return true;
4273
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004274 SmallVector<StringRef, 4> RequestedExtensions;
4275 if (!ExtensionString.empty())
4276 ExtensionString.split(RequestedExtensions, '+');
4277
4278 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4279 // once that is tablegen'ed
4280 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004281 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004282 return false;
4283 }
4284
4285 MCSubtargetInfo &STI = copySTI();
4286 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004287 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004288
4289 FeatureBitset Features = STI.getFeatureBits();
4290 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004291 // Advance source location past '+'.
4292 CurLoc = incrementLoc(CurLoc, 1);
4293
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004294 bool EnableFeature = true;
4295
4296 if (Name.startswith_lower("no")) {
4297 EnableFeature = false;
4298 Name = Name.substr(2);
4299 }
4300
Tim Northover8b96c7e2017-05-15 19:42:15 +00004301 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004302 for (const auto &Extension : ExtensionMap) {
4303 if (Extension.Name != Name)
4304 continue;
4305
4306 if (Extension.Features.none())
4307 report_fatal_error("unsupported architectural extension: " + Name);
4308
4309 FeatureBitset ToggleFeatures = EnableFeature
4310 ? (~Features & Extension.Features)
4311 : ( Features & Extension.Features);
4312 uint64_t Features =
4313 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4314 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004315 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004316
4317 break;
4318 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004319
4320 if (!FoundExtension)
4321 Error(CurLoc, "unsupported architectural extension");
4322
4323 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004324 }
4325 return false;
4326}
4327
Tim Northover3b0846e2014-05-24 12:50:23 +00004328/// parseDirectiveWord
4329/// ::= .word [ expression (, expression)* ]
4330bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004331 auto parseOp = [&]() -> bool {
4332 const MCExpr *Value;
4333 if (getParser().parseExpression(Value))
4334 return true;
4335 getParser().getStreamer().EmitValue(Value, Size, L);
4336 return false;
4337 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004338
Nirav Davee833c6c2016-11-08 18:31:04 +00004339 if (parseMany(parseOp))
4340 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004341 return false;
4342}
4343
Chad Rosierdcd2a302014-10-22 20:35:57 +00004344/// parseDirectiveInst
4345/// ::= .inst opcode [, ...]
4346bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004347 if (getLexer().is(AsmToken::EndOfStatement))
4348 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004349
Nirav Davee833c6c2016-11-08 18:31:04 +00004350 auto parseOp = [&]() -> bool {
4351 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004352 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004353 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4354 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004355 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004356 if (check(!Value, L, "expected constant expression"))
4357 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004358 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004359 return false;
4360 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004361
Nirav Davee833c6c2016-11-08 18:31:04 +00004362 if (parseMany(parseOp))
4363 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004364 return false;
4365}
4366
Tim Northover3b0846e2014-05-24 12:50:23 +00004367// parseDirectiveTLSDescCall:
4368// ::= .tlsdesccall symbol
4369bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4370 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004371 if (check(getParser().parseIdentifier(Name), L,
4372 "expected symbol after directive") ||
4373 parseToken(AsmToken::EndOfStatement))
4374 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004375
Jim Grosbach6f482002015-05-18 18:43:14 +00004376 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004377 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4378 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004379
4380 MCInst Inst;
4381 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004382 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004383
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004384 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004385 return false;
4386}
4387
4388/// ::= .loh <lohName | lohId> label1, ..., labelN
4389/// The number of arguments depends on the loh identifier.
4390bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004391 MCLOHType Kind;
4392 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4393 if (getParser().getTok().isNot(AsmToken::Integer))
4394 return TokError("expected an identifier or a number in directive");
4395 // We successfully get a numeric value for the identifier.
4396 // Check if it is valid.
4397 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004398 if (Id <= -1U && !isValidMCLOHType(Id))
4399 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004400 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004401 } else {
4402 StringRef Name = getTok().getIdentifier();
4403 // We successfully parse an identifier.
4404 // Check if it is a recognized one.
4405 int Id = MCLOHNameToId(Name);
4406
4407 if (Id == -1)
4408 return TokError("invalid identifier in directive");
4409 Kind = (MCLOHType)Id;
4410 }
4411 // Consume the identifier.
4412 Lex();
4413 // Get the number of arguments of this LOH.
4414 int NbArgs = MCLOHIdToNbArgs(Kind);
4415
4416 assert(NbArgs != -1 && "Invalid number of arguments");
4417
4418 SmallVector<MCSymbol *, 3> Args;
4419 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4420 StringRef Name;
4421 if (getParser().parseIdentifier(Name))
4422 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004423 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004424
4425 if (Idx + 1 == NbArgs)
4426 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004427 if (parseToken(AsmToken::Comma,
4428 "unexpected token in '" + Twine(IDVal) + "' directive"))
4429 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004430 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004431 if (parseToken(AsmToken::EndOfStatement,
4432 "unexpected token in '" + Twine(IDVal) + "' directive"))
4433 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004434
4435 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4436 return false;
4437}
4438
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004439/// parseDirectiveLtorg
4440/// ::= .ltorg | .pool
4441bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004442 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4443 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004444 getTargetStreamer().emitCurrentConstantPool();
4445 return false;
4446}
4447
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004448/// parseDirectiveReq
4449/// ::= name .req registername
4450bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004451 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004452 Parser.Lex(); // Eat the '.req' token.
4453 SMLoc SRegLoc = getLoc();
Sander de Smalen8e607342017-11-15 15:44:43 +00004454 int RegNum = tryParseRegister();
Florian Hahnc4422242017-11-07 13:07:50 +00004455 RegKind RegisterKind = RegKind::Scalar;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004456
Sander de Smalen8e607342017-11-15 15:44:43 +00004457 if (RegNum == -1) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004458 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004459 RegisterKind = RegKind::NeonVector;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004460 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004461 if (!Kind.empty())
4462 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004463 }
4464
Sander de Smalen8e607342017-11-15 15:44:43 +00004465 if (RegNum == -1) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004466 StringRef Kind;
4467 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen8e607342017-11-15 15:44:43 +00004468 OperandMatchResultTy Res =
4469 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4470
4471 if (Res == MatchOperand_ParseFail)
4472 return true;
4473
4474 if (Res == MatchOperand_Success && !Kind.empty())
4475 return Error(SRegLoc,
4476 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004477 }
4478
Sander de Smalencd6be962017-12-20 11:02:42 +00004479 if (RegNum == -1) {
4480 StringRef Kind;
4481 RegisterKind = RegKind::SVEPredicateVector;
4482 OperandMatchResultTy Res =
4483 tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
4484
4485 if (Res == MatchOperand_ParseFail)
4486 return true;
4487
4488 if (Res == MatchOperand_Success && !Kind.empty())
4489 return Error(SRegLoc,
4490 "sve predicate register without type specifier expected");
4491 }
4492
Sander de Smalen8e607342017-11-15 15:44:43 +00004493 if (RegNum == -1)
Nirav Dave2364748a2016-09-16 18:30:20 +00004494 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004495
4496 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004497 if (parseToken(AsmToken::EndOfStatement,
4498 "unexpected input in .req directive"))
4499 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004500
Sander de Smalen8e607342017-11-15 15:44:43 +00004501 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004502 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004503 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4504
Nirav Dave2364748a2016-09-16 18:30:20 +00004505 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004506}
4507
4508/// parseDirectiveUneq
4509/// ::= .unreq registername
4510bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004511 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004512 if (getTok().isNot(AsmToken::Identifier))
4513 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004514 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4515 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004516 if (parseToken(AsmToken::EndOfStatement))
4517 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004518 return false;
4519}
4520
Tim Northover3b0846e2014-05-24 12:50:23 +00004521bool
4522AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4523 AArch64MCExpr::VariantKind &ELFRefKind,
4524 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4525 int64_t &Addend) {
4526 ELFRefKind = AArch64MCExpr::VK_INVALID;
4527 DarwinRefKind = MCSymbolRefExpr::VK_None;
4528 Addend = 0;
4529
4530 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4531 ELFRefKind = AE->getKind();
4532 Expr = AE->getSubExpr();
4533 }
4534
4535 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4536 if (SE) {
4537 // It's a simple symbol reference with no addend.
4538 DarwinRefKind = SE->getKind();
4539 return true;
4540 }
4541
4542 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4543 if (!BE)
4544 return false;
4545
4546 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4547 if (!SE)
4548 return false;
4549 DarwinRefKind = SE->getKind();
4550
4551 if (BE->getOpcode() != MCBinaryExpr::Add &&
4552 BE->getOpcode() != MCBinaryExpr::Sub)
4553 return false;
4554
4555 // See if the addend is is a constant, otherwise there's more going
4556 // on here than we can deal with.
4557 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4558 if (!AddendExpr)
4559 return false;
4560
4561 Addend = AddendExpr->getValue();
4562 if (BE->getOpcode() == MCBinaryExpr::Sub)
4563 Addend = -Addend;
4564
4565 // It's some symbol reference + a constant addend, but really
4566 // shouldn't use both Darwin and ELF syntax.
4567 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4568 DarwinRefKind == MCSymbolRefExpr::VK_None;
4569}
4570
4571/// Force static initialization.
4572extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004573 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4574 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4575 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004576}
4577
4578#define GET_REGISTER_MATCHER
4579#define GET_SUBTARGET_FEATURE_NAME
4580#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004581#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004582#include "AArch64GenAsmMatcher.inc"
4583
4584// Define this matcher function after the auto-generated include so we
4585// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004586unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004587 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004588 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004589 // If the kind is a token for a literal immediate, check if our asm
4590 // operand matches. This is for InstAliases which have a fixed-value
4591 // immediate in the syntax.
4592 int64_t ExpectedVal;
4593 switch (Kind) {
4594 default:
4595 return Match_InvalidOperand;
4596 case MCK__35_0:
4597 ExpectedVal = 0;
4598 break;
4599 case MCK__35_1:
4600 ExpectedVal = 1;
4601 break;
4602 case MCK__35_12:
4603 ExpectedVal = 12;
4604 break;
4605 case MCK__35_16:
4606 ExpectedVal = 16;
4607 break;
4608 case MCK__35_2:
4609 ExpectedVal = 2;
4610 break;
4611 case MCK__35_24:
4612 ExpectedVal = 24;
4613 break;
4614 case MCK__35_3:
4615 ExpectedVal = 3;
4616 break;
4617 case MCK__35_32:
4618 ExpectedVal = 32;
4619 break;
4620 case MCK__35_4:
4621 ExpectedVal = 4;
4622 break;
4623 case MCK__35_48:
4624 ExpectedVal = 48;
4625 break;
4626 case MCK__35_6:
4627 ExpectedVal = 6;
4628 break;
4629 case MCK__35_64:
4630 ExpectedVal = 64;
4631 break;
4632 case MCK__35_8:
4633 ExpectedVal = 8;
4634 break;
4635 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004636 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004637 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004638 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004639 if (!CE)
4640 return Match_InvalidOperand;
4641 if (CE->getValue() == ExpectedVal)
4642 return Match_Success;
4643 return Match_InvalidOperand;
4644}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004645
Alex Bradbury58eba092016-11-01 16:32:05 +00004646OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004647AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4648
4649 SMLoc S = getLoc();
4650
4651 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4652 Error(S, "expected register");
4653 return MatchOperand_ParseFail;
4654 }
4655
4656 int FirstReg = tryParseRegister();
4657 if (FirstReg == -1) {
4658 return MatchOperand_ParseFail;
4659 }
4660 const MCRegisterClass &WRegClass =
4661 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4662 const MCRegisterClass &XRegClass =
4663 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4664
4665 bool isXReg = XRegClass.contains(FirstReg),
4666 isWReg = WRegClass.contains(FirstReg);
4667 if (!isXReg && !isWReg) {
4668 Error(S, "expected first even register of a "
4669 "consecutive same-size even/odd register pair");
4670 return MatchOperand_ParseFail;
4671 }
4672
4673 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4674 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4675
4676 if (FirstEncoding & 0x1) {
4677 Error(S, "expected first even register of a "
4678 "consecutive same-size even/odd register pair");
4679 return MatchOperand_ParseFail;
4680 }
4681
4682 SMLoc M = getLoc();
4683 if (getParser().getTok().isNot(AsmToken::Comma)) {
4684 Error(M, "expected comma");
4685 return MatchOperand_ParseFail;
4686 }
4687 // Eat the comma
4688 getParser().Lex();
4689
4690 SMLoc E = getLoc();
4691 int SecondReg = tryParseRegister();
4692 if (SecondReg ==-1) {
4693 return MatchOperand_ParseFail;
4694 }
4695
Eugene Zelenko049b0172017-01-06 00:30:53 +00004696 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004697 (isXReg && !XRegClass.contains(SecondReg)) ||
4698 (isWReg && !WRegClass.contains(SecondReg))) {
4699 Error(E,"expected second odd register of a "
4700 "consecutive same-size even/odd register pair");
4701 return MatchOperand_ParseFail;
4702 }
Joel Jones504bf332016-10-24 13:37:13 +00004703
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004704 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004705 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004706 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4707 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4708 } else {
4709 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4710 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4711 }
4712
Florian Hahnc4422242017-11-07 13:07:50 +00004713 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4714 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004715
4716 return MatchOperand_Success;
4717}
Florian Hahn91f11e52017-11-07 16:45:48 +00004718
4719template <bool ParseSuffix>
4720OperandMatchResultTy
4721AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004722 const SMLoc S = getLoc();
4723 // Check for a SVE vector register specifier first.
Sander de Smalen8e607342017-11-15 15:44:43 +00004724 int RegNum = -1;
Florian Hahn91f11e52017-11-07 16:45:48 +00004725 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004726
Sander de Smalen8e607342017-11-15 15:44:43 +00004727 OperandMatchResultTy Res =
4728 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4729
4730 if (Res != MatchOperand_Success)
4731 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004732
4733 if (ParseSuffix && Kind.empty())
4734 return MatchOperand_NoMatch;
4735
4736 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
4737 .Case("", -1)
4738 .Case(".b", 8)
4739 .Case(".h", 16)
4740 .Case(".s", 32)
4741 .Case(".d", 64)
4742 .Case(".q", 128)
4743 .Default(0);
4744 if (!ElementWidth)
4745 return MatchOperand_NoMatch;
4746
4747 Operands.push_back(
4748 AArch64Operand::CreateReg(RegNum, RegKind::SVEDataVector, ElementWidth,
4749 S, S, getContext()));
4750
4751 return MatchOperand_Success;
4752}