blob: bcffb33b9d6ec44a60eee0604817085c07c23699 [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; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000473
474 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
475
476 template <int Bits, int Scale> bool isSImmScaled() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000477 if (!isImm())
478 return false;
479 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
480 if (!MCE)
481 return false;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000482
483 int64_t Shift = Bits - 1;
484 int64_t MinVal = (int64_t(1) << Shift) * -Scale;
485 int64_t MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
486
Tim Northover3b0846e2014-05-24 12:50:23 +0000487 int64_t Val = MCE->getValue();
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000488 return Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0;
Tim Northover3b0846e2014-05-24 12:50:23 +0000489 }
490
491 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
492 AArch64MCExpr::VariantKind ELFRefKind;
493 MCSymbolRefExpr::VariantKind DarwinRefKind;
494 int64_t Addend;
495 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
496 Addend)) {
497 // If we don't understand the expression, assume the best and
498 // let the fixup and relocation code deal with it.
499 return true;
500 }
501
502 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
503 ELFRefKind == AArch64MCExpr::VK_LO12 ||
504 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
505 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
506 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
507 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
508 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
509 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
510 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) {
511 // Note that we don't range-check the addend. It's adjusted modulo page
512 // size when converted, so there is no "out of range" condition when using
513 // @pageoff.
514 return Addend >= 0 && (Addend % Scale) == 0;
515 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
516 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
517 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
518 return Addend == 0;
519 }
520
521 return false;
522 }
523
524 template <int Scale> bool isUImm12Offset() const {
525 if (!isImm())
526 return false;
527
528 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
529 if (!MCE)
530 return isSymbolicUImm12Offset(getImm(), Scale);
531
532 int64_t Val = MCE->getValue();
533 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
534 }
535
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000536 template <int N, int M>
537 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000538 if (!isImm())
539 return false;
540 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
541 if (!MCE)
542 return false;
543 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000544 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000545 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000546
Tim Northover3b0846e2014-05-24 12:50:23 +0000547 bool isLogicalImm32() const {
548 if (!isImm())
549 return false;
550 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
551 if (!MCE)
552 return false;
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000553 int64_t Val = MCE->getValue();
554 if (Val >> 32 != 0 && Val >> 32 != ~0LL)
555 return false;
556 Val &= 0xFFFFFFFF;
557 return AArch64_AM::isLogicalImmediate(Val, 32);
Tim Northover3b0846e2014-05-24 12:50:23 +0000558 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000559
Tim Northover3b0846e2014-05-24 12:50:23 +0000560 bool isLogicalImm64() const {
561 if (!isImm())
562 return false;
563 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
564 if (!MCE)
565 return false;
566 return AArch64_AM::isLogicalImmediate(MCE->getValue(), 64);
567 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000568
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000569 bool isLogicalImm32Not() const {
570 if (!isImm())
571 return false;
572 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
573 if (!MCE)
574 return false;
575 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
576 return AArch64_AM::isLogicalImmediate(Val, 32);
577 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000578
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000579 bool isLogicalImm64Not() const {
580 if (!isImm())
581 return false;
582 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
583 if (!MCE)
584 return false;
585 return AArch64_AM::isLogicalImmediate(~MCE->getValue(), 64);
586 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000587
Tim Northover3b0846e2014-05-24 12:50:23 +0000588 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000589
Tim Northover3b0846e2014-05-24 12:50:23 +0000590 bool isAddSubImm() const {
591 if (!isShiftedImm() && !isImm())
592 return false;
593
594 const MCExpr *Expr;
595
596 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
597 if (isShiftedImm()) {
598 unsigned Shift = ShiftedImm.ShiftAmount;
599 Expr = ShiftedImm.Val;
600 if (Shift != 0 && Shift != 12)
601 return false;
602 } else {
603 Expr = getImm();
604 }
605
606 AArch64MCExpr::VariantKind ELFRefKind;
607 MCSymbolRefExpr::VariantKind DarwinRefKind;
608 int64_t Addend;
609 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
610 DarwinRefKind, Addend)) {
611 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
612 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
613 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
614 || ELFRefKind == AArch64MCExpr::VK_LO12
615 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
616 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
617 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
618 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
619 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
620 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
621 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12;
622 }
623
Diana Picusc93518d2016-10-11 09:17:47 +0000624 // If it's a constant, it should be a real immediate in range:
625 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
626 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
627
628 // If it's an expression, we hope for the best and let the fixup/relocation
629 // code deal with it.
630 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000631 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000632
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000633 bool isAddSubImmNeg() const {
634 if (!isShiftedImm() && !isImm())
635 return false;
636
637 const MCExpr *Expr;
638
639 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
640 if (isShiftedImm()) {
641 unsigned Shift = ShiftedImm.ShiftAmount;
642 Expr = ShiftedImm.Val;
643 if (Shift != 0 && Shift != 12)
644 return false;
645 } else
646 Expr = getImm();
647
648 // Otherwise it should be a real negative immediate in range:
649 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
650 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
651 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000652
Tim Northover3b0846e2014-05-24 12:50:23 +0000653 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000654
Tim Northover3b0846e2014-05-24 12:50:23 +0000655 bool isSIMDImmType10() const {
656 if (!isImm())
657 return false;
658 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
659 if (!MCE)
660 return false;
661 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
662 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000663
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000664 template<int N>
665 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000666 if (!isImm())
667 return false;
668 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
669 if (!MCE)
670 return true;
671 int64_t Val = MCE->getValue();
672 if (Val & 0x3)
673 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000674 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
675 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000676 }
677
678 bool
679 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
680 if (!isImm())
681 return false;
682
683 AArch64MCExpr::VariantKind ELFRefKind;
684 MCSymbolRefExpr::VariantKind DarwinRefKind;
685 int64_t Addend;
686 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
687 DarwinRefKind, Addend)) {
688 return false;
689 }
690 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
691 return false;
692
693 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
694 if (ELFRefKind == AllowedModifiers[i])
695 return Addend == 0;
696 }
697
698 return false;
699 }
700
701 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000702 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000703 }
704
705 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000706 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
707 AArch64MCExpr::VK_TPREL_G2,
708 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000709 }
710
711 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000712 return isMovWSymbol({
713 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000714 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
715 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000716 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000717 }
718
719 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000720 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
721 AArch64MCExpr::VK_TPREL_G0,
722 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000723 }
724
725 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000726 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000727 }
728
729 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000730 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000731 }
732
733 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000734 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
735 AArch64MCExpr::VK_TPREL_G1_NC,
736 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000737 }
738
739 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000740 return isMovWSymbol(
741 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
742 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000743 }
744
745 template<int RegWidth, int Shift>
746 bool isMOVZMovAlias() const {
747 if (!isImm()) return false;
748
749 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
750 if (!CE) return false;
751 uint64_t Value = CE->getValue();
752
Tim Northoverdaa1c012016-06-16 01:42:25 +0000753 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000754 }
755
756 template<int RegWidth, int Shift>
757 bool isMOVNMovAlias() const {
758 if (!isImm()) return false;
759
760 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
761 if (!CE) return false;
762 uint64_t Value = CE->getValue();
763
Tim Northoverdaa1c012016-06-16 01:42:25 +0000764 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000765 }
766
767 bool isFPImm() const { return Kind == k_FPImm; }
768 bool isBarrier() const { return Kind == k_Barrier; }
769 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000770
Tim Northover3b0846e2014-05-24 12:50:23 +0000771 bool isMRSSystemRegister() const {
772 if (!isSysReg()) return false;
773
Tim Northover7cd58932015-01-22 17:23:04 +0000774 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000775 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000776
Tim Northover3b0846e2014-05-24 12:50:23 +0000777 bool isMSRSystemRegister() const {
778 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000779 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000780 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000781
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000782 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000783 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000784 return (SysReg.PStateField == AArch64PState::PAN ||
785 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000786 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000787
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000788 bool isSystemPStateFieldWithImm0_15() const {
789 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000790 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000791 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000792
Florian Hahnc4422242017-11-07 13:07:50 +0000793 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000794 return Kind == k_Register;
795 }
796
797 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000798 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
799 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000800
Florian Hahnc4422242017-11-07 13:07:50 +0000801 bool isNeonVectorReg() const {
802 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
803 }
804
805 bool isNeonVectorRegLo() const {
806 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000807 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
808 Reg.RegNum);
809 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000810
Sander de Smalencd6be962017-12-20 11:02:42 +0000811 template <unsigned Class> bool isSVEVectorReg() const {
812 RegKind RK;
813 switch (Class) {
814 case AArch64::ZPRRegClassID:
815 RK = RegKind::SVEDataVector;
816 break;
817 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000818 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000819 RK = RegKind::SVEPredicateVector;
820 break;
821 default:
822 llvm_unreachable("Unsupport register class");
823 }
824
825 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000826 AArch64MCRegisterClasses[Class].contains(getReg());
827 }
828
Sander de Smalencd6be962017-12-20 11:02:42 +0000829 template <int ElementWidth, unsigned Class>
830 bool isSVEVectorRegOfWidth() const {
831 return isSVEVectorReg<Class>() &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000832 (ElementWidth == -1 || Reg.ElementWidth == ElementWidth);
833 }
834
Tim Northover3b0846e2014-05-24 12:50:23 +0000835 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000836 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000837 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
838 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000839
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000840 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000841 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000842 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
843 Reg.RegNum);
844 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000845
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000846 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000847 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000848 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
849 Reg.RegNum);
850 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000851
852 bool isGPR64sp0() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000853 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000854 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
855 }
856
Sam Parker5f934642017-08-31 09:27:04 +0000857 template<int64_t Angle, int64_t Remainder>
858 bool isComplexRotation() const {
859 if (!isImm()) return false;
860
861 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
862 if (!CE) return false;
863 uint64_t Value = CE->getValue();
864
865 return (Value % Angle == Remainder && Value <= 270);
866 }
867
Tim Northover3b0846e2014-05-24 12:50:23 +0000868 /// Is this a vector list with the type implicit (presumably attached to the
869 /// instruction itself)?
870 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
871 return Kind == k_VectorList && VectorList.Count == NumRegs &&
872 !VectorList.ElementKind;
873 }
874
875 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
876 bool isTypedVectorList() const {
877 if (Kind != k_VectorList)
878 return false;
879 if (VectorList.Count != NumRegs)
880 return false;
881 if (VectorList.ElementKind != ElementKind)
882 return false;
883 return VectorList.NumElements == NumElements;
884 }
885
886 bool isVectorIndex1() const {
887 return Kind == k_VectorIndex && VectorIndex.Val == 1;
888 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000889
Tim Northover3b0846e2014-05-24 12:50:23 +0000890 bool isVectorIndexB() const {
891 return Kind == k_VectorIndex && VectorIndex.Val < 16;
892 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000893
Tim Northover3b0846e2014-05-24 12:50:23 +0000894 bool isVectorIndexH() const {
895 return Kind == k_VectorIndex && VectorIndex.Val < 8;
896 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000897
Tim Northover3b0846e2014-05-24 12:50:23 +0000898 bool isVectorIndexS() const {
899 return Kind == k_VectorIndex && VectorIndex.Val < 4;
900 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000901
Tim Northover3b0846e2014-05-24 12:50:23 +0000902 bool isVectorIndexD() const {
903 return Kind == k_VectorIndex && VectorIndex.Val < 2;
904 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000905
Tim Northover3b0846e2014-05-24 12:50:23 +0000906 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000907
Tim Northover3b0846e2014-05-24 12:50:23 +0000908 bool isTokenEqual(StringRef Str) const {
909 return Kind == k_Token && getToken() == Str;
910 }
911 bool isSysCR() const { return Kind == k_SysCR; }
912 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000913 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000914 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
915 bool isShifter() const {
916 if (!isShiftExtend())
917 return false;
918
919 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
920 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
921 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
922 ST == AArch64_AM::MSL);
923 }
924 bool isExtend() const {
925 if (!isShiftExtend())
926 return false;
927
928 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
929 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
930 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
931 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
932 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
933 ET == AArch64_AM::LSL) &&
934 getShiftExtendAmount() <= 4;
935 }
936
937 bool isExtend64() const {
938 if (!isExtend())
939 return false;
940 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
941 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
942 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
943 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000944
Tim Northover3b0846e2014-05-24 12:50:23 +0000945 bool isExtendLSL64() const {
946 if (!isExtend())
947 return false;
948 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
949 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
950 ET == AArch64_AM::LSL) &&
951 getShiftExtendAmount() <= 4;
952 }
953
954 template<int Width> bool isMemXExtend() const {
955 if (!isExtend())
956 return false;
957 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
958 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
959 (getShiftExtendAmount() == Log2_32(Width / 8) ||
960 getShiftExtendAmount() == 0);
961 }
962
963 template<int Width> bool isMemWExtend() const {
964 if (!isExtend())
965 return false;
966 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
967 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
968 (getShiftExtendAmount() == Log2_32(Width / 8) ||
969 getShiftExtendAmount() == 0);
970 }
971
972 template <unsigned width>
973 bool isArithmeticShifter() const {
974 if (!isShifter())
975 return false;
976
977 // An arithmetic shifter is LSL, LSR, or ASR.
978 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
979 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
980 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
981 }
982
983 template <unsigned width>
984 bool isLogicalShifter() const {
985 if (!isShifter())
986 return false;
987
988 // A logical shifter is LSL, LSR, ASR or ROR.
989 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
990 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
991 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
992 getShiftExtendAmount() < width;
993 }
994
995 bool isMovImm32Shifter() const {
996 if (!isShifter())
997 return false;
998
999 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1000 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1001 if (ST != AArch64_AM::LSL)
1002 return false;
1003 uint64_t Val = getShiftExtendAmount();
1004 return (Val == 0 || Val == 16);
1005 }
1006
1007 bool isMovImm64Shifter() const {
1008 if (!isShifter())
1009 return false;
1010
1011 // A MOVi shifter is LSL of 0 or 16.
1012 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1013 if (ST != AArch64_AM::LSL)
1014 return false;
1015 uint64_t Val = getShiftExtendAmount();
1016 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1017 }
1018
1019 bool isLogicalVecShifter() const {
1020 if (!isShifter())
1021 return false;
1022
1023 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1024 unsigned Shift = getShiftExtendAmount();
1025 return getShiftExtendType() == AArch64_AM::LSL &&
1026 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1027 }
1028
1029 bool isLogicalVecHalfWordShifter() const {
1030 if (!isLogicalVecShifter())
1031 return false;
1032
1033 // A logical vector shifter is a left shift by 0 or 8.
1034 unsigned Shift = getShiftExtendAmount();
1035 return getShiftExtendType() == AArch64_AM::LSL &&
1036 (Shift == 0 || Shift == 8);
1037 }
1038
1039 bool isMoveVecShifter() const {
1040 if (!isShiftExtend())
1041 return false;
1042
1043 // A logical vector shifter is a left shift by 8 or 16.
1044 unsigned Shift = getShiftExtendAmount();
1045 return getShiftExtendType() == AArch64_AM::MSL &&
1046 (Shift == 8 || Shift == 16);
1047 }
1048
1049 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1050 // to LDUR/STUR when the offset is not legal for the former but is for
1051 // the latter. As such, in addition to checking for being a legal unscaled
1052 // address, also check that it is not a legal scaled address. This avoids
1053 // ambiguity in the matcher.
1054 template<int Width>
1055 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001056 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001057 }
1058
1059 bool isAdrpLabel() const {
1060 // Validation was handled during parsing, so we just sanity check that
1061 // something didn't go haywire.
1062 if (!isImm())
1063 return false;
1064
1065 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1066 int64_t Val = CE->getValue();
1067 int64_t Min = - (4096 * (1LL << (21 - 1)));
1068 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1069 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1070 }
1071
1072 return true;
1073 }
1074
1075 bool isAdrLabel() const {
1076 // Validation was handled during parsing, so we just sanity check that
1077 // something didn't go haywire.
1078 if (!isImm())
1079 return false;
1080
1081 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1082 int64_t Val = CE->getValue();
1083 int64_t Min = - (1LL << (21 - 1));
1084 int64_t Max = ((1LL << (21 - 1)) - 1);
1085 return Val >= Min && Val <= Max;
1086 }
1087
1088 return true;
1089 }
1090
1091 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1092 // Add as immediates when possible. Null MCExpr = 0.
1093 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001094 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001095 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001096 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001097 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001098 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001099 }
1100
1101 void addRegOperands(MCInst &Inst, unsigned N) const {
1102 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001103 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001104 }
1105
1106 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1107 assert(N == 1 && "Invalid number of operands!");
1108 assert(
1109 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1110
1111 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1112 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1113 RI->getEncodingValue(getReg()));
1114
Jim Grosbache9119e42015-05-13 18:37:00 +00001115 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001116 }
1117
1118 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1119 assert(N == 1 && "Invalid number of operands!");
1120 assert(
1121 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001122 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001123 }
1124
1125 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1126 assert(N == 1 && "Invalid number of operands!");
1127 assert(
1128 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001129 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001130 }
1131
1132 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1133 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001134 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001135 }
1136
1137 template <unsigned NumRegs>
1138 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1139 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001140 static const unsigned FirstRegs[] = { AArch64::D0,
1141 AArch64::D0_D1,
1142 AArch64::D0_D1_D2,
1143 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001144 unsigned FirstReg = FirstRegs[NumRegs - 1];
1145
1146 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001147 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001148 }
1149
1150 template <unsigned NumRegs>
1151 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1152 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001153 static const unsigned FirstRegs[] = { AArch64::Q0,
1154 AArch64::Q0_Q1,
1155 AArch64::Q0_Q1_Q2,
1156 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001157 unsigned FirstReg = FirstRegs[NumRegs - 1];
1158
1159 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001160 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001161 }
1162
1163 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1164 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001165 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001166 }
1167
1168 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1169 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001170 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001171 }
1172
1173 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1174 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001175 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001176 }
1177
1178 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1179 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001180 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001181 }
1182
1183 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1184 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001185 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001186 }
1187
1188 void addImmOperands(MCInst &Inst, unsigned N) const {
1189 assert(N == 1 && "Invalid number of operands!");
1190 // If this is a pageoff symrefexpr with an addend, adjust the addend
1191 // to be only the page-offset portion. Otherwise, just add the expr
1192 // as-is.
1193 addExpr(Inst, getImm());
1194 }
1195
1196 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1197 assert(N == 2 && "Invalid number of operands!");
1198 if (isShiftedImm()) {
1199 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001200 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001201 } else {
1202 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001203 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001204 }
1205 }
1206
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001207 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1208 assert(N == 2 && "Invalid number of operands!");
1209
1210 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1211 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1212 int64_t Val = -CE->getValue();
1213 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1214
1215 Inst.addOperand(MCOperand::createImm(Val));
1216 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1217 }
1218
Tim Northover3b0846e2014-05-24 12:50:23 +00001219 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1220 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001221 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001222 }
1223
1224 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1225 assert(N == 1 && "Invalid number of operands!");
1226 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1227 if (!MCE)
1228 addExpr(Inst, getImm());
1229 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001230 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001231 }
1232
1233 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1234 addImmOperands(Inst, N);
1235 }
1236
1237 template<int Scale>
1238 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1239 assert(N == 1 && "Invalid number of operands!");
1240 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1241
1242 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001243 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001244 return;
1245 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001246 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001247 }
1248
1249 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1250 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001251 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001252 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001253 }
1254
Sam Parker6d42de72017-08-11 13:14:00 +00001255 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1256 assert(N == 1 && "Invalid number of operands!");
1257 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1258 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1259 }
1260
Tim Northover3b0846e2014-05-24 12:50:23 +00001261 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1262 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001263 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001264 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001265 }
1266
1267 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1268 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001269 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001270 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001271 }
1272
1273 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1274 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001275 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001276 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001277 }
1278
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001279 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1280 assert(N == 1 && "Invalid number of operands!");
1281 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1282 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1283 }
1284
Tim Northover3b0846e2014-05-24 12:50:23 +00001285 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1286 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001287 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001288 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001289 }
1290
1291 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1292 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001293 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001294 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001295 }
1296
1297 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1298 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001299 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001300 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001301 }
1302
1303 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1304 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001305 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001306 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001307 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001308 }
1309
1310 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1311 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001312 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001313 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001314 }
1315
1316 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1317 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001318 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001319 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001320 }
1321
1322 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1323 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001324 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001325 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001326 }
1327
1328 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1329 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001330 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001331 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001332 }
1333
1334 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1335 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001336 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001337 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001338 }
1339
1340 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1341 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001342 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001343 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001344 }
1345
1346 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1347 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001348 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001349 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001350 }
1351
1352 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1353 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001354 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001355 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001356 }
1357
1358 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1359 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001360 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001361 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001362 }
1363
1364 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1365 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001366 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001367 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001368 }
1369
1370 void addLogicalImm32Operands(MCInst &Inst, unsigned N) const {
1371 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001372 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +00001373 uint64_t encoding =
1374 AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001375 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001376 }
1377
1378 void addLogicalImm64Operands(MCInst &Inst, unsigned N) const {
1379 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001380 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001381 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001382 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001383 }
1384
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001385 void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
1386 assert(N == 1 && "Invalid number of operands!");
1387 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1388 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
1389 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001390 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001391 }
1392
1393 void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
1394 assert(N == 1 && "Invalid number of operands!");
1395 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1396 uint64_t encoding =
1397 AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001398 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001399 }
1400
Tim Northover3b0846e2014-05-24 12:50:23 +00001401 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1402 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001403 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001404 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001405 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001406 }
1407
1408 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1409 // Branch operands don't encode the low bits, so shift them off
1410 // here. If it's a label, however, just put it on directly as there's
1411 // not enough information now to do anything.
1412 assert(N == 1 && "Invalid number of operands!");
1413 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1414 if (!MCE) {
1415 addExpr(Inst, getImm());
1416 return;
1417 }
1418 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001419 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001420 }
1421
1422 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1423 // Branch operands don't encode the low bits, so shift them off
1424 // here. If it's a label, however, just put it on directly as there's
1425 // not enough information now to do anything.
1426 assert(N == 1 && "Invalid number of operands!");
1427 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1428 if (!MCE) {
1429 addExpr(Inst, getImm());
1430 return;
1431 }
1432 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001433 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 }
1435
1436 void addBranchTarget14Operands(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 addFPImmOperands(MCInst &Inst, unsigned N) const {
1451 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001452 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001453 }
1454
1455 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1456 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001457 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001458 }
1459
1460 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1461 assert(N == 1 && "Invalid number of operands!");
1462
Jim Grosbache9119e42015-05-13 18:37:00 +00001463 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001464 }
1465
1466 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1467 assert(N == 1 && "Invalid number of operands!");
1468
Jim Grosbache9119e42015-05-13 18:37:00 +00001469 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001470 }
1471
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001472 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1473 assert(N == 1 && "Invalid number of operands!");
1474
1475 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1476 }
1477
1478 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001479 assert(N == 1 && "Invalid number of operands!");
1480
Jim Grosbache9119e42015-05-13 18:37:00 +00001481 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001482 }
1483
1484 void addSysCROperands(MCInst &Inst, unsigned N) const {
1485 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001486 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001487 }
1488
1489 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1490 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001491 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001492 }
1493
Oliver Stannarda34e4702015-12-01 10:48:51 +00001494 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1495 assert(N == 1 && "Invalid number of operands!");
1496 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1497 }
1498
Tim Northover3b0846e2014-05-24 12:50:23 +00001499 void addShifterOperands(MCInst &Inst, unsigned N) const {
1500 assert(N == 1 && "Invalid number of operands!");
1501 unsigned Imm =
1502 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001503 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001504 }
1505
1506 void addExtendOperands(MCInst &Inst, unsigned N) const {
1507 assert(N == 1 && "Invalid number of operands!");
1508 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1509 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1510 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001511 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001512 }
1513
1514 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1515 assert(N == 1 && "Invalid number of operands!");
1516 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1517 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1518 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001519 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001520 }
1521
1522 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1523 assert(N == 2 && "Invalid number of operands!");
1524 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1525 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001526 Inst.addOperand(MCOperand::createImm(IsSigned));
1527 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001528 }
1529
1530 // For 8-bit load/store instructions with a register offset, both the
1531 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1532 // they're disambiguated by whether the shift was explicit or implicit rather
1533 // than its size.
1534 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1535 assert(N == 2 && "Invalid number of operands!");
1536 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1537 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001538 Inst.addOperand(MCOperand::createImm(IsSigned));
1539 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001540 }
1541
1542 template<int Shift>
1543 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1544 assert(N == 1 && "Invalid number of operands!");
1545
1546 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1547 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001548 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001549 }
1550
1551 template<int Shift>
1552 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1553 assert(N == 1 && "Invalid number of operands!");
1554
1555 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1556 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001557 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001558 }
1559
Sam Parker5f934642017-08-31 09:27:04 +00001560 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1561 assert(N == 1 && "Invalid number of operands!");
1562 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1563 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1564 }
1565
1566 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1567 assert(N == 1 && "Invalid number of operands!");
1568 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1569 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1570 }
1571
Tim Northover3b0846e2014-05-24 12:50:23 +00001572 void print(raw_ostream &OS) const override;
1573
David Blaikie960ea3f2014-06-08 16:18:35 +00001574 static std::unique_ptr<AArch64Operand>
1575 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1576 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001577 Op->Tok.Data = Str.data();
1578 Op->Tok.Length = Str.size();
1579 Op->Tok.IsSuffix = IsSuffix;
1580 Op->StartLoc = S;
1581 Op->EndLoc = S;
1582 return Op;
1583 }
1584
David Blaikie960ea3f2014-06-08 16:18:35 +00001585 static std::unique_ptr<AArch64Operand>
Florian Hahnc4422242017-11-07 13:07:50 +00001586 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001587 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001588 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001589 Op->Reg.Kind = Kind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001590 Op->StartLoc = S;
1591 Op->EndLoc = E;
1592 return Op;
1593 }
1594
David Blaikie960ea3f2014-06-08 16:18:35 +00001595 static std::unique_ptr<AArch64Operand>
Florian Hahn91f11e52017-11-07 16:45:48 +00001596 CreateReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1597 SMLoc S, SMLoc E, MCContext &Ctx) {
1598 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1599 Op->Reg.RegNum = RegNum;
1600 Op->Reg.ElementWidth = ElementWidth;
1601 Op->Reg.Kind = Kind;
1602 Op->StartLoc = S;
1603 Op->EndLoc = E;
1604 return Op;
1605 }
1606
1607 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001608 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1609 char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1610 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001611 Op->VectorList.RegNum = RegNum;
1612 Op->VectorList.Count = Count;
1613 Op->VectorList.NumElements = NumElements;
1614 Op->VectorList.ElementKind = ElementKind;
1615 Op->StartLoc = S;
1616 Op->EndLoc = E;
1617 return Op;
1618 }
1619
David Blaikie960ea3f2014-06-08 16:18:35 +00001620 static std::unique_ptr<AArch64Operand>
1621 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1622 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001623 Op->VectorIndex.Val = Idx;
1624 Op->StartLoc = S;
1625 Op->EndLoc = E;
1626 return Op;
1627 }
1628
David Blaikie960ea3f2014-06-08 16:18:35 +00001629 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1630 SMLoc E, MCContext &Ctx) {
1631 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001632 Op->Imm.Val = Val;
1633 Op->StartLoc = S;
1634 Op->EndLoc = E;
1635 return Op;
1636 }
1637
David Blaikie960ea3f2014-06-08 16:18:35 +00001638 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1639 unsigned ShiftAmount,
1640 SMLoc S, SMLoc E,
1641 MCContext &Ctx) {
1642 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001643 Op->ShiftedImm .Val = Val;
1644 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1645 Op->StartLoc = S;
1646 Op->EndLoc = E;
1647 return Op;
1648 }
1649
David Blaikie960ea3f2014-06-08 16:18:35 +00001650 static std::unique_ptr<AArch64Operand>
1651 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1652 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001653 Op->CondCode.Code = Code;
1654 Op->StartLoc = S;
1655 Op->EndLoc = E;
1656 return Op;
1657 }
1658
David Blaikie960ea3f2014-06-08 16:18:35 +00001659 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1660 MCContext &Ctx) {
1661 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001662 Op->FPImm.Val = Val;
1663 Op->StartLoc = S;
1664 Op->EndLoc = S;
1665 return Op;
1666 }
1667
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001668 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1669 StringRef Str,
1670 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001671 MCContext &Ctx) {
1672 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001673 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001674 Op->Barrier.Data = Str.data();
1675 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001676 Op->StartLoc = S;
1677 Op->EndLoc = S;
1678 return Op;
1679 }
1680
Tim Northover7cd58932015-01-22 17:23:04 +00001681 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1682 uint32_t MRSReg,
1683 uint32_t MSRReg,
1684 uint32_t PStateField,
1685 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001686 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001687 Op->SysReg.Data = Str.data();
1688 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001689 Op->SysReg.MRSReg = MRSReg;
1690 Op->SysReg.MSRReg = MSRReg;
1691 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001692 Op->StartLoc = S;
1693 Op->EndLoc = S;
1694 return Op;
1695 }
1696
David Blaikie960ea3f2014-06-08 16:18:35 +00001697 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1698 SMLoc E, MCContext &Ctx) {
1699 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001700 Op->SysCRImm.Val = Val;
1701 Op->StartLoc = S;
1702 Op->EndLoc = E;
1703 return Op;
1704 }
1705
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001706 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1707 StringRef Str,
1708 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001709 MCContext &Ctx) {
1710 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001711 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001712 Op->Barrier.Data = Str.data();
1713 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001714 Op->StartLoc = S;
1715 Op->EndLoc = S;
1716 return Op;
1717 }
1718
Oliver Stannarda34e4702015-12-01 10:48:51 +00001719 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1720 StringRef Str,
1721 SMLoc S,
1722 MCContext &Ctx) {
1723 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1724 Op->PSBHint.Val = Val;
1725 Op->PSBHint.Data = Str.data();
1726 Op->PSBHint.Length = Str.size();
1727 Op->StartLoc = S;
1728 Op->EndLoc = S;
1729 return Op;
1730 }
1731
David Blaikie960ea3f2014-06-08 16:18:35 +00001732 static std::unique_ptr<AArch64Operand>
1733 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1734 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1735 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001736 Op->ShiftExtend.Type = ShOp;
1737 Op->ShiftExtend.Amount = Val;
1738 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1739 Op->StartLoc = S;
1740 Op->EndLoc = E;
1741 return Op;
1742 }
1743};
1744
1745} // end anonymous namespace.
1746
1747void AArch64Operand::print(raw_ostream &OS) const {
1748 switch (Kind) {
1749 case k_FPImm:
1750 OS << "<fpimm " << getFPImm() << "("
1751 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1752 break;
1753 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001754 StringRef Name = getBarrierName();
1755 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001756 OS << "<barrier " << Name << ">";
1757 else
1758 OS << "<barrier invalid #" << getBarrier() << ">";
1759 break;
1760 }
1761 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001762 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001763 break;
1764 case k_ShiftedImm: {
1765 unsigned Shift = getShiftedImmShift();
1766 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001767 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001768 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1769 break;
1770 }
1771 case k_CondCode:
1772 OS << "<condcode " << getCondCode() << ">";
1773 break;
1774 case k_Register:
1775 OS << "<register " << getReg() << ">";
1776 break;
1777 case k_VectorList: {
1778 OS << "<vectorlist ";
1779 unsigned Reg = getVectorListStart();
1780 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1781 OS << Reg + i << " ";
1782 OS << ">";
1783 break;
1784 }
1785 case k_VectorIndex:
1786 OS << "<vectorindex " << getVectorIndex() << ">";
1787 break;
1788 case k_SysReg:
1789 OS << "<sysreg: " << getSysReg() << '>';
1790 break;
1791 case k_Token:
1792 OS << "'" << getToken() << "'";
1793 break;
1794 case k_SysCR:
1795 OS << "c" << getSysCR();
1796 break;
1797 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001798 StringRef Name = getPrefetchName();
1799 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001800 OS << "<prfop " << Name << ">";
1801 else
1802 OS << "<prfop invalid #" << getPrefetch() << ">";
1803 break;
1804 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001805 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001806 OS << getPSBHintName();
1807 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001808 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001809 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1810 << getShiftExtendAmount();
1811 if (!hasShiftExtendAmount())
1812 OS << "<imp>";
1813 OS << '>';
1814 break;
1815 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001816}
1817
1818/// @name Auto-generated Match Functions
1819/// {
1820
1821static unsigned MatchRegisterName(StringRef Name);
1822
1823/// }
1824
Florian Hahnc4422242017-11-07 13:07:50 +00001825static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001826 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001827 .Case("v0", AArch64::Q0)
1828 .Case("v1", AArch64::Q1)
1829 .Case("v2", AArch64::Q2)
1830 .Case("v3", AArch64::Q3)
1831 .Case("v4", AArch64::Q4)
1832 .Case("v5", AArch64::Q5)
1833 .Case("v6", AArch64::Q6)
1834 .Case("v7", AArch64::Q7)
1835 .Case("v8", AArch64::Q8)
1836 .Case("v9", AArch64::Q9)
1837 .Case("v10", AArch64::Q10)
1838 .Case("v11", AArch64::Q11)
1839 .Case("v12", AArch64::Q12)
1840 .Case("v13", AArch64::Q13)
1841 .Case("v14", AArch64::Q14)
1842 .Case("v15", AArch64::Q15)
1843 .Case("v16", AArch64::Q16)
1844 .Case("v17", AArch64::Q17)
1845 .Case("v18", AArch64::Q18)
1846 .Case("v19", AArch64::Q19)
1847 .Case("v20", AArch64::Q20)
1848 .Case("v21", AArch64::Q21)
1849 .Case("v22", AArch64::Q22)
1850 .Case("v23", AArch64::Q23)
1851 .Case("v24", AArch64::Q24)
1852 .Case("v25", AArch64::Q25)
1853 .Case("v26", AArch64::Q26)
1854 .Case("v27", AArch64::Q27)
1855 .Case("v28", AArch64::Q28)
1856 .Case("v29", AArch64::Q29)
1857 .Case("v30", AArch64::Q30)
1858 .Case("v31", AArch64::Q31)
1859 .Default(0);
1860}
1861
1862static bool isValidVectorKind(StringRef Name) {
1863 return StringSwitch<bool>(Name.lower())
1864 .Case(".8b", true)
1865 .Case(".16b", true)
1866 .Case(".4h", true)
1867 .Case(".8h", true)
1868 .Case(".2s", true)
1869 .Case(".4s", true)
1870 .Case(".1d", true)
1871 .Case(".2d", true)
1872 .Case(".1q", true)
1873 // Accept the width neutral ones, too, for verbose syntax. If those
1874 // aren't used in the right places, the token operand won't match so
1875 // all will work out.
1876 .Case(".b", true)
1877 .Case(".h", true)
1878 .Case(".s", true)
1879 .Case(".d", true)
Oliver Stannarde4c3d212015-12-08 12:16:10 +00001880 // Needed for fp16 scalar pairwise reductions
1881 .Case(".2h", true)
Sjoerd Meijer79876332017-08-09 14:59:54 +00001882 // another special case for the ARMv8.2a dot product operand
1883 .Case(".4b", true)
Tim Northover3b0846e2014-05-24 12:50:23 +00001884 .Default(false);
1885}
1886
Florian Hahn91f11e52017-11-07 16:45:48 +00001887static unsigned matchSVEDataVectorRegName(StringRef Name) {
1888 return StringSwitch<unsigned>(Name.lower())
1889 .Case("z0", AArch64::Z0)
1890 .Case("z1", AArch64::Z1)
1891 .Case("z2", AArch64::Z2)
1892 .Case("z3", AArch64::Z3)
1893 .Case("z4", AArch64::Z4)
1894 .Case("z5", AArch64::Z5)
1895 .Case("z6", AArch64::Z6)
1896 .Case("z7", AArch64::Z7)
1897 .Case("z8", AArch64::Z8)
1898 .Case("z9", AArch64::Z9)
1899 .Case("z10", AArch64::Z10)
1900 .Case("z11", AArch64::Z11)
1901 .Case("z12", AArch64::Z12)
1902 .Case("z13", AArch64::Z13)
1903 .Case("z14", AArch64::Z14)
1904 .Case("z15", AArch64::Z15)
1905 .Case("z16", AArch64::Z16)
1906 .Case("z17", AArch64::Z17)
1907 .Case("z18", AArch64::Z18)
1908 .Case("z19", AArch64::Z19)
1909 .Case("z20", AArch64::Z20)
1910 .Case("z21", AArch64::Z21)
1911 .Case("z22", AArch64::Z22)
1912 .Case("z23", AArch64::Z23)
1913 .Case("z24", AArch64::Z24)
1914 .Case("z25", AArch64::Z25)
1915 .Case("z26", AArch64::Z26)
1916 .Case("z27", AArch64::Z27)
1917 .Case("z28", AArch64::Z28)
1918 .Case("z29", AArch64::Z29)
1919 .Case("z30", AArch64::Z30)
1920 .Case("z31", AArch64::Z31)
1921 .Default(0);
1922}
1923
Sander de Smalencd6be962017-12-20 11:02:42 +00001924static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1925 return StringSwitch<unsigned>(Name.lower())
1926 .Case("p0", AArch64::P0)
1927 .Case("p1", AArch64::P1)
1928 .Case("p2", AArch64::P2)
1929 .Case("p3", AArch64::P3)
1930 .Case("p4", AArch64::P4)
1931 .Case("p5", AArch64::P5)
1932 .Case("p6", AArch64::P6)
1933 .Case("p7", AArch64::P7)
1934 .Case("p8", AArch64::P8)
1935 .Case("p9", AArch64::P9)
1936 .Case("p10", AArch64::P10)
1937 .Case("p11", AArch64::P11)
1938 .Case("p12", AArch64::P12)
1939 .Case("p13", AArch64::P13)
1940 .Case("p14", AArch64::P14)
1941 .Case("p15", AArch64::P15)
1942 .Default(0);
1943}
1944
Florian Hahn91f11e52017-11-07 16:45:48 +00001945static bool isValidSVEKind(StringRef Name) {
1946 return StringSwitch<bool>(Name.lower())
1947 .Case(".b", true)
1948 .Case(".h", true)
1949 .Case(".s", true)
1950 .Case(".d", true)
1951 .Case(".q", true)
1952 .Default(false);
1953}
1954
Tim Northover3b0846e2014-05-24 12:50:23 +00001955static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1956 char &ElementKind) {
1957 assert(isValidVectorKind(Name));
1958
1959 ElementKind = Name.lower()[Name.size() - 1];
1960 NumElements = 0;
1961
1962 if (Name.size() == 2)
1963 return;
1964
1965 // Parse the lane count
1966 Name = Name.drop_front();
1967 while (isdigit(Name.front())) {
1968 NumElements = 10 * NumElements + (Name.front() - '0');
1969 Name = Name.drop_front();
1970 }
1971}
1972
1973bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1974 SMLoc &EndLoc) {
1975 StartLoc = getLoc();
1976 RegNo = tryParseRegister();
1977 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1978 return (RegNo == (unsigned)-1);
1979}
1980
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001981// Matches a register name or register alias previously defined by '.req'
1982unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001983 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001984 unsigned RegNum = 0;
1985 if ((RegNum = matchSVEDataVectorRegName(Name)))
1986 return Kind == RegKind::SVEDataVector ? RegNum : 0;
1987
Sander de Smalencd6be962017-12-20 11:02:42 +00001988 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
1989 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
1990
Sander de Smalenc067c302017-12-20 09:45:45 +00001991 if ((RegNum = MatchNeonVectorRegName(Name)))
1992 return Kind == RegKind::NeonVector ? RegNum : 0;
1993
1994 // The parsed register must be of RegKind Scalar
1995 if ((RegNum = MatchRegisterName(Name)))
1996 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001997
Florian Hahnc4422242017-11-07 13:07:50 +00001998 if (!RegNum) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001999 // Check for aliases registered via .req. Canonicalize to lower case.
2000 // That's more consistent since register names are case insensitive, and
2001 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2002 auto Entry = RegisterReqs.find(Name.lower());
2003 if (Entry == RegisterReqs.end())
2004 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002005
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002006 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002007 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002008 RegNum = Entry->getValue().second;
2009 }
2010 return RegNum;
2011}
2012
Tim Northover3b0846e2014-05-24 12:50:23 +00002013/// tryParseRegister - Try to parse a register name. The token must be an
2014/// Identifier when called, and if it is a register name the token is eaten and
2015/// the register is added to the operand list.
2016int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002017 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002018 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002019 if (Tok.isNot(AsmToken::Identifier))
2020 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00002021
2022 std::string lowerCase = Tok.getString().lower();
Florian Hahnc4422242017-11-07 13:07:50 +00002023 unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
Sander de Smalenc067c302017-12-20 09:45:45 +00002024
Tim Northover3b0846e2014-05-24 12:50:23 +00002025 // Also handle a few aliases of registers.
2026 if (RegNum == 0)
2027 RegNum = StringSwitch<unsigned>(lowerCase)
2028 .Case("fp", AArch64::FP)
2029 .Case("lr", AArch64::LR)
2030 .Case("x31", AArch64::XZR)
2031 .Case("w31", AArch64::WZR)
2032 .Default(0);
2033
2034 if (RegNum == 0)
2035 return -1;
2036
2037 Parser.Lex(); // Eat identifier token.
2038 return RegNum;
2039}
2040
2041/// tryMatchVectorRegister - Try to parse a vector register name with optional
2042/// kind specifier. If it is a register specifier, eat the token and return it.
2043int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002044 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002045 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2046 TokError("vector register expected");
2047 return -1;
2048 }
2049
2050 StringRef Name = Parser.getTok().getString();
2051 // If there is a kind specifier, it's separated from the register name by
2052 // a '.'.
2053 size_t Start = 0, Next = Name.find('.');
2054 StringRef Head = Name.slice(Start, Next);
Florian Hahnc4422242017-11-07 13:07:50 +00002055 unsigned RegNum = matchRegisterNameAlias(Head, RegKind::NeonVector);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002056
Tim Northover3b0846e2014-05-24 12:50:23 +00002057 if (RegNum) {
2058 if (Next != StringRef::npos) {
2059 Kind = Name.slice(Next, StringRef::npos);
2060 if (!isValidVectorKind(Kind)) {
2061 TokError("invalid vector kind qualifier");
2062 return -1;
2063 }
2064 }
2065 Parser.Lex(); // Eat the register token.
2066 return RegNum;
2067 }
2068
2069 if (expected)
2070 TokError("vector register expected");
2071 return -1;
2072}
2073
2074/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002075OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002076AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002077 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002078 SMLoc S = getLoc();
2079
2080 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2081 Error(S, "Expected cN operand where 0 <= N <= 15");
2082 return MatchOperand_ParseFail;
2083 }
2084
2085 StringRef Tok = Parser.getTok().getIdentifier();
2086 if (Tok[0] != 'c' && Tok[0] != 'C') {
2087 Error(S, "Expected cN operand where 0 <= N <= 15");
2088 return MatchOperand_ParseFail;
2089 }
2090
2091 uint32_t CRNum;
2092 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2093 if (BadNum || CRNum > 15) {
2094 Error(S, "Expected cN operand where 0 <= N <= 15");
2095 return MatchOperand_ParseFail;
2096 }
2097
2098 Parser.Lex(); // Eat identifier token.
2099 Operands.push_back(
2100 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2101 return MatchOperand_Success;
2102}
2103
2104/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002105OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002106AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002107 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002108 SMLoc S = getLoc();
2109 const AsmToken &Tok = Parser.getTok();
2110 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002111 // Eat optional hash.
2112 if (parseOptionalToken(AsmToken::Hash) ||
2113 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002114 const MCExpr *ImmVal;
2115 if (getParser().parseExpression(ImmVal))
2116 return MatchOperand_ParseFail;
2117
2118 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2119 if (!MCE) {
2120 TokError("immediate value expected for prefetch operand");
2121 return MatchOperand_ParseFail;
2122 }
2123 unsigned prfop = MCE->getValue();
2124 if (prfop > 31) {
2125 TokError("prefetch operand out of range, [0,31] expected");
2126 return MatchOperand_ParseFail;
2127 }
2128
Tim Northovere6ae6762016-07-05 21:23:04 +00002129 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2130 Operands.push_back(AArch64Operand::CreatePrefetch(
2131 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002132 return MatchOperand_Success;
2133 }
2134
2135 if (Tok.isNot(AsmToken::Identifier)) {
2136 TokError("pre-fetch hint expected");
2137 return MatchOperand_ParseFail;
2138 }
2139
Tim Northovere6ae6762016-07-05 21:23:04 +00002140 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2141 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002142 TokError("pre-fetch hint expected");
2143 return MatchOperand_ParseFail;
2144 }
2145
2146 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002147 Operands.push_back(AArch64Operand::CreatePrefetch(
2148 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002149 return MatchOperand_Success;
2150}
2151
Oliver Stannarda34e4702015-12-01 10:48:51 +00002152/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002153OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002154AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2155 MCAsmParser &Parser = getParser();
2156 SMLoc S = getLoc();
2157 const AsmToken &Tok = Parser.getTok();
2158 if (Tok.isNot(AsmToken::Identifier)) {
2159 TokError("invalid operand for instruction");
2160 return MatchOperand_ParseFail;
2161 }
2162
Tim Northovere6ae6762016-07-05 21:23:04 +00002163 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2164 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002165 TokError("invalid operand for instruction");
2166 return MatchOperand_ParseFail;
2167 }
2168
2169 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002170 Operands.push_back(AArch64Operand::CreatePSBHint(
2171 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002172 return MatchOperand_Success;
2173}
2174
Tim Northover3b0846e2014-05-24 12:50:23 +00002175/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2176/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002177OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002178AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002179 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002180 SMLoc S = getLoc();
2181 const MCExpr *Expr;
2182
2183 if (Parser.getTok().is(AsmToken::Hash)) {
2184 Parser.Lex(); // Eat hash token.
2185 }
2186
2187 if (parseSymbolicImmVal(Expr))
2188 return MatchOperand_ParseFail;
2189
2190 AArch64MCExpr::VariantKind ELFRefKind;
2191 MCSymbolRefExpr::VariantKind DarwinRefKind;
2192 int64_t Addend;
2193 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2194 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2195 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2196 // No modifier was specified at all; this is the syntax for an ELF basic
2197 // ADRP relocation (unfortunately).
2198 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002199 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002200 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2201 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2202 Addend != 0) {
2203 Error(S, "gotpage label reference not allowed an addend");
2204 return MatchOperand_ParseFail;
2205 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2206 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2207 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2208 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2209 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2210 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2211 // The operand must be an @page or @gotpage qualified symbolref.
2212 Error(S, "page or gotpage label reference expected");
2213 return MatchOperand_ParseFail;
2214 }
2215 }
2216
2217 // We have either a label reference possibly with addend or an immediate. The
2218 // addend is a raw value here. The linker will adjust it to only reference the
2219 // page.
2220 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2221 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2222
2223 return MatchOperand_Success;
2224}
2225
2226/// tryParseAdrLabel - Parse and validate a source label for the ADR
2227/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002228OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002229AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2230 SMLoc S = getLoc();
2231 const MCExpr *Expr;
2232
Nirav Davee833c6c2016-11-08 18:31:04 +00002233 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002234 if (getParser().parseExpression(Expr))
2235 return MatchOperand_ParseFail;
2236
2237 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2238 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2239
2240 return MatchOperand_Success;
2241}
2242
2243/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002244OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002245AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002246 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002247 SMLoc S = getLoc();
2248
Nirav Davee833c6c2016-11-08 18:31:04 +00002249 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002250
2251 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002252 bool isNegative = parseOptionalToken(AsmToken::Minus);
2253
Tim Northover3b0846e2014-05-24 12:50:23 +00002254 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002255 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002256 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002257 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002258 Val = Tok.getIntVal();
2259 if (Val > 255 || Val < 0) {
2260 TokError("encoded floating point value out of range");
2261 return MatchOperand_ParseFail;
2262 }
2263 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002264 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002265 if (isNegative)
2266 RealVal.changeSign();
2267
Tim Northover3b0846e2014-05-24 12:50:23 +00002268 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002269 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002270
John Brawn5ca5daa2017-04-20 10:13:54 +00002271 // Check for out of range values. As an exception we let Zero through,
2272 // but as tokens instead of an FPImm so that it can be matched by the
2273 // appropriate alias if one exists.
2274 if (RealVal.isPosZero()) {
2275 Parser.Lex(); // Eat the token.
2276 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2277 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2278 return MatchOperand_Success;
2279 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002280 TokError("expected compatible register or floating-point constant");
2281 return MatchOperand_ParseFail;
2282 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002283 }
2284 Parser.Lex(); // Eat the token.
2285 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2286 return MatchOperand_Success;
2287 }
2288
2289 if (!Hash)
2290 return MatchOperand_NoMatch;
2291
2292 TokError("invalid floating point immediate");
2293 return MatchOperand_ParseFail;
2294}
2295
2296/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002297OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002298AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002299 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002300 SMLoc S = getLoc();
2301
2302 if (Parser.getTok().is(AsmToken::Hash))
2303 Parser.Lex(); // Eat '#'
2304 else if (Parser.getTok().isNot(AsmToken::Integer))
2305 // Operand should start from # or should be integer, emit error otherwise.
2306 return MatchOperand_NoMatch;
2307
2308 const MCExpr *Imm;
2309 if (parseSymbolicImmVal(Imm))
2310 return MatchOperand_ParseFail;
2311 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2312 uint64_t ShiftAmount = 0;
2313 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2314 if (MCE) {
2315 int64_t Val = MCE->getValue();
2316 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002317 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002318 ShiftAmount = 12;
2319 }
2320 }
2321 SMLoc E = Parser.getTok().getLoc();
2322 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2323 getContext()));
2324 return MatchOperand_Success;
2325 }
2326
2327 // Eat ','
2328 Parser.Lex();
2329
2330 // The optional operand must be "lsl #N" where N is non-negative.
2331 if (!Parser.getTok().is(AsmToken::Identifier) ||
2332 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2333 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2334 return MatchOperand_ParseFail;
2335 }
2336
2337 // Eat 'lsl'
2338 Parser.Lex();
2339
Nirav Davee833c6c2016-11-08 18:31:04 +00002340 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002341
2342 if (Parser.getTok().isNot(AsmToken::Integer)) {
2343 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2344 return MatchOperand_ParseFail;
2345 }
2346
2347 int64_t ShiftAmount = Parser.getTok().getIntVal();
2348
2349 if (ShiftAmount < 0) {
2350 Error(Parser.getTok().getLoc(), "positive shift amount required");
2351 return MatchOperand_ParseFail;
2352 }
2353 Parser.Lex(); // Eat the number
2354
2355 SMLoc E = Parser.getTok().getLoc();
2356 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2357 S, E, getContext()));
2358 return MatchOperand_Success;
2359}
2360
2361/// parseCondCodeString - Parse a Condition Code string.
2362AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2363 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2364 .Case("eq", AArch64CC::EQ)
2365 .Case("ne", AArch64CC::NE)
2366 .Case("cs", AArch64CC::HS)
2367 .Case("hs", AArch64CC::HS)
2368 .Case("cc", AArch64CC::LO)
2369 .Case("lo", AArch64CC::LO)
2370 .Case("mi", AArch64CC::MI)
2371 .Case("pl", AArch64CC::PL)
2372 .Case("vs", AArch64CC::VS)
2373 .Case("vc", AArch64CC::VC)
2374 .Case("hi", AArch64CC::HI)
2375 .Case("ls", AArch64CC::LS)
2376 .Case("ge", AArch64CC::GE)
2377 .Case("lt", AArch64CC::LT)
2378 .Case("gt", AArch64CC::GT)
2379 .Case("le", AArch64CC::LE)
2380 .Case("al", AArch64CC::AL)
2381 .Case("nv", AArch64CC::NV)
2382 .Default(AArch64CC::Invalid);
2383 return CC;
2384}
2385
2386/// parseCondCode - Parse a Condition Code operand.
2387bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2388 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002389 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002390 SMLoc S = getLoc();
2391 const AsmToken &Tok = Parser.getTok();
2392 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2393
2394 StringRef Cond = Tok.getString();
2395 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2396 if (CC == AArch64CC::Invalid)
2397 return TokError("invalid condition code");
2398 Parser.Lex(); // Eat identifier token.
2399
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002400 if (invertCondCode) {
2401 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2402 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002403 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002404 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002405
2406 Operands.push_back(
2407 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2408 return false;
2409}
2410
2411/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2412/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002413OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002414AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002415 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002416 const AsmToken &Tok = Parser.getTok();
2417 std::string LowerID = Tok.getString().lower();
2418 AArch64_AM::ShiftExtendType ShOp =
2419 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2420 .Case("lsl", AArch64_AM::LSL)
2421 .Case("lsr", AArch64_AM::LSR)
2422 .Case("asr", AArch64_AM::ASR)
2423 .Case("ror", AArch64_AM::ROR)
2424 .Case("msl", AArch64_AM::MSL)
2425 .Case("uxtb", AArch64_AM::UXTB)
2426 .Case("uxth", AArch64_AM::UXTH)
2427 .Case("uxtw", AArch64_AM::UXTW)
2428 .Case("uxtx", AArch64_AM::UXTX)
2429 .Case("sxtb", AArch64_AM::SXTB)
2430 .Case("sxth", AArch64_AM::SXTH)
2431 .Case("sxtw", AArch64_AM::SXTW)
2432 .Case("sxtx", AArch64_AM::SXTX)
2433 .Default(AArch64_AM::InvalidShiftExtend);
2434
2435 if (ShOp == AArch64_AM::InvalidShiftExtend)
2436 return MatchOperand_NoMatch;
2437
2438 SMLoc S = Tok.getLoc();
2439 Parser.Lex();
2440
Nirav Davee833c6c2016-11-08 18:31:04 +00002441 bool Hash = parseOptionalToken(AsmToken::Hash);
2442
Tim Northover3b0846e2014-05-24 12:50:23 +00002443 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2444 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2445 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2446 ShOp == AArch64_AM::MSL) {
2447 // We expect a number here.
2448 TokError("expected #imm after shift specifier");
2449 return MatchOperand_ParseFail;
2450 }
2451
Chad Rosier2ff37b82016-12-27 16:58:09 +00002452 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002453 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2454 Operands.push_back(
2455 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2456 return MatchOperand_Success;
2457 }
2458
Chad Rosier2ff37b82016-12-27 16:58:09 +00002459 // Make sure we do actually have a number, identifier or a parenthesized
2460 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002461 SMLoc E = Parser.getTok().getLoc();
2462 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002463 !Parser.getTok().is(AsmToken::LParen) &&
2464 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002465 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002466 return MatchOperand_ParseFail;
2467 }
2468
2469 const MCExpr *ImmVal;
2470 if (getParser().parseExpression(ImmVal))
2471 return MatchOperand_ParseFail;
2472
2473 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2474 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002475 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002476 return MatchOperand_ParseFail;
2477 }
2478
Jim Grosbach57fd2622014-09-23 22:16:02 +00002479 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002480 Operands.push_back(AArch64Operand::CreateShiftExtend(
2481 ShOp, MCE->getValue(), true, S, E, getContext()));
2482 return MatchOperand_Success;
2483}
2484
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002485static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2486 if (FBS[AArch64::HasV8_1aOps])
2487 Str += "ARMv8.1a";
2488 else if (FBS[AArch64::HasV8_2aOps])
2489 Str += "ARMv8.2a";
2490 else
2491 Str += "(unknown)";
2492}
2493
2494void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2495 SMLoc S) {
2496 const uint16_t Op2 = Encoding & 7;
2497 const uint16_t Cm = (Encoding & 0x78) >> 3;
2498 const uint16_t Cn = (Encoding & 0x780) >> 7;
2499 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2500
2501 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2502
2503 Operands.push_back(
2504 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2505 Operands.push_back(
2506 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2507 Operands.push_back(
2508 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2509 Expr = MCConstantExpr::create(Op2, getContext());
2510 Operands.push_back(
2511 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2512}
2513
Tim Northover3b0846e2014-05-24 12:50:23 +00002514/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2515/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2516bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2517 OperandVector &Operands) {
2518 if (Name.find('.') != StringRef::npos)
2519 return TokError("invalid operand");
2520
2521 Mnemonic = Name;
2522 Operands.push_back(
2523 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2524
Rafael Espindola961d4692014-11-11 05:18:41 +00002525 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002526 const AsmToken &Tok = Parser.getTok();
2527 StringRef Op = Tok.getString();
2528 SMLoc S = Tok.getLoc();
2529
Tim Northover3b0846e2014-05-24 12:50:23 +00002530 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002531 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2532 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002533 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002534 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2535 std::string Str("IC " + std::string(IC->Name) + " requires ");
2536 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2537 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002538 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002539 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002540 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002541 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2542 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002543 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002544 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2545 std::string Str("DC " + std::string(DC->Name) + " requires ");
2546 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2547 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002548 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002549 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002550 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002551 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2552 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002553 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002554 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2555 std::string Str("AT " + std::string(AT->Name) + " requires ");
2556 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2557 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002558 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002559 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002560 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002561 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2562 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002563 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002564 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2565 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2566 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2567 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002568 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002569 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002570 }
2571
Tim Northover3b0846e2014-05-24 12:50:23 +00002572 Parser.Lex(); // Eat operand.
2573
2574 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2575 bool HasRegister = false;
2576
2577 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002578 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002579 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2580 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002581 HasRegister = true;
2582 }
2583
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002584 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002585 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002586 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002587 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002588
Nirav Davee833c6c2016-11-08 18:31:04 +00002589 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2590 return true;
2591
Tim Northover3b0846e2014-05-24 12:50:23 +00002592 return false;
2593}
2594
Alex Bradbury58eba092016-11-01 16:32:05 +00002595OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002596AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002597 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002598 const AsmToken &Tok = Parser.getTok();
2599
2600 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002601 if (parseOptionalToken(AsmToken::Hash) ||
2602 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002603 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002604 const MCExpr *ImmVal;
2605 SMLoc ExprLoc = getLoc();
2606 if (getParser().parseExpression(ImmVal))
2607 return MatchOperand_ParseFail;
2608 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2609 if (!MCE) {
2610 Error(ExprLoc, "immediate value expected for barrier operand");
2611 return MatchOperand_ParseFail;
2612 }
2613 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2614 Error(ExprLoc, "barrier operand out of range");
2615 return MatchOperand_ParseFail;
2616 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002617 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2618 Operands.push_back(AArch64Operand::CreateBarrier(
2619 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002620 return MatchOperand_Success;
2621 }
2622
2623 if (Tok.isNot(AsmToken::Identifier)) {
2624 TokError("invalid operand for instruction");
2625 return MatchOperand_ParseFail;
2626 }
2627
Tim Northover3b0846e2014-05-24 12:50:23 +00002628 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002629 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2630 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002631 TokError("'sy' or #imm operand expected");
2632 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002633 } else if (!DB) {
2634 TokError("invalid barrier option name");
2635 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002636 }
2637
Tim Northovere6ae6762016-07-05 21:23:04 +00002638 Operands.push_back(AArch64Operand::CreateBarrier(
2639 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002640 Parser.Lex(); // Consume the option
2641
2642 return MatchOperand_Success;
2643}
2644
Alex Bradbury58eba092016-11-01 16:32:05 +00002645OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002646AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002647 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002648 const AsmToken &Tok = Parser.getTok();
2649
2650 if (Tok.isNot(AsmToken::Identifier))
2651 return MatchOperand_NoMatch;
2652
Tim Northovere6ae6762016-07-05 21:23:04 +00002653 int MRSReg, MSRReg;
2654 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2655 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2656 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2657 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2658 } else
2659 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002660
Tim Northovere6ae6762016-07-05 21:23:04 +00002661 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2662 unsigned PStateImm = -1;
2663 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2664 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002665
Tim Northovere6ae6762016-07-05 21:23:04 +00002666 Operands.push_back(
2667 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2668 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002669 Parser.Lex(); // Eat identifier
2670
2671 return MatchOperand_Success;
2672}
2673
Florian Hahnc4422242017-11-07 13:07:50 +00002674/// tryParseNeonVectorRegister - Parse a vector register operand.
2675bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002676 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002677 if (Parser.getTok().isNot(AsmToken::Identifier))
2678 return true;
2679
2680 SMLoc S = getLoc();
2681 // Check for a vector register specifier first.
2682 StringRef Kind;
2683 int64_t Reg = tryMatchVectorRegister(Kind, false);
2684 if (Reg == -1)
2685 return true;
2686 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00002687 AArch64Operand::CreateReg(Reg, RegKind::NeonVector, S, getLoc(),
2688 getContext()));
2689
Tim Northover3b0846e2014-05-24 12:50:23 +00002690 // If there was an explicit qualifier, that goes on as a literal text
2691 // operand.
2692 if (!Kind.empty())
2693 Operands.push_back(
2694 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2695
2696 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002697 SMLoc SIdx = getLoc();
2698 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002699 const MCExpr *ImmVal;
2700 if (getParser().parseExpression(ImmVal))
2701 return false;
2702 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2703 if (!MCE) {
2704 TokError("immediate value expected for vector index");
2705 return false;
2706 }
2707
2708 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002709
Nirav Davee833c6c2016-11-08 18:31:04 +00002710 if (parseToken(AsmToken::RBrac, "']' expected"))
2711 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002712
2713 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2714 E, getContext()));
2715 }
2716
2717 return false;
2718}
2719
Florian Hahn91f11e52017-11-07 16:45:48 +00002720// tryParseSVEDataVectorRegister - Try to parse a SVE vector register name with
2721// optional kind specifier. If it is a register specifier, eat the token
2722// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002723OperandMatchResultTy
2724AArch64AsmParser::tryParseSVERegister(int &Reg, StringRef &Kind,
2725 RegKind MatchKind) {
2726 MCAsmParser &Parser = getParser();
2727 const AsmToken &Tok = Parser.getTok();
2728
Florian Hahn91f11e52017-11-07 16:45:48 +00002729 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002730 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002731
2732 StringRef Name = Tok.getString();
2733 // If there is a kind specifier, it's separated from the register name by
2734 // a '.'.
2735 size_t Start = 0, Next = Name.find('.');
2736 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002737 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002738
2739 if (RegNum) {
2740 if (Next != StringRef::npos) {
2741 Kind = Name.slice(Next, StringRef::npos);
2742 if (!isValidSVEKind(Kind)) {
2743 TokError("invalid sve vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002744 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002745 }
2746 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002747 Parser.Lex(); // Eat the register token.
2748
2749 Reg = RegNum;
2750 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002751 }
2752
Sander de Smalen8e607342017-11-15 15:44:43 +00002753 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002754}
2755
Sander de Smalencd6be962017-12-20 11:02:42 +00002756/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2757OperandMatchResultTy
2758AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2759 // Check for a SVE predicate register specifier first.
2760 const SMLoc S = getLoc();
2761 StringRef Kind;
2762 int RegNum = -1;
2763 auto Res = tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
2764 if (Res != MatchOperand_Success)
2765 return Res;
2766
2767 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
2768 .Case("", -1)
2769 .Case(".b", 8)
2770 .Case(".h", 16)
2771 .Case(".s", 32)
2772 .Case(".d", 64)
2773 .Case(".q", 128)
2774 .Default(0);
2775
2776 if (!ElementWidth)
2777 return MatchOperand_NoMatch;
2778
2779 Operands.push_back(
2780 AArch64Operand::CreateReg(RegNum, RegKind::SVEPredicateVector,
2781 ElementWidth, S, getLoc(), getContext()));
2782
Sander de Smalen7868e742018-01-09 11:17:06 +00002783 // Not all predicates are followed by a '/m' or '/z'.
2784 MCAsmParser &Parser = getParser();
2785 if (Parser.getTok().isNot(AsmToken::Slash))
2786 return MatchOperand_Success;
2787
2788 // But when they do they shouldn't have an element type suffix.
2789 if (!Kind.empty()) {
2790 Error(S, "not expecting size suffix");
2791 return MatchOperand_ParseFail;
2792 }
2793
2794 // Add a literal slash as operand
2795 Operands.push_back(
2796 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2797
2798 Parser.Lex(); // Eat the slash.
2799
2800 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002801 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002802 if (Pred != "z" && Pred != "m") {
2803 Error(getLoc(), "expecting 'm' or 'z' predication");
2804 return MatchOperand_ParseFail;
2805 }
2806
2807 // Add zero/merge token.
2808 const char *ZM = Pred == "z" ? "z" : "m";
2809 Operands.push_back(
2810 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2811
2812 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002813 return MatchOperand_Success;
2814}
2815
Tim Northover3b0846e2014-05-24 12:50:23 +00002816/// parseRegister - Parse a non-vector register operand.
2817bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2818 SMLoc S = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00002819 // Try for a vector (neon) register.
2820 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002821 return false;
2822
2823 // Try for a scalar register.
2824 int64_t Reg = tryParseRegister();
2825 if (Reg == -1)
2826 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002827 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2828 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002829
Tim Northover3b0846e2014-05-24 12:50:23 +00002830 return false;
2831}
2832
2833bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002834 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002835 bool HasELFModifier = false;
2836 AArch64MCExpr::VariantKind RefKind;
2837
Nirav Davee833c6c2016-11-08 18:31:04 +00002838 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002839 HasELFModifier = true;
2840
Nirav Davee833c6c2016-11-08 18:31:04 +00002841 if (Parser.getTok().isNot(AsmToken::Identifier))
2842 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002843
2844 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2845 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2846 .Case("lo12", AArch64MCExpr::VK_LO12)
2847 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2848 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2849 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2850 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2851 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2852 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2853 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2854 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2855 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2856 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2857 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2858 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2859 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2860 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2861 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2862 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2863 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2864 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2865 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2866 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2867 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2868 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2869 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2870 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2871 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2872 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2873 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2874 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2875 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2876 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2877 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2878 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2879 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2880 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2881 .Default(AArch64MCExpr::VK_INVALID);
2882
Nirav Davee833c6c2016-11-08 18:31:04 +00002883 if (RefKind == AArch64MCExpr::VK_INVALID)
2884 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002885
2886 Parser.Lex(); // Eat identifier
2887
Nirav Davee833c6c2016-11-08 18:31:04 +00002888 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002889 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002890 }
2891
2892 if (getParser().parseExpression(ImmVal))
2893 return true;
2894
2895 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002896 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002897
2898 return false;
2899}
2900
2901/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2902bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002903 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002904 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2905 SMLoc S = getLoc();
2906 Parser.Lex(); // Eat left bracket token.
2907 StringRef Kind;
2908 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2909 if (FirstReg == -1)
2910 return true;
2911 int64_t PrevReg = FirstReg;
2912 unsigned Count = 1;
2913
Nirav Davee833c6c2016-11-08 18:31:04 +00002914 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002915 SMLoc Loc = getLoc();
2916 StringRef NextKind;
2917 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2918 if (Reg == -1)
2919 return true;
2920 // Any Kind suffices must match on all regs in the list.
2921 if (Kind != NextKind)
2922 return Error(Loc, "mismatched register size suffix");
2923
2924 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2925
2926 if (Space == 0 || Space > 3) {
2927 return Error(Loc, "invalid number of vectors");
2928 }
2929
2930 Count += Space;
2931 }
2932 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002933 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002934 SMLoc Loc = getLoc();
2935 StringRef NextKind;
2936 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2937 if (Reg == -1)
2938 return true;
2939 // Any Kind suffices must match on all regs in the list.
2940 if (Kind != NextKind)
2941 return Error(Loc, "mismatched register size suffix");
2942
2943 // Registers must be incremental (with wraparound at 31)
2944 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2945 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2946 return Error(Loc, "registers must be sequential");
2947
2948 PrevReg = Reg;
2949 ++Count;
2950 }
2951 }
2952
Nirav Davee833c6c2016-11-08 18:31:04 +00002953 if (parseToken(AsmToken::RCurly, "'}' expected"))
2954 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002955
2956 if (Count > 4)
2957 return Error(S, "invalid number of vectors");
2958
2959 unsigned NumElements = 0;
2960 char ElementKind = 0;
2961 if (!Kind.empty())
2962 parseValidVectorKind(Kind, NumElements, ElementKind);
2963
2964 Operands.push_back(AArch64Operand::CreateVectorList(
2965 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
2966
2967 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002968 SMLoc SIdx = getLoc();
2969 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002970 const MCExpr *ImmVal;
2971 if (getParser().parseExpression(ImmVal))
2972 return false;
2973 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2974 if (!MCE) {
2975 TokError("immediate value expected for vector index");
2976 return false;
2977 }
2978
2979 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002980 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002981 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002982
2983 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2984 E, getContext()));
2985 }
2986 return false;
2987}
2988
Alex Bradbury58eba092016-11-01 16:32:05 +00002989OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002990AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002991 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002992 const AsmToken &Tok = Parser.getTok();
2993 if (!Tok.is(AsmToken::Identifier))
2994 return MatchOperand_NoMatch;
2995
Florian Hahnc4422242017-11-07 13:07:50 +00002996 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00002997
2998 MCContext &Ctx = getContext();
2999 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
3000 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
3001 return MatchOperand_NoMatch;
3002
3003 SMLoc S = getLoc();
3004 Parser.Lex(); // Eat register
3005
Nirav Davee833c6c2016-11-08 18:31:04 +00003006 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003007 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003008 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003009 return MatchOperand_Success;
3010 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003011
Nirav Davee833c6c2016-11-08 18:31:04 +00003012 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003013
3014 if (Parser.getTok().isNot(AsmToken::Integer)) {
3015 Error(getLoc(), "index must be absent or #0");
3016 return MatchOperand_ParseFail;
3017 }
3018
3019 const MCExpr *ImmVal;
3020 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3021 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3022 Error(getLoc(), "index must be absent or #0");
3023 return MatchOperand_ParseFail;
3024 }
3025
3026 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003027 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003028 return MatchOperand_Success;
3029}
3030
3031/// parseOperand - Parse a arm instruction operand. For now this parses the
3032/// operand regardless of the mnemonic.
3033bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3034 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003035 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003036
3037 OperandMatchResultTy ResTy =
3038 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3039
Tim Northover3b0846e2014-05-24 12:50:23 +00003040 // Check if the current operand has a custom associated parser, if so, try to
3041 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003042 if (ResTy == MatchOperand_Success)
3043 return false;
3044 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3045 // there was a match, but an error occurred, in which case, just return that
3046 // the operand parsing failed.
3047 if (ResTy == MatchOperand_ParseFail)
3048 return true;
3049
3050 // Nothing custom, so do general case parsing.
3051 SMLoc S, E;
3052 switch (getLexer().getKind()) {
3053 default: {
3054 SMLoc S = getLoc();
3055 const MCExpr *Expr;
3056 if (parseSymbolicImmVal(Expr))
3057 return Error(S, "invalid operand");
3058
3059 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3060 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3061 return false;
3062 }
3063 case AsmToken::LBrac: {
3064 SMLoc Loc = Parser.getTok().getLoc();
3065 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3066 getContext()));
3067 Parser.Lex(); // Eat '['
3068
3069 // There's no comma after a '[', so we can parse the next operand
3070 // immediately.
3071 return parseOperand(Operands, false, false);
3072 }
3073 case AsmToken::LCurly:
3074 return parseVectorList(Operands);
3075 case AsmToken::Identifier: {
3076 // If we're expecting a Condition Code operand, then just parse that.
3077 if (isCondCode)
3078 return parseCondCode(Operands, invertCondCode);
3079
3080 // If it's a register name, parse it.
3081 if (!parseRegister(Operands))
3082 return false;
3083
3084 // This could be an optional "shift" or "extend" operand.
3085 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3086 // We can only continue if no tokens were eaten.
3087 if (GotShift != MatchOperand_NoMatch)
3088 return GotShift;
3089
3090 // This was not a register so parse other operands that start with an
3091 // identifier (like labels) as expressions and create them as immediates.
3092 const MCExpr *IdVal;
3093 S = getLoc();
3094 if (getParser().parseExpression(IdVal))
3095 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003096 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3097 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3098 return false;
3099 }
3100 case AsmToken::Integer:
3101 case AsmToken::Real:
3102 case AsmToken::Hash: {
3103 // #42 -> immediate.
3104 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003105
3106 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003107
3108 // Parse a negative sign
3109 bool isNegative = false;
3110 if (Parser.getTok().is(AsmToken::Minus)) {
3111 isNegative = true;
3112 // We need to consume this token only when we have a Real, otherwise
3113 // we let parseSymbolicImmVal take care of it
3114 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3115 Parser.Lex();
3116 }
3117
3118 // The only Real that should come through here is a literal #0.0 for
3119 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3120 // so convert the value.
3121 const AsmToken &Tok = Parser.getTok();
3122 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003123 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003124 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3125 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3126 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3127 Mnemonic != "fcmlt")
3128 return TokError("unexpected floating point literal");
3129 else if (IntVal != 0 || isNegative)
3130 return TokError("expected floating-point constant #0.0");
3131 Parser.Lex(); // Eat the token.
3132
3133 Operands.push_back(
3134 AArch64Operand::CreateToken("#0", false, S, getContext()));
3135 Operands.push_back(
3136 AArch64Operand::CreateToken(".0", false, S, getContext()));
3137 return false;
3138 }
3139
3140 const MCExpr *ImmVal;
3141 if (parseSymbolicImmVal(ImmVal))
3142 return true;
3143
3144 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3145 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3146 return false;
3147 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003148 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003149 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003150 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003151 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003152 Parser.Lex(); // Eat '='
3153 const MCExpr *SubExprVal;
3154 if (getParser().parseExpression(SubExprVal))
3155 return true;
3156
David Peixottoae5ba762014-07-18 16:05:14 +00003157 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003158 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003159 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003160
3161 bool IsXReg =
3162 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3163 Operands[1]->getReg());
3164
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003165 MCContext& Ctx = getContext();
3166 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3167 // 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 +00003168 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003169 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3170 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3171 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3172 ShiftAmt += 16;
3173 Imm >>= 16;
3174 }
3175 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3176 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3177 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003178 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003179 if (ShiftAmt)
3180 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3181 ShiftAmt, true, S, E, Ctx));
3182 return false;
3183 }
David Peixottoae5ba762014-07-18 16:05:14 +00003184 APInt Simm = APInt(64, Imm << ShiftAmt);
3185 // check if the immediate is an unsigned or signed 32-bit int for W regs
3186 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3187 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003188 }
3189 // 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 +00003190 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003191 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003192 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3193 return false;
3194 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003195 }
3196}
3197
3198/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3199/// operands.
3200bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3201 StringRef Name, SMLoc NameLoc,
3202 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003203 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003204 Name = StringSwitch<StringRef>(Name.lower())
3205 .Case("beq", "b.eq")
3206 .Case("bne", "b.ne")
3207 .Case("bhs", "b.hs")
3208 .Case("bcs", "b.cs")
3209 .Case("blo", "b.lo")
3210 .Case("bcc", "b.cc")
3211 .Case("bmi", "b.mi")
3212 .Case("bpl", "b.pl")
3213 .Case("bvs", "b.vs")
3214 .Case("bvc", "b.vc")
3215 .Case("bhi", "b.hi")
3216 .Case("bls", "b.ls")
3217 .Case("bge", "b.ge")
3218 .Case("blt", "b.lt")
3219 .Case("bgt", "b.gt")
3220 .Case("ble", "b.le")
3221 .Case("bal", "b.al")
3222 .Case("bnv", "b.nv")
3223 .Default(Name);
3224
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003225 // First check for the AArch64-specific .req directive.
3226 if (Parser.getTok().is(AsmToken::Identifier) &&
3227 Parser.getTok().getIdentifier() == ".req") {
3228 parseDirectiveReq(Name, NameLoc);
3229 // We always return 'error' for this, as we're done with this
3230 // statement and don't need to match the 'instruction."
3231 return true;
3232 }
3233
Tim Northover3b0846e2014-05-24 12:50:23 +00003234 // Create the leading tokens for the mnemonic, split by '.' characters.
3235 size_t Start = 0, Next = Name.find('.');
3236 StringRef Head = Name.slice(Start, Next);
3237
3238 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003239 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3240 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003241
3242 Operands.push_back(
3243 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3244 Mnemonic = Head;
3245
3246 // Handle condition codes for a branch mnemonic
3247 if (Head == "b" && Next != StringRef::npos) {
3248 Start = Next;
3249 Next = Name.find('.', Start + 1);
3250 Head = Name.slice(Start + 1, Next);
3251
3252 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3253 (Head.data() - Name.data()));
3254 AArch64CC::CondCode CC = parseCondCodeString(Head);
3255 if (CC == AArch64CC::Invalid)
3256 return Error(SuffixLoc, "invalid condition code");
3257 Operands.push_back(
3258 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3259 Operands.push_back(
3260 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3261 }
3262
3263 // Add the remaining tokens in the mnemonic.
3264 while (Next != StringRef::npos) {
3265 Start = Next;
3266 Next = Name.find('.', Start + 1);
3267 Head = Name.slice(Start, Next);
3268 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3269 (Head.data() - Name.data()) + 1);
3270 Operands.push_back(
3271 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3272 }
3273
3274 // Conditional compare instructions have a Condition Code operand, which needs
3275 // to be parsed and an immediate operand created.
3276 bool condCodeFourthOperand =
3277 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3278 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3279 Head == "csinc" || Head == "csinv" || Head == "csneg");
3280
3281 // These instructions are aliases to some of the conditional select
3282 // instructions. However, the condition code is inverted in the aliased
3283 // instruction.
3284 //
3285 // FIXME: Is this the correct way to handle these? Or should the parser
3286 // generate the aliased instructions directly?
3287 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3288 bool condCodeThirdOperand =
3289 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3290
3291 // Read the remaining operands.
3292 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3293 // Read the first operand.
3294 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003295 return true;
3296 }
3297
3298 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003299 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003300 // Parse and remember the operand.
3301 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3302 (N == 3 && condCodeThirdOperand) ||
3303 (N == 2 && condCodeSecondOperand),
3304 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003305 return true;
3306 }
3307
3308 // After successfully parsing some operands there are two special cases to
3309 // consider (i.e. notional operands not separated by commas). Both are due
3310 // to memory specifiers:
3311 // + An RBrac will end an address for load/store/prefetch
3312 // + An '!' will indicate a pre-indexed operation.
3313 //
3314 // It's someone else's responsibility to make sure these tokens are sane
3315 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003316
Nirav Davee833c6c2016-11-08 18:31:04 +00003317 SMLoc RLoc = Parser.getTok().getLoc();
3318 if (parseOptionalToken(AsmToken::RBrac))
3319 Operands.push_back(
3320 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3321 SMLoc ELoc = Parser.getTok().getLoc();
3322 if (parseOptionalToken(AsmToken::Exclaim))
3323 Operands.push_back(
3324 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003325
3326 ++N;
3327 }
3328 }
3329
Nirav Davee833c6c2016-11-08 18:31:04 +00003330 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3331 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003332
Tim Northover3b0846e2014-05-24 12:50:23 +00003333 return false;
3334}
3335
3336// FIXME: This entire function is a giant hack to provide us with decent
3337// operand range validation/diagnostics until TableGen/MC can be extended
3338// to support autogeneration of this kind of validation.
3339bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3340 SmallVectorImpl<SMLoc> &Loc) {
3341 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3342 // Check for indexed addressing modes w/ the base register being the
3343 // same as a destination/source register or pair load where
3344 // the Rt == Rt2. All of those are undefined behaviour.
3345 switch (Inst.getOpcode()) {
3346 case AArch64::LDPSWpre:
3347 case AArch64::LDPWpost:
3348 case AArch64::LDPWpre:
3349 case AArch64::LDPXpost:
3350 case AArch64::LDPXpre: {
3351 unsigned Rt = Inst.getOperand(1).getReg();
3352 unsigned Rt2 = Inst.getOperand(2).getReg();
3353 unsigned Rn = Inst.getOperand(3).getReg();
3354 if (RI->isSubRegisterEq(Rn, Rt))
3355 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3356 "is also a destination");
3357 if (RI->isSubRegisterEq(Rn, Rt2))
3358 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3359 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003360 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003361 }
3362 case AArch64::LDPDi:
3363 case AArch64::LDPQi:
3364 case AArch64::LDPSi:
3365 case AArch64::LDPSWi:
3366 case AArch64::LDPWi:
3367 case AArch64::LDPXi: {
3368 unsigned Rt = Inst.getOperand(0).getReg();
3369 unsigned Rt2 = Inst.getOperand(1).getReg();
3370 if (Rt == Rt2)
3371 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3372 break;
3373 }
3374 case AArch64::LDPDpost:
3375 case AArch64::LDPDpre:
3376 case AArch64::LDPQpost:
3377 case AArch64::LDPQpre:
3378 case AArch64::LDPSpost:
3379 case AArch64::LDPSpre:
3380 case AArch64::LDPSWpost: {
3381 unsigned Rt = Inst.getOperand(1).getReg();
3382 unsigned Rt2 = Inst.getOperand(2).getReg();
3383 if (Rt == Rt2)
3384 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3385 break;
3386 }
3387 case AArch64::STPDpost:
3388 case AArch64::STPDpre:
3389 case AArch64::STPQpost:
3390 case AArch64::STPQpre:
3391 case AArch64::STPSpost:
3392 case AArch64::STPSpre:
3393 case AArch64::STPWpost:
3394 case AArch64::STPWpre:
3395 case AArch64::STPXpost:
3396 case AArch64::STPXpre: {
3397 unsigned Rt = Inst.getOperand(1).getReg();
3398 unsigned Rt2 = Inst.getOperand(2).getReg();
3399 unsigned Rn = Inst.getOperand(3).getReg();
3400 if (RI->isSubRegisterEq(Rn, Rt))
3401 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3402 "is also a source");
3403 if (RI->isSubRegisterEq(Rn, Rt2))
3404 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3405 "is also a source");
3406 break;
3407 }
3408 case AArch64::LDRBBpre:
3409 case AArch64::LDRBpre:
3410 case AArch64::LDRHHpre:
3411 case AArch64::LDRHpre:
3412 case AArch64::LDRSBWpre:
3413 case AArch64::LDRSBXpre:
3414 case AArch64::LDRSHWpre:
3415 case AArch64::LDRSHXpre:
3416 case AArch64::LDRSWpre:
3417 case AArch64::LDRWpre:
3418 case AArch64::LDRXpre:
3419 case AArch64::LDRBBpost:
3420 case AArch64::LDRBpost:
3421 case AArch64::LDRHHpost:
3422 case AArch64::LDRHpost:
3423 case AArch64::LDRSBWpost:
3424 case AArch64::LDRSBXpost:
3425 case AArch64::LDRSHWpost:
3426 case AArch64::LDRSHXpost:
3427 case AArch64::LDRSWpost:
3428 case AArch64::LDRWpost:
3429 case AArch64::LDRXpost: {
3430 unsigned Rt = Inst.getOperand(1).getReg();
3431 unsigned Rn = Inst.getOperand(2).getReg();
3432 if (RI->isSubRegisterEq(Rn, Rt))
3433 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3434 "is also a source");
3435 break;
3436 }
3437 case AArch64::STRBBpost:
3438 case AArch64::STRBpost:
3439 case AArch64::STRHHpost:
3440 case AArch64::STRHpost:
3441 case AArch64::STRWpost:
3442 case AArch64::STRXpost:
3443 case AArch64::STRBBpre:
3444 case AArch64::STRBpre:
3445 case AArch64::STRHHpre:
3446 case AArch64::STRHpre:
3447 case AArch64::STRWpre:
3448 case AArch64::STRXpre: {
3449 unsigned Rt = Inst.getOperand(1).getReg();
3450 unsigned Rn = Inst.getOperand(2).getReg();
3451 if (RI->isSubRegisterEq(Rn, Rt))
3452 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3453 "is also a source");
3454 break;
3455 }
3456 }
3457
3458 // Now check immediate ranges. Separate from the above as there is overlap
3459 // in the instructions being checked and this keeps the nested conditionals
3460 // to a minimum.
3461 switch (Inst.getOpcode()) {
3462 case AArch64::ADDSWri:
3463 case AArch64::ADDSXri:
3464 case AArch64::ADDWri:
3465 case AArch64::ADDXri:
3466 case AArch64::SUBSWri:
3467 case AArch64::SUBSXri:
3468 case AArch64::SUBWri:
3469 case AArch64::SUBXri: {
3470 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3471 // some slight duplication here.
3472 if (Inst.getOperand(2).isExpr()) {
3473 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3474 AArch64MCExpr::VariantKind ELFRefKind;
3475 MCSymbolRefExpr::VariantKind DarwinRefKind;
3476 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003477 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3478
3479 // Only allow these with ADDXri.
3480 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3481 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3482 Inst.getOpcode() == AArch64::ADDXri)
3483 return false;
3484
3485 // Only allow these with ADDXri/ADDWri
3486 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3487 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3488 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3489 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3490 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3491 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3492 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3493 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3494 (Inst.getOpcode() == AArch64::ADDXri ||
3495 Inst.getOpcode() == AArch64::ADDWri))
3496 return false;
3497
3498 // Don't allow symbol refs in the immediate field otherwise
3499 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3500 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3501 // 'cmp w0, 'borked')
3502 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003503 }
Diana Picusc93518d2016-10-11 09:17:47 +00003504 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003505 }
3506 return false;
3507 }
3508 default:
3509 return false;
3510 }
3511}
3512
Craig Topper05515562017-10-26 06:46:41 +00003513static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3514 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003515
3516bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3517 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003518 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003519 case Match_InvalidTiedOperand:
3520 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003521 case Match_MissingFeature:
3522 return Error(Loc,
3523 "instruction requires a CPU feature not currently enabled");
3524 case Match_InvalidOperand:
3525 return Error(Loc, "invalid operand for instruction");
3526 case Match_InvalidSuffix:
3527 return Error(Loc, "invalid type suffix for instruction");
3528 case Match_InvalidCondCode:
3529 return Error(Loc, "expected AArch64 condition code");
3530 case Match_AddSubRegExtendSmall:
3531 return Error(Loc,
3532 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3533 case Match_AddSubRegExtendLarge:
3534 return Error(Loc,
3535 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3536 case Match_AddSubSecondSource:
3537 return Error(Loc,
3538 "expected compatible register, symbol or integer in range [0, 4095]");
3539 case Match_LogicalSecondSource:
3540 return Error(Loc, "expected compatible register or logical immediate");
3541 case Match_InvalidMovImm32Shift:
3542 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3543 case Match_InvalidMovImm64Shift:
3544 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3545 case Match_AddSubRegShift32:
3546 return Error(Loc,
3547 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3548 case Match_AddSubRegShift64:
3549 return Error(Loc,
3550 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3551 case Match_InvalidFPImm:
3552 return Error(Loc,
3553 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003554 case Match_InvalidMemoryIndexedSImm6:
3555 return Error(Loc, "index must be an integer in range [-32, 31].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003556 case Match_InvalidMemoryIndexedSImm9:
3557 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003558 case Match_InvalidMemoryIndexedSImm10:
3559 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003560 case Match_InvalidMemoryIndexed4SImm7:
3561 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3562 case Match_InvalidMemoryIndexed8SImm7:
3563 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3564 case Match_InvalidMemoryIndexed16SImm7:
3565 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3566 case Match_InvalidMemoryWExtend8:
3567 return Error(Loc,
3568 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3569 case Match_InvalidMemoryWExtend16:
3570 return Error(Loc,
3571 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3572 case Match_InvalidMemoryWExtend32:
3573 return Error(Loc,
3574 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3575 case Match_InvalidMemoryWExtend64:
3576 return Error(Loc,
3577 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3578 case Match_InvalidMemoryWExtend128:
3579 return Error(Loc,
3580 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3581 case Match_InvalidMemoryXExtend8:
3582 return Error(Loc,
3583 "expected 'lsl' or 'sxtx' with optional shift of #0");
3584 case Match_InvalidMemoryXExtend16:
3585 return Error(Loc,
3586 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3587 case Match_InvalidMemoryXExtend32:
3588 return Error(Loc,
3589 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3590 case Match_InvalidMemoryXExtend64:
3591 return Error(Loc,
3592 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3593 case Match_InvalidMemoryXExtend128:
3594 return Error(Loc,
3595 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3596 case Match_InvalidMemoryIndexed1:
3597 return Error(Loc, "index must be an integer in range [0, 4095].");
3598 case Match_InvalidMemoryIndexed2:
3599 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3600 case Match_InvalidMemoryIndexed4:
3601 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3602 case Match_InvalidMemoryIndexed8:
3603 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3604 case Match_InvalidMemoryIndexed16:
3605 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003606 case Match_InvalidImm0_1:
3607 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003608 case Match_InvalidImm0_7:
3609 return Error(Loc, "immediate must be an integer in range [0, 7].");
3610 case Match_InvalidImm0_15:
3611 return Error(Loc, "immediate must be an integer in range [0, 15].");
3612 case Match_InvalidImm0_31:
3613 return Error(Loc, "immediate must be an integer in range [0, 31].");
3614 case Match_InvalidImm0_63:
3615 return Error(Loc, "immediate must be an integer in range [0, 63].");
3616 case Match_InvalidImm0_127:
3617 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003618 case Match_InvalidImm0_255:
3619 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003620 case Match_InvalidImm0_65535:
3621 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3622 case Match_InvalidImm1_8:
3623 return Error(Loc, "immediate must be an integer in range [1, 8].");
3624 case Match_InvalidImm1_16:
3625 return Error(Loc, "immediate must be an integer in range [1, 16].");
3626 case Match_InvalidImm1_32:
3627 return Error(Loc, "immediate must be an integer in range [1, 32].");
3628 case Match_InvalidImm1_64:
3629 return Error(Loc, "immediate must be an integer in range [1, 64].");
3630 case Match_InvalidIndex1:
3631 return Error(Loc, "expected lane specifier '[1]'");
3632 case Match_InvalidIndexB:
3633 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3634 case Match_InvalidIndexH:
3635 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3636 case Match_InvalidIndexS:
3637 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3638 case Match_InvalidIndexD:
3639 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3640 case Match_InvalidLabel:
3641 return Error(Loc, "expected label or encodable integer pc offset");
3642 case Match_MRS:
3643 return Error(Loc, "expected readable system register");
3644 case Match_MSR:
3645 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003646 case Match_InvalidComplexRotationEven:
3647 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3648 case Match_InvalidComplexRotationOdd:
3649 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003650 case Match_MnemonicFail: {
3651 std::string Suggestion = AArch64MnemonicSpellCheck(
3652 ((AArch64Operand &)*Operands[0]).getToken(),
3653 ComputeAvailableFeatures(STI->getFeatureBits()));
3654 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3655 }
Sander de Smalencd6be962017-12-20 11:02:42 +00003656 case Match_InvalidSVEPredicateAnyReg:
3657 case Match_InvalidSVEPredicateBReg:
3658 case Match_InvalidSVEPredicateHReg:
3659 case Match_InvalidSVEPredicateSReg:
3660 case Match_InvalidSVEPredicateDReg:
3661 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003662 case Match_InvalidSVEPredicate3bAnyReg:
3663 case Match_InvalidSVEPredicate3bBReg:
3664 case Match_InvalidSVEPredicate3bHReg:
3665 case Match_InvalidSVEPredicate3bSReg:
3666 case Match_InvalidSVEPredicate3bDReg:
3667 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003668 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003669 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003670 }
3671}
3672
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003673static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003674
3675bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3676 OperandVector &Operands,
3677 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003678 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003679 bool MatchingInlineAsm) {
3680 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003681 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3682 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003683
David Blaikie960ea3f2014-06-08 16:18:35 +00003684 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003685 unsigned NumOperands = Operands.size();
3686
3687 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003688 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3689 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003690 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003691 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003692 if (Op3CE) {
3693 uint64_t Op3Val = Op3CE->getValue();
3694 uint64_t NewOp3Val = 0;
3695 uint64_t NewOp4Val = 0;
3696 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003697 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003698 NewOp3Val = (32 - Op3Val) & 0x1f;
3699 NewOp4Val = 31 - Op3Val;
3700 } else {
3701 NewOp3Val = (64 - Op3Val) & 0x3f;
3702 NewOp4Val = 63 - Op3Val;
3703 }
3704
Jim Grosbach13760bd2015-05-30 01:25:56 +00003705 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3706 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003707
3708 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003709 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003710 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003711 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3712 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3713 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003714 }
3715 }
Tim Northover03b99f62015-04-30 18:28:58 +00003716 } else if (NumOperands == 4 && Tok == "bfc") {
3717 // FIXME: Horrible hack to handle BFC->BFM alias.
3718 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3719 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3720 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3721
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003722 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003723 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3724 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3725
3726 if (LSBCE && WidthCE) {
3727 uint64_t LSB = LSBCE->getValue();
3728 uint64_t Width = WidthCE->getValue();
3729
3730 uint64_t RegWidth = 0;
3731 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3732 Op1.getReg()))
3733 RegWidth = 64;
3734 else
3735 RegWidth = 32;
3736
3737 if (LSB >= RegWidth)
3738 return Error(LSBOp.getStartLoc(),
3739 "expected integer in range [0, 31]");
3740 if (Width < 1 || Width > RegWidth)
3741 return Error(WidthOp.getStartLoc(),
3742 "expected integer in range [1, 32]");
3743
3744 uint64_t ImmR = 0;
3745 if (RegWidth == 32)
3746 ImmR = (32 - LSB) & 0x1f;
3747 else
3748 ImmR = (64 - LSB) & 0x3f;
3749
3750 uint64_t ImmS = Width - 1;
3751
3752 if (ImmR != 0 && ImmS >= ImmR)
3753 return Error(WidthOp.getStartLoc(),
3754 "requested insert overflows register");
3755
Jim Grosbach13760bd2015-05-30 01:25:56 +00003756 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3757 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003758 Operands[0] = AArch64Operand::CreateToken(
3759 "bfm", false, Op.getStartLoc(), getContext());
3760 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003761 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3762 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003763 Operands[3] = AArch64Operand::CreateImm(
3764 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3765 Operands.emplace_back(
3766 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3767 WidthOp.getEndLoc(), getContext()));
3768 }
3769 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003770 } else if (NumOperands == 5) {
3771 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3772 // UBFIZ -> UBFM aliases.
3773 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003774 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3775 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3776 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003777
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003778 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003779 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3780 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003781
3782 if (Op3CE && Op4CE) {
3783 uint64_t Op3Val = Op3CE->getValue();
3784 uint64_t Op4Val = Op4CE->getValue();
3785
3786 uint64_t RegWidth = 0;
3787 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003788 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003789 RegWidth = 64;
3790 else
3791 RegWidth = 32;
3792
3793 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003794 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003795 "expected integer in range [0, 31]");
3796 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003797 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003798 "expected integer in range [1, 32]");
3799
3800 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003801 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003802 NewOp3Val = (32 - Op3Val) & 0x1f;
3803 else
3804 NewOp3Val = (64 - Op3Val) & 0x3f;
3805
3806 uint64_t NewOp4Val = Op4Val - 1;
3807
3808 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003809 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003810 "requested insert overflows register");
3811
3812 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003813 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003814 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003815 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003816 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003817 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003818 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003819 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003820 if (Tok == "bfi")
3821 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003822 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003823 else if (Tok == "sbfiz")
3824 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003825 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003826 else if (Tok == "ubfiz")
3827 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003828 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003829 else
3830 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003831 }
3832 }
3833
3834 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3835 // UBFX -> UBFM aliases.
3836 } else if (NumOperands == 5 &&
3837 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003838 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3839 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3840 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003841
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003842 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003843 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3844 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003845
3846 if (Op3CE && Op4CE) {
3847 uint64_t Op3Val = Op3CE->getValue();
3848 uint64_t Op4Val = Op4CE->getValue();
3849
3850 uint64_t RegWidth = 0;
3851 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003852 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003853 RegWidth = 64;
3854 else
3855 RegWidth = 32;
3856
3857 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003858 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003859 "expected integer in range [0, 31]");
3860 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003861 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003862 "expected integer in range [1, 32]");
3863
3864 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3865
3866 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003867 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003868 "requested extract overflows register");
3869
3870 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003871 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003872 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003873 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003874 if (Tok == "bfxil")
3875 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003876 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003877 else if (Tok == "sbfx")
3878 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003879 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003880 else if (Tok == "ubfx")
3881 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003882 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003883 else
3884 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003885 }
3886 }
3887 }
3888 }
Tim Northover9097a072017-12-18 10:36:00 +00003889
3890 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
3891 // instruction for FP registers correctly in some rare circumstances. Convert
3892 // it to a safe instruction and warn (because silently changing someone's
3893 // assembly is rude).
3894 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
3895 NumOperands == 4 && Tok == "movi") {
3896 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3897 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3898 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3899 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
3900 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
3901 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
3902 if (Suffix.lower() == ".2d" &&
3903 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
3904 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
3905 " correctly on this CPU, converting to equivalent movi.16b");
3906 // Switch the suffix to .16b.
3907 unsigned Idx = Op1.isToken() ? 1 : 2;
3908 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
3909 getContext());
3910 }
3911 }
3912 }
3913
Tim Northover3b0846e2014-05-24 12:50:23 +00003914 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3915 // InstAlias can't quite handle this since the reg classes aren't
3916 // subclasses.
3917 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3918 // The source register can be Wn here, but the matcher expects a
3919 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003920 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003921 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003922 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003923 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3924 Op.getStartLoc(), Op.getEndLoc(),
3925 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003926 }
3927 }
3928 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3929 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003930 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003931 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003932 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003933 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003934 // The source register can be Wn here, but the matcher expects a
3935 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003936 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003937 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003938 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003939 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3940 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003941 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003942 }
3943 }
3944 }
3945 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3946 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003947 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003948 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003949 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003950 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003951 // The source register can be Wn here, but the matcher expects a
3952 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003953 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003954 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003955 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003956 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3957 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003958 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003959 }
3960 }
3961 }
3962
Tim Northover3b0846e2014-05-24 12:50:23 +00003963 MCInst Inst;
3964 // First try to match against the secondary set of tables containing the
3965 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3966 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003967 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003968
3969 // If that fails, try against the alternate table containing long-form NEON:
3970 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003971 if (MatchResult != Match_Success) {
3972 // But first, save the short-form match result: we can use it in case the
3973 // long-form match also fails.
3974 auto ShortFormNEONErrorInfo = ErrorInfo;
3975 auto ShortFormNEONMatchResult = MatchResult;
3976
Tim Northover3b0846e2014-05-24 12:50:23 +00003977 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003978 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003979
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003980 // Now, both matches failed, and the long-form match failed on the mnemonic
3981 // suffix token operand. The short-form match failure is probably more
3982 // relevant: use it instead.
3983 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003984 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003985 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3986 MatchResult = ShortFormNEONMatchResult;
3987 ErrorInfo = ShortFormNEONErrorInfo;
3988 }
3989 }
3990
Tim Northover3b0846e2014-05-24 12:50:23 +00003991 switch (MatchResult) {
3992 case Match_Success: {
3993 // Perform range checking and other semantic validations
3994 SmallVector<SMLoc, 8> OperandLocs;
3995 NumOperands = Operands.size();
3996 for (unsigned i = 1; i < NumOperands; ++i)
3997 OperandLocs.push_back(Operands[i]->getStartLoc());
3998 if (validateInstruction(Inst, OperandLocs))
3999 return true;
4000
4001 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004002 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004003 return false;
4004 }
4005 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004006 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004007 // Special case the error message for the very common case where only
4008 // a single subtarget feature is missing (neon, e.g.).
4009 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004010 uint64_t Mask = 1;
4011 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4012 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004013 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004014 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004015 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004016 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004017 }
4018 return Error(IDLoc, Msg);
4019 }
4020 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004021 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004022 case Match_InvalidOperand: {
4023 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004024
Tim Northover26bb14e2014-08-18 11:49:42 +00004025 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004026 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004027 return Error(IDLoc, "too few operands for instruction",
4028 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004029
David Blaikie960ea3f2014-06-08 16:18:35 +00004030 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004031 if (ErrorLoc == SMLoc())
4032 ErrorLoc = IDLoc;
4033 }
4034 // If the match failed on a suffix token operand, tweak the diagnostic
4035 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004036 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4037 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004038 MatchResult = Match_InvalidSuffix;
4039
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004040 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004041 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004042 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004043 case Match_InvalidMemoryIndexed1:
4044 case Match_InvalidMemoryIndexed2:
4045 case Match_InvalidMemoryIndexed4:
4046 case Match_InvalidMemoryIndexed8:
4047 case Match_InvalidMemoryIndexed16:
4048 case Match_InvalidCondCode:
4049 case Match_AddSubRegExtendSmall:
4050 case Match_AddSubRegExtendLarge:
4051 case Match_AddSubSecondSource:
4052 case Match_LogicalSecondSource:
4053 case Match_AddSubRegShift32:
4054 case Match_AddSubRegShift64:
4055 case Match_InvalidMovImm32Shift:
4056 case Match_InvalidMovImm64Shift:
4057 case Match_InvalidFPImm:
4058 case Match_InvalidMemoryWExtend8:
4059 case Match_InvalidMemoryWExtend16:
4060 case Match_InvalidMemoryWExtend32:
4061 case Match_InvalidMemoryWExtend64:
4062 case Match_InvalidMemoryWExtend128:
4063 case Match_InvalidMemoryXExtend8:
4064 case Match_InvalidMemoryXExtend16:
4065 case Match_InvalidMemoryXExtend32:
4066 case Match_InvalidMemoryXExtend64:
4067 case Match_InvalidMemoryXExtend128:
Sander de Smalen909cf952018-01-19 15:22:00 +00004068 case Match_InvalidMemoryIndexedSImm6:
Tim Northover3b0846e2014-05-24 12:50:23 +00004069 case Match_InvalidMemoryIndexed4SImm7:
4070 case Match_InvalidMemoryIndexed8SImm7:
4071 case Match_InvalidMemoryIndexed16SImm7:
4072 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004073 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004074 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004075 case Match_InvalidImm0_7:
4076 case Match_InvalidImm0_15:
4077 case Match_InvalidImm0_31:
4078 case Match_InvalidImm0_63:
4079 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004080 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004081 case Match_InvalidImm0_65535:
4082 case Match_InvalidImm1_8:
4083 case Match_InvalidImm1_16:
4084 case Match_InvalidImm1_32:
4085 case Match_InvalidImm1_64:
4086 case Match_InvalidIndex1:
4087 case Match_InvalidIndexB:
4088 case Match_InvalidIndexH:
4089 case Match_InvalidIndexS:
4090 case Match_InvalidIndexD:
4091 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004092 case Match_InvalidComplexRotationEven:
4093 case Match_InvalidComplexRotationOdd:
Sander de Smalencd6be962017-12-20 11:02:42 +00004094 case Match_InvalidSVEPredicateAnyReg:
4095 case Match_InvalidSVEPredicateBReg:
4096 case Match_InvalidSVEPredicateHReg:
4097 case Match_InvalidSVEPredicateSReg:
4098 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004099 case Match_InvalidSVEPredicate3bAnyReg:
4100 case Match_InvalidSVEPredicate3bBReg:
4101 case Match_InvalidSVEPredicate3bHReg:
4102 case Match_InvalidSVEPredicate3bSReg:
4103 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004104 case Match_MSR:
4105 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004106 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004107 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004108 // Any time we get here, there's nothing fancy to do. Just get the
4109 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004110 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004111 if (ErrorLoc == SMLoc())
4112 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004113 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004114 }
4115 }
4116
4117 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004118}
4119
4120/// ParseDirective parses the arm specific directives
4121bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004122 const MCObjectFileInfo::Environment Format =
4123 getContext().getObjectFileInfo()->getObjectFileType();
4124 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4125 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004126
Tim Northover3b0846e2014-05-24 12:50:23 +00004127 StringRef IDVal = DirectiveID.getIdentifier();
4128 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004129 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004130 parseDirectiveArch(Loc);
4131 else if (IDVal == ".cpu")
4132 parseDirectiveCPU(Loc);
4133 else if (IDVal == ".hword")
4134 parseDirectiveWord(2, Loc);
4135 else if (IDVal == ".word")
4136 parseDirectiveWord(4, Loc);
4137 else if (IDVal == ".xword")
4138 parseDirectiveWord(8, Loc);
4139 else if (IDVal == ".tlsdesccall")
4140 parseDirectiveTLSDescCall(Loc);
4141 else if (IDVal == ".ltorg" || IDVal == ".pool")
4142 parseDirectiveLtorg(Loc);
4143 else if (IDVal == ".unreq")
4144 parseDirectiveUnreq(Loc);
4145 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004146 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004147 parseDirectiveInst(Loc);
4148 else
4149 return true;
4150 } else if (IDVal == MCLOHDirectiveName())
4151 parseDirectiveLOH(IDVal, Loc);
4152 else
4153 return true;
4154 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004155}
4156
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004157static const struct {
4158 const char *Name;
4159 const FeatureBitset Features;
4160} ExtensionMap[] = {
4161 { "crc", {AArch64::FeatureCRC} },
4162 { "crypto", {AArch64::FeatureCrypto} },
4163 { "fp", {AArch64::FeatureFPARMv8} },
4164 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004165 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004166 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004167
4168 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004169 { "pan", {} },
4170 { "lor", {} },
4171 { "rdma", {} },
4172 { "profile", {} },
4173};
4174
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004175/// parseDirectiveArch
4176/// ::= .arch token
4177bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4178 SMLoc ArchLoc = getLoc();
4179
4180 StringRef Arch, ExtensionString;
4181 std::tie(Arch, ExtensionString) =
4182 getParser().parseStringToEndOfStatement().trim().split('+');
4183
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004184 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4185 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004186 return Error(ArchLoc, "unknown arch name");
4187
4188 if (parseToken(AsmToken::EndOfStatement))
4189 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004190
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004191 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004192 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004193 AArch64::getArchFeatures(ID, AArch64Features);
4194 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4195 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004196
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004197 MCSubtargetInfo &STI = copySTI();
4198 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4199 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4200
4201 SmallVector<StringRef, 4> RequestedExtensions;
4202 if (!ExtensionString.empty())
4203 ExtensionString.split(RequestedExtensions, '+');
4204
4205 FeatureBitset Features = STI.getFeatureBits();
4206 for (auto Name : RequestedExtensions) {
4207 bool EnableFeature = true;
4208
4209 if (Name.startswith_lower("no")) {
4210 EnableFeature = false;
4211 Name = Name.substr(2);
4212 }
4213
4214 for (const auto &Extension : ExtensionMap) {
4215 if (Extension.Name != Name)
4216 continue;
4217
4218 if (Extension.Features.none())
4219 report_fatal_error("unsupported architectural extension: " + Name);
4220
4221 FeatureBitset ToggleFeatures = EnableFeature
4222 ? (~Features & Extension.Features)
4223 : ( Features & Extension.Features);
4224 uint64_t Features =
4225 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4226 setAvailableFeatures(Features);
4227 break;
4228 }
4229 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004230 return false;
4231}
4232
Tim Northover8b96c7e2017-05-15 19:42:15 +00004233static SMLoc incrementLoc(SMLoc L, int Offset) {
4234 return SMLoc::getFromPointer(L.getPointer() + Offset);
4235}
4236
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004237/// parseDirectiveCPU
4238/// ::= .cpu id
4239bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004240 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004241
4242 StringRef CPU, ExtensionString;
4243 std::tie(CPU, ExtensionString) =
4244 getParser().parseStringToEndOfStatement().trim().split('+');
4245
Nirav Davee833c6c2016-11-08 18:31:04 +00004246 if (parseToken(AsmToken::EndOfStatement))
4247 return true;
4248
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004249 SmallVector<StringRef, 4> RequestedExtensions;
4250 if (!ExtensionString.empty())
4251 ExtensionString.split(RequestedExtensions, '+');
4252
4253 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4254 // once that is tablegen'ed
4255 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004256 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004257 return false;
4258 }
4259
4260 MCSubtargetInfo &STI = copySTI();
4261 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004262 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004263
4264 FeatureBitset Features = STI.getFeatureBits();
4265 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004266 // Advance source location past '+'.
4267 CurLoc = incrementLoc(CurLoc, 1);
4268
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004269 bool EnableFeature = true;
4270
4271 if (Name.startswith_lower("no")) {
4272 EnableFeature = false;
4273 Name = Name.substr(2);
4274 }
4275
Tim Northover8b96c7e2017-05-15 19:42:15 +00004276 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004277 for (const auto &Extension : ExtensionMap) {
4278 if (Extension.Name != Name)
4279 continue;
4280
4281 if (Extension.Features.none())
4282 report_fatal_error("unsupported architectural extension: " + Name);
4283
4284 FeatureBitset ToggleFeatures = EnableFeature
4285 ? (~Features & Extension.Features)
4286 : ( Features & Extension.Features);
4287 uint64_t Features =
4288 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4289 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004290 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004291
4292 break;
4293 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004294
4295 if (!FoundExtension)
4296 Error(CurLoc, "unsupported architectural extension");
4297
4298 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004299 }
4300 return false;
4301}
4302
Tim Northover3b0846e2014-05-24 12:50:23 +00004303/// parseDirectiveWord
4304/// ::= .word [ expression (, expression)* ]
4305bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004306 auto parseOp = [&]() -> bool {
4307 const MCExpr *Value;
4308 if (getParser().parseExpression(Value))
4309 return true;
4310 getParser().getStreamer().EmitValue(Value, Size, L);
4311 return false;
4312 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004313
Nirav Davee833c6c2016-11-08 18:31:04 +00004314 if (parseMany(parseOp))
4315 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004316 return false;
4317}
4318
Chad Rosierdcd2a302014-10-22 20:35:57 +00004319/// parseDirectiveInst
4320/// ::= .inst opcode [, ...]
4321bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004322 if (getLexer().is(AsmToken::EndOfStatement))
4323 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004324
Nirav Davee833c6c2016-11-08 18:31:04 +00004325 auto parseOp = [&]() -> bool {
4326 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004327 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004328 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4329 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004330 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004331 if (check(!Value, L, "expected constant expression"))
4332 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004333 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004334 return false;
4335 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004336
Nirav Davee833c6c2016-11-08 18:31:04 +00004337 if (parseMany(parseOp))
4338 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004339 return false;
4340}
4341
Tim Northover3b0846e2014-05-24 12:50:23 +00004342// parseDirectiveTLSDescCall:
4343// ::= .tlsdesccall symbol
4344bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4345 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004346 if (check(getParser().parseIdentifier(Name), L,
4347 "expected symbol after directive") ||
4348 parseToken(AsmToken::EndOfStatement))
4349 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004350
Jim Grosbach6f482002015-05-18 18:43:14 +00004351 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004352 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4353 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004354
4355 MCInst Inst;
4356 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004357 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004358
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004359 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004360 return false;
4361}
4362
4363/// ::= .loh <lohName | lohId> label1, ..., labelN
4364/// The number of arguments depends on the loh identifier.
4365bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004366 MCLOHType Kind;
4367 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4368 if (getParser().getTok().isNot(AsmToken::Integer))
4369 return TokError("expected an identifier or a number in directive");
4370 // We successfully get a numeric value for the identifier.
4371 // Check if it is valid.
4372 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004373 if (Id <= -1U && !isValidMCLOHType(Id))
4374 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004375 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004376 } else {
4377 StringRef Name = getTok().getIdentifier();
4378 // We successfully parse an identifier.
4379 // Check if it is a recognized one.
4380 int Id = MCLOHNameToId(Name);
4381
4382 if (Id == -1)
4383 return TokError("invalid identifier in directive");
4384 Kind = (MCLOHType)Id;
4385 }
4386 // Consume the identifier.
4387 Lex();
4388 // Get the number of arguments of this LOH.
4389 int NbArgs = MCLOHIdToNbArgs(Kind);
4390
4391 assert(NbArgs != -1 && "Invalid number of arguments");
4392
4393 SmallVector<MCSymbol *, 3> Args;
4394 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4395 StringRef Name;
4396 if (getParser().parseIdentifier(Name))
4397 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004398 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004399
4400 if (Idx + 1 == NbArgs)
4401 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004402 if (parseToken(AsmToken::Comma,
4403 "unexpected token in '" + Twine(IDVal) + "' directive"))
4404 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004405 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004406 if (parseToken(AsmToken::EndOfStatement,
4407 "unexpected token in '" + Twine(IDVal) + "' directive"))
4408 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004409
4410 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4411 return false;
4412}
4413
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004414/// parseDirectiveLtorg
4415/// ::= .ltorg | .pool
4416bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004417 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4418 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004419 getTargetStreamer().emitCurrentConstantPool();
4420 return false;
4421}
4422
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004423/// parseDirectiveReq
4424/// ::= name .req registername
4425bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004426 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004427 Parser.Lex(); // Eat the '.req' token.
4428 SMLoc SRegLoc = getLoc();
Sander de Smalen8e607342017-11-15 15:44:43 +00004429 int RegNum = tryParseRegister();
Florian Hahnc4422242017-11-07 13:07:50 +00004430 RegKind RegisterKind = RegKind::Scalar;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004431
Sander de Smalen8e607342017-11-15 15:44:43 +00004432 if (RegNum == -1) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004433 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004434 RegisterKind = RegKind::NeonVector;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004435 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004436 if (!Kind.empty())
4437 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004438 }
4439
Sander de Smalen8e607342017-11-15 15:44:43 +00004440 if (RegNum == -1) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004441 StringRef Kind;
4442 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen8e607342017-11-15 15:44:43 +00004443 OperandMatchResultTy Res =
4444 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4445
4446 if (Res == MatchOperand_ParseFail)
4447 return true;
4448
4449 if (Res == MatchOperand_Success && !Kind.empty())
4450 return Error(SRegLoc,
4451 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004452 }
4453
Sander de Smalencd6be962017-12-20 11:02:42 +00004454 if (RegNum == -1) {
4455 StringRef Kind;
4456 RegisterKind = RegKind::SVEPredicateVector;
4457 OperandMatchResultTy Res =
4458 tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
4459
4460 if (Res == MatchOperand_ParseFail)
4461 return true;
4462
4463 if (Res == MatchOperand_Success && !Kind.empty())
4464 return Error(SRegLoc,
4465 "sve predicate register without type specifier expected");
4466 }
4467
Sander de Smalen8e607342017-11-15 15:44:43 +00004468 if (RegNum == -1)
Nirav Dave2364748a2016-09-16 18:30:20 +00004469 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004470
4471 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004472 if (parseToken(AsmToken::EndOfStatement,
4473 "unexpected input in .req directive"))
4474 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004475
Sander de Smalen8e607342017-11-15 15:44:43 +00004476 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004477 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004478 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4479
Nirav Dave2364748a2016-09-16 18:30:20 +00004480 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004481}
4482
4483/// parseDirectiveUneq
4484/// ::= .unreq registername
4485bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004486 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004487 if (getTok().isNot(AsmToken::Identifier))
4488 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004489 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4490 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004491 if (parseToken(AsmToken::EndOfStatement))
4492 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004493 return false;
4494}
4495
Tim Northover3b0846e2014-05-24 12:50:23 +00004496bool
4497AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4498 AArch64MCExpr::VariantKind &ELFRefKind,
4499 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4500 int64_t &Addend) {
4501 ELFRefKind = AArch64MCExpr::VK_INVALID;
4502 DarwinRefKind = MCSymbolRefExpr::VK_None;
4503 Addend = 0;
4504
4505 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4506 ELFRefKind = AE->getKind();
4507 Expr = AE->getSubExpr();
4508 }
4509
4510 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4511 if (SE) {
4512 // It's a simple symbol reference with no addend.
4513 DarwinRefKind = SE->getKind();
4514 return true;
4515 }
4516
4517 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4518 if (!BE)
4519 return false;
4520
4521 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4522 if (!SE)
4523 return false;
4524 DarwinRefKind = SE->getKind();
4525
4526 if (BE->getOpcode() != MCBinaryExpr::Add &&
4527 BE->getOpcode() != MCBinaryExpr::Sub)
4528 return false;
4529
4530 // See if the addend is is a constant, otherwise there's more going
4531 // on here than we can deal with.
4532 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4533 if (!AddendExpr)
4534 return false;
4535
4536 Addend = AddendExpr->getValue();
4537 if (BE->getOpcode() == MCBinaryExpr::Sub)
4538 Addend = -Addend;
4539
4540 // It's some symbol reference + a constant addend, but really
4541 // shouldn't use both Darwin and ELF syntax.
4542 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4543 DarwinRefKind == MCSymbolRefExpr::VK_None;
4544}
4545
4546/// Force static initialization.
4547extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004548 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4549 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4550 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004551}
4552
4553#define GET_REGISTER_MATCHER
4554#define GET_SUBTARGET_FEATURE_NAME
4555#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004556#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004557#include "AArch64GenAsmMatcher.inc"
4558
4559// Define this matcher function after the auto-generated include so we
4560// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004561unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004562 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004563 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004564 // If the kind is a token for a literal immediate, check if our asm
4565 // operand matches. This is for InstAliases which have a fixed-value
4566 // immediate in the syntax.
4567 int64_t ExpectedVal;
4568 switch (Kind) {
4569 default:
4570 return Match_InvalidOperand;
4571 case MCK__35_0:
4572 ExpectedVal = 0;
4573 break;
4574 case MCK__35_1:
4575 ExpectedVal = 1;
4576 break;
4577 case MCK__35_12:
4578 ExpectedVal = 12;
4579 break;
4580 case MCK__35_16:
4581 ExpectedVal = 16;
4582 break;
4583 case MCK__35_2:
4584 ExpectedVal = 2;
4585 break;
4586 case MCK__35_24:
4587 ExpectedVal = 24;
4588 break;
4589 case MCK__35_3:
4590 ExpectedVal = 3;
4591 break;
4592 case MCK__35_32:
4593 ExpectedVal = 32;
4594 break;
4595 case MCK__35_4:
4596 ExpectedVal = 4;
4597 break;
4598 case MCK__35_48:
4599 ExpectedVal = 48;
4600 break;
4601 case MCK__35_6:
4602 ExpectedVal = 6;
4603 break;
4604 case MCK__35_64:
4605 ExpectedVal = 64;
4606 break;
4607 case MCK__35_8:
4608 ExpectedVal = 8;
4609 break;
4610 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004611 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004612 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004613 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004614 if (!CE)
4615 return Match_InvalidOperand;
4616 if (CE->getValue() == ExpectedVal)
4617 return Match_Success;
4618 return Match_InvalidOperand;
4619}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004620
Alex Bradbury58eba092016-11-01 16:32:05 +00004621OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004622AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4623
4624 SMLoc S = getLoc();
4625
4626 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4627 Error(S, "expected register");
4628 return MatchOperand_ParseFail;
4629 }
4630
4631 int FirstReg = tryParseRegister();
4632 if (FirstReg == -1) {
4633 return MatchOperand_ParseFail;
4634 }
4635 const MCRegisterClass &WRegClass =
4636 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4637 const MCRegisterClass &XRegClass =
4638 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4639
4640 bool isXReg = XRegClass.contains(FirstReg),
4641 isWReg = WRegClass.contains(FirstReg);
4642 if (!isXReg && !isWReg) {
4643 Error(S, "expected first even register of a "
4644 "consecutive same-size even/odd register pair");
4645 return MatchOperand_ParseFail;
4646 }
4647
4648 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4649 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4650
4651 if (FirstEncoding & 0x1) {
4652 Error(S, "expected first even register of a "
4653 "consecutive same-size even/odd register pair");
4654 return MatchOperand_ParseFail;
4655 }
4656
4657 SMLoc M = getLoc();
4658 if (getParser().getTok().isNot(AsmToken::Comma)) {
4659 Error(M, "expected comma");
4660 return MatchOperand_ParseFail;
4661 }
4662 // Eat the comma
4663 getParser().Lex();
4664
4665 SMLoc E = getLoc();
4666 int SecondReg = tryParseRegister();
4667 if (SecondReg ==-1) {
4668 return MatchOperand_ParseFail;
4669 }
4670
Eugene Zelenko049b0172017-01-06 00:30:53 +00004671 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004672 (isXReg && !XRegClass.contains(SecondReg)) ||
4673 (isWReg && !WRegClass.contains(SecondReg))) {
4674 Error(E,"expected second odd register of a "
4675 "consecutive same-size even/odd register pair");
4676 return MatchOperand_ParseFail;
4677 }
Joel Jones504bf332016-10-24 13:37:13 +00004678
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004679 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004680 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004681 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4682 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4683 } else {
4684 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4685 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4686 }
4687
Florian Hahnc4422242017-11-07 13:07:50 +00004688 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4689 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004690
4691 return MatchOperand_Success;
4692}
Florian Hahn91f11e52017-11-07 16:45:48 +00004693
4694template <bool ParseSuffix>
4695OperandMatchResultTy
4696AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004697 const SMLoc S = getLoc();
4698 // Check for a SVE vector register specifier first.
Sander de Smalen8e607342017-11-15 15:44:43 +00004699 int RegNum = -1;
Florian Hahn91f11e52017-11-07 16:45:48 +00004700 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004701
Sander de Smalen8e607342017-11-15 15:44:43 +00004702 OperandMatchResultTy Res =
4703 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4704
4705 if (Res != MatchOperand_Success)
4706 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004707
4708 if (ParseSuffix && Kind.empty())
4709 return MatchOperand_NoMatch;
4710
4711 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
4712 .Case("", -1)
4713 .Case(".b", 8)
4714 .Case(".h", 16)
4715 .Case(".s", 32)
4716 .Case(".d", 64)
4717 .Case(".q", 128)
4718 .Default(0);
4719 if (!ElementWidth)
4720 return MatchOperand_NoMatch;
4721
4722 Operands.push_back(
4723 AArch64Operand::CreateReg(RegNum, RegKind::SVEDataVector, ElementWidth,
4724 S, S, getContext()));
4725
4726 return MatchOperand_Success;
4727}