blob: b44cebe205f1d34a36c54302f3bb2bcafd049e17 [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();
Tim Northover3b0846e2014-05-24 12:50:23 +000089 bool parseRegister(OperandVector &Operands);
90 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
Sander de Smalenc88f9a12018-04-11 14:10:37 +000091 bool parseNeonVectorList(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000092 bool parseOperand(OperandVector &Operands, bool isCondCode,
93 bool invertCondCode);
94
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +000095 bool showMatchError(SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000096
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000097 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000098 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +000099 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +0000100 bool parseDirectiveInst(SMLoc L);
101
Tim Northover3b0846e2014-05-24 12:50:23 +0000102 bool parseDirectiveTLSDescCall(SMLoc L);
103
104 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000105 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000106
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000107 bool parseDirectiveReq(StringRef Name, SMLoc L);
108 bool parseDirectiveUnreq(SMLoc L);
109
Tim Northover3b0846e2014-05-24 12:50:23 +0000110 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
111 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
112 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000113 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000114 bool MatchingInlineAsm) override;
115/// @name Auto-generated Match Functions
116/// {
117
118#define GET_ASSEMBLER_HEADER
119#include "AArch64GenAsmMatcher.inc"
120
121 /// }
122
Sander de Smalen73937b72018-04-11 07:36:10 +0000123 OperandMatchResultTy tryParseVectorRegister(int &Reg, StringRef &Kind,
124 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000125 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
126 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
127 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
128 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
129 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
130 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000131 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000132 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
133 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
134 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
135 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
136 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000137 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000138 OperandMatchResultTy tryParseVectorIndex(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);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000143 bool tryParseVectorList(OperandVector &Operands);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000144 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000145
146public:
147 enum AArch64MatchResultTy {
148 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
149#define GET_OPERAND_DIAGNOSTIC_TYPES
150#include "AArch64GenAsmMatcher.inc"
151 };
Joel Jones504bf332016-10-24 13:37:13 +0000152 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000153
Akira Hatanakab11ef082015-11-14 06:35:56 +0000154 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000155 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000156 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000157 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000158 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000159 MCStreamer &S = getParser().getStreamer();
160 if (S.getTargetStreamer() == nullptr)
161 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000162
163 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000164 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000165 }
166
167 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
168 SMLoc NameLoc, OperandVector &Operands) override;
169 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
170 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000171 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000172 unsigned Kind) override;
173
174 static bool classifySymbolRef(const MCExpr *Expr,
175 AArch64MCExpr::VariantKind &ELFRefKind,
176 MCSymbolRefExpr::VariantKind &DarwinRefKind,
177 int64_t &Addend);
178};
Tim Northover3b0846e2014-05-24 12:50:23 +0000179
180/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
181/// instruction.
182class AArch64Operand : public MCParsedAsmOperand {
183private:
184 enum KindTy {
185 k_Immediate,
186 k_ShiftedImm,
187 k_CondCode,
188 k_Register,
189 k_VectorList,
190 k_VectorIndex,
191 k_Token,
192 k_SysReg,
193 k_SysCR,
194 k_Prefetch,
195 k_ShiftExtend,
196 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000197 k_Barrier,
198 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000199 } Kind;
200
201 SMLoc StartLoc, EndLoc;
202
203 struct TokOp {
204 const char *Data;
205 unsigned Length;
206 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
207 };
208
209 struct RegOp {
210 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000211 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000212
213 int ElementWidth;
Tim Northover3b0846e2014-05-24 12:50:23 +0000214 };
215
216 struct VectorListOp {
217 unsigned RegNum;
218 unsigned Count;
219 unsigned NumElements;
220 unsigned ElementKind;
221 };
222
223 struct VectorIndexOp {
224 unsigned Val;
225 };
226
227 struct ImmOp {
228 const MCExpr *Val;
229 };
230
231 struct ShiftedImmOp {
232 const MCExpr *Val;
233 unsigned ShiftAmount;
234 };
235
236 struct CondCodeOp {
237 AArch64CC::CondCode Code;
238 };
239
240 struct FPImmOp {
241 unsigned Val; // Encoded 8-bit representation.
242 };
243
244 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000245 const char *Data;
246 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000247 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000248 };
249
250 struct SysRegOp {
251 const char *Data;
252 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000253 uint32_t MRSReg;
254 uint32_t MSRReg;
255 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000256 };
257
258 struct SysCRImmOp {
259 unsigned Val;
260 };
261
262 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000263 const char *Data;
264 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000265 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000266 };
267
Oliver Stannarda34e4702015-12-01 10:48:51 +0000268 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000269 const char *Data;
270 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000271 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000272 };
273
Tim Northover3b0846e2014-05-24 12:50:23 +0000274 struct ShiftExtendOp {
275 AArch64_AM::ShiftExtendType Type;
276 unsigned Amount;
277 bool HasExplicitAmount;
278 };
279
280 struct ExtendOp {
281 unsigned Val;
282 };
283
284 union {
285 struct TokOp Tok;
286 struct RegOp Reg;
287 struct VectorListOp VectorList;
288 struct VectorIndexOp VectorIndex;
289 struct ImmOp Imm;
290 struct ShiftedImmOp ShiftedImm;
291 struct CondCodeOp CondCode;
292 struct FPImmOp FPImm;
293 struct BarrierOp Barrier;
294 struct SysRegOp SysReg;
295 struct SysCRImmOp SysCRImm;
296 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000297 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000298 struct ShiftExtendOp ShiftExtend;
299 };
300
301 // Keep the MCContext around as the MCExprs may need manipulated during
302 // the add<>Operands() calls.
303 MCContext &Ctx;
304
David Blaikie960ea3f2014-06-08 16:18:35 +0000305public:
David Blaikie9f380a32015-03-16 18:06:57 +0000306 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000307
Tim Northover3b0846e2014-05-24 12:50:23 +0000308 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
309 Kind = o.Kind;
310 StartLoc = o.StartLoc;
311 EndLoc = o.EndLoc;
312 switch (Kind) {
313 case k_Token:
314 Tok = o.Tok;
315 break;
316 case k_Immediate:
317 Imm = o.Imm;
318 break;
319 case k_ShiftedImm:
320 ShiftedImm = o.ShiftedImm;
321 break;
322 case k_CondCode:
323 CondCode = o.CondCode;
324 break;
325 case k_FPImm:
326 FPImm = o.FPImm;
327 break;
328 case k_Barrier:
329 Barrier = o.Barrier;
330 break;
331 case k_Register:
332 Reg = o.Reg;
333 break;
334 case k_VectorList:
335 VectorList = o.VectorList;
336 break;
337 case k_VectorIndex:
338 VectorIndex = o.VectorIndex;
339 break;
340 case k_SysReg:
341 SysReg = o.SysReg;
342 break;
343 case k_SysCR:
344 SysCRImm = o.SysCRImm;
345 break;
346 case k_Prefetch:
347 Prefetch = o.Prefetch;
348 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000349 case k_PSBHint:
350 PSBHint = o.PSBHint;
351 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000352 case k_ShiftExtend:
353 ShiftExtend = o.ShiftExtend;
354 break;
355 }
356 }
357
358 /// getStartLoc - Get the location of the first token of this operand.
359 SMLoc getStartLoc() const override { return StartLoc; }
360 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000361 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000362
363 StringRef getToken() const {
364 assert(Kind == k_Token && "Invalid access!");
365 return StringRef(Tok.Data, Tok.Length);
366 }
367
368 bool isTokenSuffix() const {
369 assert(Kind == k_Token && "Invalid access!");
370 return Tok.IsSuffix;
371 }
372
373 const MCExpr *getImm() const {
374 assert(Kind == k_Immediate && "Invalid access!");
375 return Imm.Val;
376 }
377
378 const MCExpr *getShiftedImmVal() const {
379 assert(Kind == k_ShiftedImm && "Invalid access!");
380 return ShiftedImm.Val;
381 }
382
383 unsigned getShiftedImmShift() const {
384 assert(Kind == k_ShiftedImm && "Invalid access!");
385 return ShiftedImm.ShiftAmount;
386 }
387
388 AArch64CC::CondCode getCondCode() const {
389 assert(Kind == k_CondCode && "Invalid access!");
390 return CondCode.Code;
391 }
392
393 unsigned getFPImm() const {
394 assert(Kind == k_FPImm && "Invalid access!");
395 return FPImm.Val;
396 }
397
398 unsigned getBarrier() const {
399 assert(Kind == k_Barrier && "Invalid access!");
400 return Barrier.Val;
401 }
402
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000403 StringRef getBarrierName() const {
404 assert(Kind == k_Barrier && "Invalid access!");
405 return StringRef(Barrier.Data, Barrier.Length);
406 }
407
Tim Northover3b0846e2014-05-24 12:50:23 +0000408 unsigned getReg() const override {
409 assert(Kind == k_Register && "Invalid access!");
410 return Reg.RegNum;
411 }
412
413 unsigned getVectorListStart() const {
414 assert(Kind == k_VectorList && "Invalid access!");
415 return VectorList.RegNum;
416 }
417
418 unsigned getVectorListCount() const {
419 assert(Kind == k_VectorList && "Invalid access!");
420 return VectorList.Count;
421 }
422
423 unsigned getVectorIndex() const {
424 assert(Kind == k_VectorIndex && "Invalid access!");
425 return VectorIndex.Val;
426 }
427
428 StringRef getSysReg() const {
429 assert(Kind == k_SysReg && "Invalid access!");
430 return StringRef(SysReg.Data, SysReg.Length);
431 }
432
Tim Northover3b0846e2014-05-24 12:50:23 +0000433 unsigned getSysCR() const {
434 assert(Kind == k_SysCR && "Invalid access!");
435 return SysCRImm.Val;
436 }
437
438 unsigned getPrefetch() const {
439 assert(Kind == k_Prefetch && "Invalid access!");
440 return Prefetch.Val;
441 }
442
Oliver Stannarda34e4702015-12-01 10:48:51 +0000443 unsigned getPSBHint() const {
444 assert(Kind == k_PSBHint && "Invalid access!");
445 return PSBHint.Val;
446 }
447
448 StringRef getPSBHintName() const {
449 assert(Kind == k_PSBHint && "Invalid access!");
450 return StringRef(PSBHint.Data, PSBHint.Length);
451 }
452
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000453 StringRef getPrefetchName() const {
454 assert(Kind == k_Prefetch && "Invalid access!");
455 return StringRef(Prefetch.Data, Prefetch.Length);
456 }
457
Tim Northover3b0846e2014-05-24 12:50:23 +0000458 AArch64_AM::ShiftExtendType getShiftExtendType() const {
459 assert(Kind == k_ShiftExtend && "Invalid access!");
460 return ShiftExtend.Type;
461 }
462
463 unsigned getShiftExtendAmount() const {
464 assert(Kind == k_ShiftExtend && "Invalid access!");
465 return ShiftExtend.Amount;
466 }
467
468 bool hasShiftExtendAmount() const {
469 assert(Kind == k_ShiftExtend && "Invalid access!");
470 return ShiftExtend.HasExplicitAmount;
471 }
472
473 bool isImm() const override { return Kind == k_Immediate; }
474 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000475
476 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
477
478 template <int Bits, int Scale> bool isSImmScaled() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000479 if (!isImm())
480 return false;
481 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
482 if (!MCE)
483 return false;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000484
485 int64_t Shift = Bits - 1;
486 int64_t MinVal = (int64_t(1) << Shift) * -Scale;
487 int64_t MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
488
Tim Northover3b0846e2014-05-24 12:50:23 +0000489 int64_t Val = MCE->getValue();
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000490 return Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0;
Tim Northover3b0846e2014-05-24 12:50:23 +0000491 }
492
Sander de Smalen245e0e62018-01-22 10:46:00 +0000493 bool isSVEPattern() const {
494 if (!isImm())
495 return false;
496 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
497 if (!MCE)
498 return false;
499 int64_t Val = MCE->getValue();
500 return Val >= 0 && Val < 32;
501 }
502
Tim Northover3b0846e2014-05-24 12:50:23 +0000503 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
504 AArch64MCExpr::VariantKind ELFRefKind;
505 MCSymbolRefExpr::VariantKind DarwinRefKind;
506 int64_t Addend;
507 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
508 Addend)) {
509 // If we don't understand the expression, assume the best and
510 // let the fixup and relocation code deal with it.
511 return true;
512 }
513
514 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
515 ELFRefKind == AArch64MCExpr::VK_LO12 ||
516 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
517 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
518 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
519 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
520 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
521 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000522 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
523 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
524 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000525 // Note that we don't range-check the addend. It's adjusted modulo page
526 // size when converted, so there is no "out of range" condition when using
527 // @pageoff.
528 return Addend >= 0 && (Addend % Scale) == 0;
529 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
530 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
531 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
532 return Addend == 0;
533 }
534
535 return false;
536 }
537
538 template <int Scale> bool isUImm12Offset() const {
539 if (!isImm())
540 return false;
541
542 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
543 if (!MCE)
544 return isSymbolicUImm12Offset(getImm(), Scale);
545
546 int64_t Val = MCE->getValue();
547 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
548 }
549
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000550 template <int N, int M>
551 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000552 if (!isImm())
553 return false;
554 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
555 if (!MCE)
556 return false;
557 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000558 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000559 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000560
Sander de Smalena1c259c2018-01-29 13:05:38 +0000561 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
562 // a logical immediate can always be represented when inverted.
563 template <typename T>
564 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000565 if (!isImm())
566 return false;
567 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
568 if (!MCE)
569 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000570
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000571 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000572 int64_t SVal = typename std::make_signed<T>::type(Val);
573 int64_t UVal = typename std::make_unsigned<T>::type(Val);
574 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000575 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000576
Sander de Smalena1c259c2018-01-29 13:05:38 +0000577 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000578 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000579
Tim Northover3b0846e2014-05-24 12:50:23 +0000580 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000581
Tim Northover3b0846e2014-05-24 12:50:23 +0000582 bool isAddSubImm() const {
583 if (!isShiftedImm() && !isImm())
584 return false;
585
586 const MCExpr *Expr;
587
588 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
589 if (isShiftedImm()) {
590 unsigned Shift = ShiftedImm.ShiftAmount;
591 Expr = ShiftedImm.Val;
592 if (Shift != 0 && Shift != 12)
593 return false;
594 } else {
595 Expr = getImm();
596 }
597
598 AArch64MCExpr::VariantKind ELFRefKind;
599 MCSymbolRefExpr::VariantKind DarwinRefKind;
600 int64_t Addend;
601 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
602 DarwinRefKind, Addend)) {
603 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
604 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
605 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
606 || ELFRefKind == AArch64MCExpr::VK_LO12
607 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
608 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
609 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
610 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
611 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
612 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000613 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
614 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
615 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000616 }
617
Diana Picusc93518d2016-10-11 09:17:47 +0000618 // If it's a constant, it should be a real immediate in range:
619 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
620 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
621
622 // If it's an expression, we hope for the best and let the fixup/relocation
623 // code deal with it.
624 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000625 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000626
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000627 bool isAddSubImmNeg() const {
628 if (!isShiftedImm() && !isImm())
629 return false;
630
631 const MCExpr *Expr;
632
633 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
634 if (isShiftedImm()) {
635 unsigned Shift = ShiftedImm.ShiftAmount;
636 Expr = ShiftedImm.Val;
637 if (Shift != 0 && Shift != 12)
638 return false;
639 } else
640 Expr = getImm();
641
642 // Otherwise it should be a real negative immediate in range:
643 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
644 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
645 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000646
Tim Northover3b0846e2014-05-24 12:50:23 +0000647 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000648
Tim Northover3b0846e2014-05-24 12:50:23 +0000649 bool isSIMDImmType10() const {
650 if (!isImm())
651 return false;
652 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
653 if (!MCE)
654 return false;
655 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
656 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000657
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000658 template<int N>
659 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000660 if (!isImm())
661 return false;
662 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
663 if (!MCE)
664 return true;
665 int64_t Val = MCE->getValue();
666 if (Val & 0x3)
667 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000668 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
669 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000670 }
671
672 bool
673 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
674 if (!isImm())
675 return false;
676
677 AArch64MCExpr::VariantKind ELFRefKind;
678 MCSymbolRefExpr::VariantKind DarwinRefKind;
679 int64_t Addend;
680 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
681 DarwinRefKind, Addend)) {
682 return false;
683 }
684 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
685 return false;
686
687 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
688 if (ELFRefKind == AllowedModifiers[i])
689 return Addend == 0;
690 }
691
692 return false;
693 }
694
695 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000696 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000697 }
698
699 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000700 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
701 AArch64MCExpr::VK_TPREL_G2,
702 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000703 }
704
705 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000706 return isMovWSymbol({
707 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000708 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
709 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000710 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000711 }
712
713 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000714 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
715 AArch64MCExpr::VK_TPREL_G0,
716 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000717 }
718
719 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000720 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000721 }
722
723 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000724 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000725 }
726
727 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000728 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
729 AArch64MCExpr::VK_TPREL_G1_NC,
730 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000731 }
732
733 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000734 return isMovWSymbol(
735 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
736 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000737 }
738
739 template<int RegWidth, int Shift>
740 bool isMOVZMovAlias() const {
741 if (!isImm()) return false;
742
743 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
744 if (!CE) return false;
745 uint64_t Value = CE->getValue();
746
Tim Northoverdaa1c012016-06-16 01:42:25 +0000747 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000748 }
749
750 template<int RegWidth, int Shift>
751 bool isMOVNMovAlias() const {
752 if (!isImm()) return false;
753
754 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
755 if (!CE) return false;
756 uint64_t Value = CE->getValue();
757
Tim Northoverdaa1c012016-06-16 01:42:25 +0000758 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000759 }
760
761 bool isFPImm() const { return Kind == k_FPImm; }
762 bool isBarrier() const { return Kind == k_Barrier; }
763 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000764
Tim Northover3b0846e2014-05-24 12:50:23 +0000765 bool isMRSSystemRegister() const {
766 if (!isSysReg()) return false;
767
Tim Northover7cd58932015-01-22 17:23:04 +0000768 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000769 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000770
Tim Northover3b0846e2014-05-24 12:50:23 +0000771 bool isMSRSystemRegister() const {
772 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000773 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000774 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000775
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000776 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000777 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000778 return (SysReg.PStateField == AArch64PState::PAN ||
779 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000780 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000781
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000782 bool isSystemPStateFieldWithImm0_15() const {
783 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000784 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000785 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000786
Florian Hahnc4422242017-11-07 13:07:50 +0000787 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000788 return Kind == k_Register;
789 }
790
791 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000792 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
793 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000794
Florian Hahnc4422242017-11-07 13:07:50 +0000795 bool isNeonVectorReg() const {
796 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
797 }
798
799 bool isNeonVectorRegLo() const {
800 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000801 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
802 Reg.RegNum);
803 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000804
Sander de Smalencd6be962017-12-20 11:02:42 +0000805 template <unsigned Class> bool isSVEVectorReg() const {
806 RegKind RK;
807 switch (Class) {
808 case AArch64::ZPRRegClassID:
809 RK = RegKind::SVEDataVector;
810 break;
811 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000812 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000813 RK = RegKind::SVEPredicateVector;
814 break;
815 default:
816 llvm_unreachable("Unsupport register class");
817 }
818
819 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000820 AArch64MCRegisterClasses[Class].contains(getReg());
821 }
822
Sander de Smalencd6be962017-12-20 11:02:42 +0000823 template <int ElementWidth, unsigned Class>
824 bool isSVEVectorRegOfWidth() const {
825 return isSVEVectorReg<Class>() &&
Sander de Smalen73937b72018-04-11 07:36:10 +0000826 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth);
Florian Hahn91f11e52017-11-07 16:45:48 +0000827 }
828
Tim Northover3b0846e2014-05-24 12:50:23 +0000829 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000830 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000831 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
832 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000833
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000834 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000835 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000836 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
837 Reg.RegNum);
838 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000839
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000840 bool isXSeqPair() 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::XSeqPairsClassRegClassID].contains(
843 Reg.RegNum);
844 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000845
846 bool isGPR64sp0() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000847 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000848 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
849 }
850
Sam Parker5f934642017-08-31 09:27:04 +0000851 template<int64_t Angle, int64_t Remainder>
852 bool isComplexRotation() const {
853 if (!isImm()) return false;
854
855 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
856 if (!CE) return false;
857 uint64_t Value = CE->getValue();
858
859 return (Value % Angle == Remainder && Value <= 270);
860 }
861
Tim Northover3b0846e2014-05-24 12:50:23 +0000862 /// Is this a vector list with the type implicit (presumably attached to the
863 /// instruction itself)?
864 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
865 return Kind == k_VectorList && VectorList.Count == NumRegs &&
866 !VectorList.ElementKind;
867 }
868
869 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
870 bool isTypedVectorList() const {
871 if (Kind != k_VectorList)
872 return false;
873 if (VectorList.Count != NumRegs)
874 return false;
875 if (VectorList.ElementKind != ElementKind)
876 return false;
877 return VectorList.NumElements == NumElements;
878 }
879
880 bool isVectorIndex1() const {
881 return Kind == k_VectorIndex && VectorIndex.Val == 1;
882 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000883
Tim Northover3b0846e2014-05-24 12:50:23 +0000884 bool isVectorIndexB() const {
885 return Kind == k_VectorIndex && VectorIndex.Val < 16;
886 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000887
Tim Northover3b0846e2014-05-24 12:50:23 +0000888 bool isVectorIndexH() const {
889 return Kind == k_VectorIndex && VectorIndex.Val < 8;
890 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000891
Tim Northover3b0846e2014-05-24 12:50:23 +0000892 bool isVectorIndexS() const {
893 return Kind == k_VectorIndex && VectorIndex.Val < 4;
894 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000895
Tim Northover3b0846e2014-05-24 12:50:23 +0000896 bool isVectorIndexD() const {
897 return Kind == k_VectorIndex && VectorIndex.Val < 2;
898 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000899
Tim Northover3b0846e2014-05-24 12:50:23 +0000900 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000901
Tim Northover3b0846e2014-05-24 12:50:23 +0000902 bool isTokenEqual(StringRef Str) const {
903 return Kind == k_Token && getToken() == Str;
904 }
905 bool isSysCR() const { return Kind == k_SysCR; }
906 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000907 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000908 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
909 bool isShifter() const {
910 if (!isShiftExtend())
911 return false;
912
913 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
914 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
915 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
916 ST == AArch64_AM::MSL);
917 }
918 bool isExtend() const {
919 if (!isShiftExtend())
920 return false;
921
922 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
923 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
924 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
925 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
926 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
927 ET == AArch64_AM::LSL) &&
928 getShiftExtendAmount() <= 4;
929 }
930
931 bool isExtend64() const {
932 if (!isExtend())
933 return false;
934 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
935 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
936 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
937 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000938
Tim Northover3b0846e2014-05-24 12:50:23 +0000939 bool isExtendLSL64() const {
940 if (!isExtend())
941 return false;
942 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
943 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
944 ET == AArch64_AM::LSL) &&
945 getShiftExtendAmount() <= 4;
946 }
947
948 template<int Width> bool isMemXExtend() const {
949 if (!isExtend())
950 return false;
951 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
952 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
953 (getShiftExtendAmount() == Log2_32(Width / 8) ||
954 getShiftExtendAmount() == 0);
955 }
956
957 template<int Width> bool isMemWExtend() const {
958 if (!isExtend())
959 return false;
960 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
961 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
962 (getShiftExtendAmount() == Log2_32(Width / 8) ||
963 getShiftExtendAmount() == 0);
964 }
965
966 template <unsigned width>
967 bool isArithmeticShifter() const {
968 if (!isShifter())
969 return false;
970
971 // An arithmetic shifter is LSL, LSR, or ASR.
972 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
973 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
974 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
975 }
976
977 template <unsigned width>
978 bool isLogicalShifter() const {
979 if (!isShifter())
980 return false;
981
982 // A logical shifter is LSL, LSR, ASR or ROR.
983 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
984 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
985 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
986 getShiftExtendAmount() < width;
987 }
988
989 bool isMovImm32Shifter() const {
990 if (!isShifter())
991 return false;
992
993 // A MOVi shifter is LSL of 0, 16, 32, or 48.
994 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
995 if (ST != AArch64_AM::LSL)
996 return false;
997 uint64_t Val = getShiftExtendAmount();
998 return (Val == 0 || Val == 16);
999 }
1000
1001 bool isMovImm64Shifter() const {
1002 if (!isShifter())
1003 return false;
1004
1005 // A MOVi shifter is LSL of 0 or 16.
1006 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1007 if (ST != AArch64_AM::LSL)
1008 return false;
1009 uint64_t Val = getShiftExtendAmount();
1010 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1011 }
1012
1013 bool isLogicalVecShifter() const {
1014 if (!isShifter())
1015 return false;
1016
1017 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1018 unsigned Shift = getShiftExtendAmount();
1019 return getShiftExtendType() == AArch64_AM::LSL &&
1020 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1021 }
1022
1023 bool isLogicalVecHalfWordShifter() const {
1024 if (!isLogicalVecShifter())
1025 return false;
1026
1027 // A logical vector shifter is a left shift by 0 or 8.
1028 unsigned Shift = getShiftExtendAmount();
1029 return getShiftExtendType() == AArch64_AM::LSL &&
1030 (Shift == 0 || Shift == 8);
1031 }
1032
1033 bool isMoveVecShifter() const {
1034 if (!isShiftExtend())
1035 return false;
1036
1037 // A logical vector shifter is a left shift by 8 or 16.
1038 unsigned Shift = getShiftExtendAmount();
1039 return getShiftExtendType() == AArch64_AM::MSL &&
1040 (Shift == 8 || Shift == 16);
1041 }
1042
1043 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1044 // to LDUR/STUR when the offset is not legal for the former but is for
1045 // the latter. As such, in addition to checking for being a legal unscaled
1046 // address, also check that it is not a legal scaled address. This avoids
1047 // ambiguity in the matcher.
1048 template<int Width>
1049 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001050 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001051 }
1052
1053 bool isAdrpLabel() const {
1054 // Validation was handled during parsing, so we just sanity check that
1055 // something didn't go haywire.
1056 if (!isImm())
1057 return false;
1058
1059 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1060 int64_t Val = CE->getValue();
1061 int64_t Min = - (4096 * (1LL << (21 - 1)));
1062 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1063 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1064 }
1065
1066 return true;
1067 }
1068
1069 bool isAdrLabel() const {
1070 // Validation was handled during parsing, so we just sanity check that
1071 // something didn't go haywire.
1072 if (!isImm())
1073 return false;
1074
1075 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1076 int64_t Val = CE->getValue();
1077 int64_t Min = - (1LL << (21 - 1));
1078 int64_t Max = ((1LL << (21 - 1)) - 1);
1079 return Val >= Min && Val <= Max;
1080 }
1081
1082 return true;
1083 }
1084
1085 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1086 // Add as immediates when possible. Null MCExpr = 0.
1087 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001088 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001089 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001090 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001091 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001092 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001093 }
1094
1095 void addRegOperands(MCInst &Inst, unsigned N) const {
1096 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001097 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001098 }
1099
1100 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1101 assert(N == 1 && "Invalid number of operands!");
1102 assert(
1103 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1104
1105 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1106 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1107 RI->getEncodingValue(getReg()));
1108
Jim Grosbache9119e42015-05-13 18:37:00 +00001109 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001110 }
1111
1112 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1113 assert(N == 1 && "Invalid number of operands!");
1114 assert(
1115 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001116 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001117 }
1118
1119 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1120 assert(N == 1 && "Invalid number of operands!");
1121 assert(
1122 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001123 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001124 }
1125
1126 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1127 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001128 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001129 }
1130
1131 template <unsigned NumRegs>
1132 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1133 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001134 static const unsigned FirstRegs[] = { AArch64::D0,
1135 AArch64::D0_D1,
1136 AArch64::D0_D1_D2,
1137 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001138 unsigned FirstReg = FirstRegs[NumRegs - 1];
1139
1140 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001141 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001142 }
1143
1144 template <unsigned NumRegs>
1145 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1146 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001147 static const unsigned FirstRegs[] = { AArch64::Q0,
1148 AArch64::Q0_Q1,
1149 AArch64::Q0_Q1_Q2,
1150 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001151 unsigned FirstReg = FirstRegs[NumRegs - 1];
1152
1153 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001154 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001155 }
1156
1157 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1158 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001159 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001160 }
1161
1162 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1163 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001164 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001165 }
1166
1167 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1168 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001169 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001170 }
1171
1172 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1173 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001174 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001175 }
1176
1177 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1178 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001179 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001180 }
1181
1182 void addImmOperands(MCInst &Inst, unsigned N) const {
1183 assert(N == 1 && "Invalid number of operands!");
1184 // If this is a pageoff symrefexpr with an addend, adjust the addend
1185 // to be only the page-offset portion. Otherwise, just add the expr
1186 // as-is.
1187 addExpr(Inst, getImm());
1188 }
1189
1190 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1191 assert(N == 2 && "Invalid number of operands!");
1192 if (isShiftedImm()) {
1193 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001194 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001195 } else {
1196 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001197 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001198 }
1199 }
1200
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001201 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1202 assert(N == 2 && "Invalid number of operands!");
1203
1204 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1205 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1206 int64_t Val = -CE->getValue();
1207 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1208
1209 Inst.addOperand(MCOperand::createImm(Val));
1210 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1211 }
1212
Tim Northover3b0846e2014-05-24 12:50:23 +00001213 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1214 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001215 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001216 }
1217
1218 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1219 assert(N == 1 && "Invalid number of operands!");
1220 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1221 if (!MCE)
1222 addExpr(Inst, getImm());
1223 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001224 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001225 }
1226
1227 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1228 addImmOperands(Inst, N);
1229 }
1230
1231 template<int Scale>
1232 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1233 assert(N == 1 && "Invalid number of operands!");
1234 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1235
1236 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001237 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001238 return;
1239 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001240 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001241 }
1242
1243 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1244 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001245 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001246 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001247 }
1248
Sam Parker6d42de72017-08-11 13:14:00 +00001249 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1250 assert(N == 1 && "Invalid number of operands!");
1251 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1252 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1253 }
1254
Tim Northover3b0846e2014-05-24 12:50:23 +00001255 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1256 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001257 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001258 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001259 }
1260
1261 void addSImm7s8Operands(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() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001265 }
1266
1267 void addSImm7s16Operands(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() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001271 }
1272
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001273 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1274 assert(N == 1 && "Invalid number of operands!");
1275 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1276 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1277 }
1278
Tim Northover3b0846e2014-05-24 12:50:23 +00001279 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1280 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001281 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001282 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001283 }
1284
1285 void addImm1_8Operands(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 addImm0_15Operands(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 addImm1_16Operands(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());
Tim Northover3b0846e2014-05-24 12:50:23 +00001300 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001301 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001302 }
1303
1304 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1305 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001306 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
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 addImm1_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_32Operands(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 addImm0_63Operands(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 addImm1_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_64Operands(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 addImm0_127Operands(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_255Operands(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_65535Operands(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 addImm32_63Operands(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
Sander de Smalena1c259c2018-01-29 13:05:38 +00001364 template <typename T>
1365 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001366 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001367 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001368 typename std::make_unsigned<T>::type Val = MCE->getValue();
1369 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001370 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001371 }
1372
Sander de Smalena1c259c2018-01-29 13:05:38 +00001373 template <typename T>
1374 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001375 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001376 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001377 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1378 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001379 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001380 }
1381
Tim Northover3b0846e2014-05-24 12:50:23 +00001382 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1383 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001384 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001385 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001386 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001387 }
1388
1389 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1390 // Branch operands don't encode the low bits, so shift them off
1391 // here. If it's a label, however, just put it on directly as there's
1392 // not enough information now to do anything.
1393 assert(N == 1 && "Invalid number of operands!");
1394 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1395 if (!MCE) {
1396 addExpr(Inst, getImm());
1397 return;
1398 }
1399 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001400 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001401 }
1402
1403 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1404 // Branch operands don't encode the low bits, so shift them off
1405 // here. If it's a label, however, just put it on directly as there's
1406 // not enough information now to do anything.
1407 assert(N == 1 && "Invalid number of operands!");
1408 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1409 if (!MCE) {
1410 addExpr(Inst, getImm());
1411 return;
1412 }
1413 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001414 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001415 }
1416
1417 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1418 // Branch operands don't encode the low bits, so shift them off
1419 // here. If it's a label, however, just put it on directly as there's
1420 // not enough information now to do anything.
1421 assert(N == 1 && "Invalid number of operands!");
1422 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1423 if (!MCE) {
1424 addExpr(Inst, getImm());
1425 return;
1426 }
1427 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001428 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001429 }
1430
1431 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1432 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001433 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 }
1435
1436 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1437 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001438 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001439 }
1440
1441 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1442 assert(N == 1 && "Invalid number of operands!");
1443
Jim Grosbache9119e42015-05-13 18:37:00 +00001444 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001445 }
1446
1447 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1448 assert(N == 1 && "Invalid number of operands!");
1449
Jim Grosbache9119e42015-05-13 18:37:00 +00001450 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001451 }
1452
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001453 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1454 assert(N == 1 && "Invalid number of operands!");
1455
1456 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1457 }
1458
1459 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001460 assert(N == 1 && "Invalid number of operands!");
1461
Jim Grosbache9119e42015-05-13 18:37:00 +00001462 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001463 }
1464
1465 void addSysCROperands(MCInst &Inst, unsigned N) const {
1466 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001467 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001468 }
1469
1470 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1471 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001472 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001473 }
1474
Oliver Stannarda34e4702015-12-01 10:48:51 +00001475 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 1 && "Invalid number of operands!");
1477 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1478 }
1479
Tim Northover3b0846e2014-05-24 12:50:23 +00001480 void addShifterOperands(MCInst &Inst, unsigned N) const {
1481 assert(N == 1 && "Invalid number of operands!");
1482 unsigned Imm =
1483 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001484 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001485 }
1486
1487 void addExtendOperands(MCInst &Inst, unsigned N) const {
1488 assert(N == 1 && "Invalid number of operands!");
1489 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1490 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1491 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001492 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001493 }
1494
1495 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1496 assert(N == 1 && "Invalid number of operands!");
1497 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1498 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1499 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001500 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001501 }
1502
1503 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1504 assert(N == 2 && "Invalid number of operands!");
1505 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1506 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001507 Inst.addOperand(MCOperand::createImm(IsSigned));
1508 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001509 }
1510
1511 // For 8-bit load/store instructions with a register offset, both the
1512 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1513 // they're disambiguated by whether the shift was explicit or implicit rather
1514 // than its size.
1515 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1516 assert(N == 2 && "Invalid number of operands!");
1517 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1518 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001519 Inst.addOperand(MCOperand::createImm(IsSigned));
1520 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001521 }
1522
1523 template<int Shift>
1524 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1525 assert(N == 1 && "Invalid number of operands!");
1526
1527 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1528 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001529 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001530 }
1531
1532 template<int Shift>
1533 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1534 assert(N == 1 && "Invalid number of operands!");
1535
1536 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1537 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001538 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001539 }
1540
Sam Parker5f934642017-08-31 09:27:04 +00001541 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1542 assert(N == 1 && "Invalid number of operands!");
1543 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1544 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1545 }
1546
1547 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1548 assert(N == 1 && "Invalid number of operands!");
1549 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1550 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1551 }
1552
Tim Northover3b0846e2014-05-24 12:50:23 +00001553 void print(raw_ostream &OS) const override;
1554
David Blaikie960ea3f2014-06-08 16:18:35 +00001555 static std::unique_ptr<AArch64Operand>
1556 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1557 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001558 Op->Tok.Data = Str.data();
1559 Op->Tok.Length = Str.size();
1560 Op->Tok.IsSuffix = IsSuffix;
1561 Op->StartLoc = S;
1562 Op->EndLoc = S;
1563 return Op;
1564 }
1565
David Blaikie960ea3f2014-06-08 16:18:35 +00001566 static std::unique_ptr<AArch64Operand>
Florian Hahnc4422242017-11-07 13:07:50 +00001567 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001568 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001569 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001570 Op->Reg.Kind = Kind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001571 Op->StartLoc = S;
1572 Op->EndLoc = E;
1573 return Op;
1574 }
1575
David Blaikie960ea3f2014-06-08 16:18:35 +00001576 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001577 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1578 SMLoc S, SMLoc E, MCContext &Ctx) {
1579 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1580 Kind == RegKind::SVEPredicateVector) &&
1581 "Invalid vector kind");
Florian Hahn91f11e52017-11-07 16:45:48 +00001582 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1583 Op->Reg.RegNum = RegNum;
1584 Op->Reg.ElementWidth = ElementWidth;
1585 Op->Reg.Kind = Kind;
1586 Op->StartLoc = S;
1587 Op->EndLoc = E;
1588 return Op;
1589 }
1590
1591 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001592 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen73937b72018-04-11 07:36:10 +00001593 unsigned ElementWidth, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001594 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001595 Op->VectorList.RegNum = RegNum;
1596 Op->VectorList.Count = Count;
1597 Op->VectorList.NumElements = NumElements;
Sander de Smalen73937b72018-04-11 07:36:10 +00001598 switch (ElementWidth) {
1599 case 0:
1600 Op->VectorList.ElementKind = 0;
1601 break;
1602 case 8:
1603 Op->VectorList.ElementKind = 'b';
1604 break;
1605 case 16:
1606 Op->VectorList.ElementKind = 'h';
1607 break;
1608 case 32:
1609 Op->VectorList.ElementKind = 's';
1610 break;
1611 case 64:
1612 Op->VectorList.ElementKind = 'd';
1613 break;
1614 default:
1615 llvm_unreachable("Unsupported elementwidth");
1616 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001617 Op->StartLoc = S;
1618 Op->EndLoc = E;
1619 return Op;
1620 }
1621
David Blaikie960ea3f2014-06-08 16:18:35 +00001622 static std::unique_ptr<AArch64Operand>
1623 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1624 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001625 Op->VectorIndex.Val = Idx;
1626 Op->StartLoc = S;
1627 Op->EndLoc = E;
1628 return Op;
1629 }
1630
David Blaikie960ea3f2014-06-08 16:18:35 +00001631 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1632 SMLoc E, MCContext &Ctx) {
1633 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001634 Op->Imm.Val = Val;
1635 Op->StartLoc = S;
1636 Op->EndLoc = E;
1637 return Op;
1638 }
1639
David Blaikie960ea3f2014-06-08 16:18:35 +00001640 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1641 unsigned ShiftAmount,
1642 SMLoc S, SMLoc E,
1643 MCContext &Ctx) {
1644 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001645 Op->ShiftedImm .Val = Val;
1646 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1647 Op->StartLoc = S;
1648 Op->EndLoc = E;
1649 return Op;
1650 }
1651
David Blaikie960ea3f2014-06-08 16:18:35 +00001652 static std::unique_ptr<AArch64Operand>
1653 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1654 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001655 Op->CondCode.Code = Code;
1656 Op->StartLoc = S;
1657 Op->EndLoc = E;
1658 return Op;
1659 }
1660
David Blaikie960ea3f2014-06-08 16:18:35 +00001661 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1662 MCContext &Ctx) {
1663 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001664 Op->FPImm.Val = Val;
1665 Op->StartLoc = S;
1666 Op->EndLoc = S;
1667 return Op;
1668 }
1669
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001670 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1671 StringRef Str,
1672 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001673 MCContext &Ctx) {
1674 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001675 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001676 Op->Barrier.Data = Str.data();
1677 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001678 Op->StartLoc = S;
1679 Op->EndLoc = S;
1680 return Op;
1681 }
1682
Tim Northover7cd58932015-01-22 17:23:04 +00001683 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1684 uint32_t MRSReg,
1685 uint32_t MSRReg,
1686 uint32_t PStateField,
1687 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001688 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001689 Op->SysReg.Data = Str.data();
1690 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001691 Op->SysReg.MRSReg = MRSReg;
1692 Op->SysReg.MSRReg = MSRReg;
1693 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001694 Op->StartLoc = S;
1695 Op->EndLoc = S;
1696 return Op;
1697 }
1698
David Blaikie960ea3f2014-06-08 16:18:35 +00001699 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1700 SMLoc E, MCContext &Ctx) {
1701 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001702 Op->SysCRImm.Val = Val;
1703 Op->StartLoc = S;
1704 Op->EndLoc = E;
1705 return Op;
1706 }
1707
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001708 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1709 StringRef Str,
1710 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001711 MCContext &Ctx) {
1712 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001713 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001714 Op->Barrier.Data = Str.data();
1715 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001716 Op->StartLoc = S;
1717 Op->EndLoc = S;
1718 return Op;
1719 }
1720
Oliver Stannarda34e4702015-12-01 10:48:51 +00001721 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1722 StringRef Str,
1723 SMLoc S,
1724 MCContext &Ctx) {
1725 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1726 Op->PSBHint.Val = Val;
1727 Op->PSBHint.Data = Str.data();
1728 Op->PSBHint.Length = Str.size();
1729 Op->StartLoc = S;
1730 Op->EndLoc = S;
1731 return Op;
1732 }
1733
David Blaikie960ea3f2014-06-08 16:18:35 +00001734 static std::unique_ptr<AArch64Operand>
1735 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1736 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1737 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001738 Op->ShiftExtend.Type = ShOp;
1739 Op->ShiftExtend.Amount = Val;
1740 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1741 Op->StartLoc = S;
1742 Op->EndLoc = E;
1743 return Op;
1744 }
1745};
1746
1747} // end anonymous namespace.
1748
1749void AArch64Operand::print(raw_ostream &OS) const {
1750 switch (Kind) {
1751 case k_FPImm:
1752 OS << "<fpimm " << getFPImm() << "("
1753 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1754 break;
1755 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001756 StringRef Name = getBarrierName();
1757 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001758 OS << "<barrier " << Name << ">";
1759 else
1760 OS << "<barrier invalid #" << getBarrier() << ">";
1761 break;
1762 }
1763 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001764 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001765 break;
1766 case k_ShiftedImm: {
1767 unsigned Shift = getShiftedImmShift();
1768 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001769 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001770 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1771 break;
1772 }
1773 case k_CondCode:
1774 OS << "<condcode " << getCondCode() << ">";
1775 break;
1776 case k_Register:
1777 OS << "<register " << getReg() << ">";
1778 break;
1779 case k_VectorList: {
1780 OS << "<vectorlist ";
1781 unsigned Reg = getVectorListStart();
1782 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1783 OS << Reg + i << " ";
1784 OS << ">";
1785 break;
1786 }
1787 case k_VectorIndex:
1788 OS << "<vectorindex " << getVectorIndex() << ">";
1789 break;
1790 case k_SysReg:
1791 OS << "<sysreg: " << getSysReg() << '>';
1792 break;
1793 case k_Token:
1794 OS << "'" << getToken() << "'";
1795 break;
1796 case k_SysCR:
1797 OS << "c" << getSysCR();
1798 break;
1799 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001800 StringRef Name = getPrefetchName();
1801 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001802 OS << "<prfop " << Name << ">";
1803 else
1804 OS << "<prfop invalid #" << getPrefetch() << ">";
1805 break;
1806 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001807 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001808 OS << getPSBHintName();
1809 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001810 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001811 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1812 << getShiftExtendAmount();
1813 if (!hasShiftExtendAmount())
1814 OS << "<imp>";
1815 OS << '>';
1816 break;
1817 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001818}
1819
1820/// @name Auto-generated Match Functions
1821/// {
1822
1823static unsigned MatchRegisterName(StringRef Name);
1824
1825/// }
1826
Florian Hahnc4422242017-11-07 13:07:50 +00001827static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001828 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001829 .Case("v0", AArch64::Q0)
1830 .Case("v1", AArch64::Q1)
1831 .Case("v2", AArch64::Q2)
1832 .Case("v3", AArch64::Q3)
1833 .Case("v4", AArch64::Q4)
1834 .Case("v5", AArch64::Q5)
1835 .Case("v6", AArch64::Q6)
1836 .Case("v7", AArch64::Q7)
1837 .Case("v8", AArch64::Q8)
1838 .Case("v9", AArch64::Q9)
1839 .Case("v10", AArch64::Q10)
1840 .Case("v11", AArch64::Q11)
1841 .Case("v12", AArch64::Q12)
1842 .Case("v13", AArch64::Q13)
1843 .Case("v14", AArch64::Q14)
1844 .Case("v15", AArch64::Q15)
1845 .Case("v16", AArch64::Q16)
1846 .Case("v17", AArch64::Q17)
1847 .Case("v18", AArch64::Q18)
1848 .Case("v19", AArch64::Q19)
1849 .Case("v20", AArch64::Q20)
1850 .Case("v21", AArch64::Q21)
1851 .Case("v22", AArch64::Q22)
1852 .Case("v23", AArch64::Q23)
1853 .Case("v24", AArch64::Q24)
1854 .Case("v25", AArch64::Q25)
1855 .Case("v26", AArch64::Q26)
1856 .Case("v27", AArch64::Q27)
1857 .Case("v28", AArch64::Q28)
1858 .Case("v29", AArch64::Q29)
1859 .Case("v30", AArch64::Q30)
1860 .Case("v31", AArch64::Q31)
1861 .Default(0);
1862}
1863
Sander de Smalen73937b72018-04-11 07:36:10 +00001864/// Returns an optional pair of (#elements, element-width) if Suffix
1865/// is a valid vector kind. Where the number of elements in a vector
1866/// or the vector width is implicit or explicitly unknown (but still a
1867/// valid suffix kind), 0 is used.
1868static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1869 RegKind VectorKind) {
1870 std::pair<int, int> Res = {-1, -1};
1871
1872 switch (VectorKind) {
1873 case RegKind::NeonVector:
1874 Res =
1875 StringSwitch<std::pair<int, int>>(Suffix.lower())
1876 .Case("", {0, 0})
1877 .Case(".1d", {1, 64})
1878 .Case(".1q", {1, 128})
1879 // '.2h' needed for fp16 scalar pairwise reductions
1880 .Case(".2h", {2, 16})
1881 .Case(".2s", {2, 32})
1882 .Case(".2d", {2, 64})
1883 // '.4b' is another special case for the ARMv8.2a dot product
1884 // operand
1885 .Case(".4b", {4, 8})
1886 .Case(".4h", {4, 16})
1887 .Case(".4s", {4, 32})
1888 .Case(".8b", {8, 8})
1889 .Case(".8h", {8, 16})
1890 .Case(".16b", {16, 8})
1891 // Accept the width neutral ones, too, for verbose syntax. If those
1892 // aren't used in the right places, the token operand won't match so
1893 // all will work out.
1894 .Case(".b", {0, 8})
1895 .Case(".h", {0, 16})
1896 .Case(".s", {0, 32})
1897 .Case(".d", {0, 64})
1898 .Default({-1, -1});
1899 break;
1900 case RegKind::SVEPredicateVector:
1901 case RegKind::SVEDataVector:
1902 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1903 .Case("", {0, 0})
1904 .Case(".b", {0, 8})
1905 .Case(".h", {0, 16})
1906 .Case(".s", {0, 32})
1907 .Case(".d", {0, 64})
1908 .Case(".q", {0, 128})
1909 .Default({-1, -1});
1910 break;
1911 default:
1912 llvm_unreachable("Unsupported RegKind");
1913 }
1914
1915 if (Res == std::make_pair(-1, -1))
1916 return Optional<std::pair<int, int>>();
1917
1918 return Optional<std::pair<int, int>>(Res);
1919}
1920
1921static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1922 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001923}
1924
Florian Hahn91f11e52017-11-07 16:45:48 +00001925static unsigned matchSVEDataVectorRegName(StringRef Name) {
1926 return StringSwitch<unsigned>(Name.lower())
1927 .Case("z0", AArch64::Z0)
1928 .Case("z1", AArch64::Z1)
1929 .Case("z2", AArch64::Z2)
1930 .Case("z3", AArch64::Z3)
1931 .Case("z4", AArch64::Z4)
1932 .Case("z5", AArch64::Z5)
1933 .Case("z6", AArch64::Z6)
1934 .Case("z7", AArch64::Z7)
1935 .Case("z8", AArch64::Z8)
1936 .Case("z9", AArch64::Z9)
1937 .Case("z10", AArch64::Z10)
1938 .Case("z11", AArch64::Z11)
1939 .Case("z12", AArch64::Z12)
1940 .Case("z13", AArch64::Z13)
1941 .Case("z14", AArch64::Z14)
1942 .Case("z15", AArch64::Z15)
1943 .Case("z16", AArch64::Z16)
1944 .Case("z17", AArch64::Z17)
1945 .Case("z18", AArch64::Z18)
1946 .Case("z19", AArch64::Z19)
1947 .Case("z20", AArch64::Z20)
1948 .Case("z21", AArch64::Z21)
1949 .Case("z22", AArch64::Z22)
1950 .Case("z23", AArch64::Z23)
1951 .Case("z24", AArch64::Z24)
1952 .Case("z25", AArch64::Z25)
1953 .Case("z26", AArch64::Z26)
1954 .Case("z27", AArch64::Z27)
1955 .Case("z28", AArch64::Z28)
1956 .Case("z29", AArch64::Z29)
1957 .Case("z30", AArch64::Z30)
1958 .Case("z31", AArch64::Z31)
1959 .Default(0);
1960}
1961
Sander de Smalencd6be962017-12-20 11:02:42 +00001962static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1963 return StringSwitch<unsigned>(Name.lower())
1964 .Case("p0", AArch64::P0)
1965 .Case("p1", AArch64::P1)
1966 .Case("p2", AArch64::P2)
1967 .Case("p3", AArch64::P3)
1968 .Case("p4", AArch64::P4)
1969 .Case("p5", AArch64::P5)
1970 .Case("p6", AArch64::P6)
1971 .Case("p7", AArch64::P7)
1972 .Case("p8", AArch64::P8)
1973 .Case("p9", AArch64::P9)
1974 .Case("p10", AArch64::P10)
1975 .Case("p11", AArch64::P11)
1976 .Case("p12", AArch64::P12)
1977 .Case("p13", AArch64::P13)
1978 .Case("p14", AArch64::P14)
1979 .Case("p15", AArch64::P15)
1980 .Default(0);
1981}
1982
Tim Northover3b0846e2014-05-24 12:50:23 +00001983bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1984 SMLoc &EndLoc) {
1985 StartLoc = getLoc();
1986 RegNo = tryParseRegister();
1987 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1988 return (RegNo == (unsigned)-1);
1989}
1990
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001991// Matches a register name or register alias previously defined by '.req'
1992unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001993 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001994 unsigned RegNum = 0;
1995 if ((RegNum = matchSVEDataVectorRegName(Name)))
1996 return Kind == RegKind::SVEDataVector ? RegNum : 0;
1997
Sander de Smalencd6be962017-12-20 11:02:42 +00001998 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
1999 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2000
Sander de Smalenc067c302017-12-20 09:45:45 +00002001 if ((RegNum = MatchNeonVectorRegName(Name)))
2002 return Kind == RegKind::NeonVector ? RegNum : 0;
2003
2004 // The parsed register must be of RegKind Scalar
2005 if ((RegNum = MatchRegisterName(Name)))
2006 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002007
Florian Hahnc4422242017-11-07 13:07:50 +00002008 if (!RegNum) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002009 // Check for aliases registered via .req. Canonicalize to lower case.
2010 // That's more consistent since register names are case insensitive, and
2011 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2012 auto Entry = RegisterReqs.find(Name.lower());
2013 if (Entry == RegisterReqs.end())
2014 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002015
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002016 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002017 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002018 RegNum = Entry->getValue().second;
2019 }
2020 return RegNum;
2021}
2022
Tim Northover3b0846e2014-05-24 12:50:23 +00002023/// tryParseRegister - Try to parse a register name. The token must be an
2024/// Identifier when called, and if it is a register name the token is eaten and
2025/// the register is added to the operand list.
2026int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002027 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002028 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002029 if (Tok.isNot(AsmToken::Identifier))
2030 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00002031
2032 std::string lowerCase = Tok.getString().lower();
Florian Hahnc4422242017-11-07 13:07:50 +00002033 unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
Sander de Smalenc067c302017-12-20 09:45:45 +00002034
Tim Northover3b0846e2014-05-24 12:50:23 +00002035 // Also handle a few aliases of registers.
2036 if (RegNum == 0)
2037 RegNum = StringSwitch<unsigned>(lowerCase)
2038 .Case("fp", AArch64::FP)
2039 .Case("lr", AArch64::LR)
2040 .Case("x31", AArch64::XZR)
2041 .Case("w31", AArch64::WZR)
2042 .Default(0);
2043
2044 if (RegNum == 0)
2045 return -1;
2046
2047 Parser.Lex(); // Eat identifier token.
2048 return RegNum;
2049}
2050
Tim Northover3b0846e2014-05-24 12:50:23 +00002051/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002052OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002053AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002054 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002055 SMLoc S = getLoc();
2056
2057 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2058 Error(S, "Expected cN operand where 0 <= N <= 15");
2059 return MatchOperand_ParseFail;
2060 }
2061
2062 StringRef Tok = Parser.getTok().getIdentifier();
2063 if (Tok[0] != 'c' && Tok[0] != 'C') {
2064 Error(S, "Expected cN operand where 0 <= N <= 15");
2065 return MatchOperand_ParseFail;
2066 }
2067
2068 uint32_t CRNum;
2069 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2070 if (BadNum || CRNum > 15) {
2071 Error(S, "Expected cN operand where 0 <= N <= 15");
2072 return MatchOperand_ParseFail;
2073 }
2074
2075 Parser.Lex(); // Eat identifier token.
2076 Operands.push_back(
2077 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2078 return MatchOperand_Success;
2079}
2080
2081/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002082OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002083AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002084 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002085 SMLoc S = getLoc();
2086 const AsmToken &Tok = Parser.getTok();
2087 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002088 // Eat optional hash.
2089 if (parseOptionalToken(AsmToken::Hash) ||
2090 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002091 const MCExpr *ImmVal;
2092 if (getParser().parseExpression(ImmVal))
2093 return MatchOperand_ParseFail;
2094
2095 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2096 if (!MCE) {
2097 TokError("immediate value expected for prefetch operand");
2098 return MatchOperand_ParseFail;
2099 }
2100 unsigned prfop = MCE->getValue();
2101 if (prfop > 31) {
2102 TokError("prefetch operand out of range, [0,31] expected");
2103 return MatchOperand_ParseFail;
2104 }
2105
Tim Northovere6ae6762016-07-05 21:23:04 +00002106 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2107 Operands.push_back(AArch64Operand::CreatePrefetch(
2108 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002109 return MatchOperand_Success;
2110 }
2111
2112 if (Tok.isNot(AsmToken::Identifier)) {
2113 TokError("pre-fetch hint expected");
2114 return MatchOperand_ParseFail;
2115 }
2116
Tim Northovere6ae6762016-07-05 21:23:04 +00002117 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2118 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002119 TokError("pre-fetch hint expected");
2120 return MatchOperand_ParseFail;
2121 }
2122
2123 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002124 Operands.push_back(AArch64Operand::CreatePrefetch(
2125 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002126 return MatchOperand_Success;
2127}
2128
Oliver Stannarda34e4702015-12-01 10:48:51 +00002129/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002130OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002131AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2132 MCAsmParser &Parser = getParser();
2133 SMLoc S = getLoc();
2134 const AsmToken &Tok = Parser.getTok();
2135 if (Tok.isNot(AsmToken::Identifier)) {
2136 TokError("invalid operand for instruction");
2137 return MatchOperand_ParseFail;
2138 }
2139
Tim Northovere6ae6762016-07-05 21:23:04 +00002140 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2141 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002142 TokError("invalid operand for instruction");
2143 return MatchOperand_ParseFail;
2144 }
2145
2146 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002147 Operands.push_back(AArch64Operand::CreatePSBHint(
2148 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002149 return MatchOperand_Success;
2150}
2151
Tim Northover3b0846e2014-05-24 12:50:23 +00002152/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2153/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002154OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002155AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002156 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002157 SMLoc S = getLoc();
2158 const MCExpr *Expr;
2159
2160 if (Parser.getTok().is(AsmToken::Hash)) {
2161 Parser.Lex(); // Eat hash token.
2162 }
2163
2164 if (parseSymbolicImmVal(Expr))
2165 return MatchOperand_ParseFail;
2166
2167 AArch64MCExpr::VariantKind ELFRefKind;
2168 MCSymbolRefExpr::VariantKind DarwinRefKind;
2169 int64_t Addend;
2170 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2171 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2172 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2173 // No modifier was specified at all; this is the syntax for an ELF basic
2174 // ADRP relocation (unfortunately).
2175 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002176 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002177 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2178 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2179 Addend != 0) {
2180 Error(S, "gotpage label reference not allowed an addend");
2181 return MatchOperand_ParseFail;
2182 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2183 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2184 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2185 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2186 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2187 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2188 // The operand must be an @page or @gotpage qualified symbolref.
2189 Error(S, "page or gotpage label reference expected");
2190 return MatchOperand_ParseFail;
2191 }
2192 }
2193
2194 // We have either a label reference possibly with addend or an immediate. The
2195 // addend is a raw value here. The linker will adjust it to only reference the
2196 // page.
2197 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2198 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2199
2200 return MatchOperand_Success;
2201}
2202
2203/// tryParseAdrLabel - Parse and validate a source label for the ADR
2204/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002205OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002206AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2207 SMLoc S = getLoc();
2208 const MCExpr *Expr;
2209
Nirav Davee833c6c2016-11-08 18:31:04 +00002210 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002211 if (getParser().parseExpression(Expr))
2212 return MatchOperand_ParseFail;
2213
2214 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2215 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2216
2217 return MatchOperand_Success;
2218}
2219
2220/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002221OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002222AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002223 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002224 SMLoc S = getLoc();
2225
Nirav Davee833c6c2016-11-08 18:31:04 +00002226 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002227
2228 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002229 bool isNegative = parseOptionalToken(AsmToken::Minus);
2230
Tim Northover3b0846e2014-05-24 12:50:23 +00002231 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002232 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002233 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002234 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002235 Val = Tok.getIntVal();
2236 if (Val > 255 || Val < 0) {
2237 TokError("encoded floating point value out of range");
2238 return MatchOperand_ParseFail;
2239 }
2240 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002241 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002242 if (isNegative)
2243 RealVal.changeSign();
2244
Tim Northover3b0846e2014-05-24 12:50:23 +00002245 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002246 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002247
John Brawn5ca5daa2017-04-20 10:13:54 +00002248 // Check for out of range values. As an exception we let Zero through,
2249 // but as tokens instead of an FPImm so that it can be matched by the
2250 // appropriate alias if one exists.
2251 if (RealVal.isPosZero()) {
2252 Parser.Lex(); // Eat the token.
2253 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2254 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2255 return MatchOperand_Success;
2256 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002257 TokError("expected compatible register or floating-point constant");
2258 return MatchOperand_ParseFail;
2259 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002260 }
2261 Parser.Lex(); // Eat the token.
2262 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2263 return MatchOperand_Success;
2264 }
2265
2266 if (!Hash)
2267 return MatchOperand_NoMatch;
2268
2269 TokError("invalid floating point immediate");
2270 return MatchOperand_ParseFail;
2271}
2272
2273/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002274OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002275AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002276 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002277 SMLoc S = getLoc();
2278
2279 if (Parser.getTok().is(AsmToken::Hash))
2280 Parser.Lex(); // Eat '#'
2281 else if (Parser.getTok().isNot(AsmToken::Integer))
2282 // Operand should start from # or should be integer, emit error otherwise.
2283 return MatchOperand_NoMatch;
2284
2285 const MCExpr *Imm;
2286 if (parseSymbolicImmVal(Imm))
2287 return MatchOperand_ParseFail;
2288 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2289 uint64_t ShiftAmount = 0;
2290 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2291 if (MCE) {
2292 int64_t Val = MCE->getValue();
2293 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002294 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002295 ShiftAmount = 12;
2296 }
2297 }
2298 SMLoc E = Parser.getTok().getLoc();
2299 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2300 getContext()));
2301 return MatchOperand_Success;
2302 }
2303
2304 // Eat ','
2305 Parser.Lex();
2306
2307 // The optional operand must be "lsl #N" where N is non-negative.
2308 if (!Parser.getTok().is(AsmToken::Identifier) ||
2309 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2310 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2311 return MatchOperand_ParseFail;
2312 }
2313
2314 // Eat 'lsl'
2315 Parser.Lex();
2316
Nirav Davee833c6c2016-11-08 18:31:04 +00002317 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002318
2319 if (Parser.getTok().isNot(AsmToken::Integer)) {
2320 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2321 return MatchOperand_ParseFail;
2322 }
2323
2324 int64_t ShiftAmount = Parser.getTok().getIntVal();
2325
2326 if (ShiftAmount < 0) {
2327 Error(Parser.getTok().getLoc(), "positive shift amount required");
2328 return MatchOperand_ParseFail;
2329 }
2330 Parser.Lex(); // Eat the number
2331
2332 SMLoc E = Parser.getTok().getLoc();
2333 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2334 S, E, getContext()));
2335 return MatchOperand_Success;
2336}
2337
2338/// parseCondCodeString - Parse a Condition Code string.
2339AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2340 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2341 .Case("eq", AArch64CC::EQ)
2342 .Case("ne", AArch64CC::NE)
2343 .Case("cs", AArch64CC::HS)
2344 .Case("hs", AArch64CC::HS)
2345 .Case("cc", AArch64CC::LO)
2346 .Case("lo", AArch64CC::LO)
2347 .Case("mi", AArch64CC::MI)
2348 .Case("pl", AArch64CC::PL)
2349 .Case("vs", AArch64CC::VS)
2350 .Case("vc", AArch64CC::VC)
2351 .Case("hi", AArch64CC::HI)
2352 .Case("ls", AArch64CC::LS)
2353 .Case("ge", AArch64CC::GE)
2354 .Case("lt", AArch64CC::LT)
2355 .Case("gt", AArch64CC::GT)
2356 .Case("le", AArch64CC::LE)
2357 .Case("al", AArch64CC::AL)
2358 .Case("nv", AArch64CC::NV)
2359 .Default(AArch64CC::Invalid);
2360 return CC;
2361}
2362
2363/// parseCondCode - Parse a Condition Code operand.
2364bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2365 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002366 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002367 SMLoc S = getLoc();
2368 const AsmToken &Tok = Parser.getTok();
2369 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2370
2371 StringRef Cond = Tok.getString();
2372 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2373 if (CC == AArch64CC::Invalid)
2374 return TokError("invalid condition code");
2375 Parser.Lex(); // Eat identifier token.
2376
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002377 if (invertCondCode) {
2378 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2379 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002380 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002381 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002382
2383 Operands.push_back(
2384 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2385 return false;
2386}
2387
2388/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2389/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002390OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002391AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002392 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002393 const AsmToken &Tok = Parser.getTok();
2394 std::string LowerID = Tok.getString().lower();
2395 AArch64_AM::ShiftExtendType ShOp =
2396 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2397 .Case("lsl", AArch64_AM::LSL)
2398 .Case("lsr", AArch64_AM::LSR)
2399 .Case("asr", AArch64_AM::ASR)
2400 .Case("ror", AArch64_AM::ROR)
2401 .Case("msl", AArch64_AM::MSL)
2402 .Case("uxtb", AArch64_AM::UXTB)
2403 .Case("uxth", AArch64_AM::UXTH)
2404 .Case("uxtw", AArch64_AM::UXTW)
2405 .Case("uxtx", AArch64_AM::UXTX)
2406 .Case("sxtb", AArch64_AM::SXTB)
2407 .Case("sxth", AArch64_AM::SXTH)
2408 .Case("sxtw", AArch64_AM::SXTW)
2409 .Case("sxtx", AArch64_AM::SXTX)
2410 .Default(AArch64_AM::InvalidShiftExtend);
2411
2412 if (ShOp == AArch64_AM::InvalidShiftExtend)
2413 return MatchOperand_NoMatch;
2414
2415 SMLoc S = Tok.getLoc();
2416 Parser.Lex();
2417
Nirav Davee833c6c2016-11-08 18:31:04 +00002418 bool Hash = parseOptionalToken(AsmToken::Hash);
2419
Tim Northover3b0846e2014-05-24 12:50:23 +00002420 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2421 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2422 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2423 ShOp == AArch64_AM::MSL) {
2424 // We expect a number here.
2425 TokError("expected #imm after shift specifier");
2426 return MatchOperand_ParseFail;
2427 }
2428
Chad Rosier2ff37b82016-12-27 16:58:09 +00002429 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002430 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2431 Operands.push_back(
2432 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2433 return MatchOperand_Success;
2434 }
2435
Chad Rosier2ff37b82016-12-27 16:58:09 +00002436 // Make sure we do actually have a number, identifier or a parenthesized
2437 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002438 SMLoc E = Parser.getTok().getLoc();
2439 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002440 !Parser.getTok().is(AsmToken::LParen) &&
2441 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002442 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002443 return MatchOperand_ParseFail;
2444 }
2445
2446 const MCExpr *ImmVal;
2447 if (getParser().parseExpression(ImmVal))
2448 return MatchOperand_ParseFail;
2449
2450 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2451 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002452 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002453 return MatchOperand_ParseFail;
2454 }
2455
Jim Grosbach57fd2622014-09-23 22:16:02 +00002456 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002457 Operands.push_back(AArch64Operand::CreateShiftExtend(
2458 ShOp, MCE->getValue(), true, S, E, getContext()));
2459 return MatchOperand_Success;
2460}
2461
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002462static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2463 if (FBS[AArch64::HasV8_1aOps])
2464 Str += "ARMv8.1a";
2465 else if (FBS[AArch64::HasV8_2aOps])
2466 Str += "ARMv8.2a";
2467 else
2468 Str += "(unknown)";
2469}
2470
2471void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2472 SMLoc S) {
2473 const uint16_t Op2 = Encoding & 7;
2474 const uint16_t Cm = (Encoding & 0x78) >> 3;
2475 const uint16_t Cn = (Encoding & 0x780) >> 7;
2476 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2477
2478 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2479
2480 Operands.push_back(
2481 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2482 Operands.push_back(
2483 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2484 Operands.push_back(
2485 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2486 Expr = MCConstantExpr::create(Op2, getContext());
2487 Operands.push_back(
2488 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2489}
2490
Tim Northover3b0846e2014-05-24 12:50:23 +00002491/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2492/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2493bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2494 OperandVector &Operands) {
2495 if (Name.find('.') != StringRef::npos)
2496 return TokError("invalid operand");
2497
2498 Mnemonic = Name;
2499 Operands.push_back(
2500 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2501
Rafael Espindola961d4692014-11-11 05:18:41 +00002502 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002503 const AsmToken &Tok = Parser.getTok();
2504 StringRef Op = Tok.getString();
2505 SMLoc S = Tok.getLoc();
2506
Tim Northover3b0846e2014-05-24 12:50:23 +00002507 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002508 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2509 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002510 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002511 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2512 std::string Str("IC " + std::string(IC->Name) + " requires ");
2513 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2514 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002515 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002516 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002517 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002518 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2519 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002520 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002521 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2522 std::string Str("DC " + std::string(DC->Name) + " requires ");
2523 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2524 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002525 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002526 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002527 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002528 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2529 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002530 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002531 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2532 std::string Str("AT " + std::string(AT->Name) + " requires ");
2533 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2534 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002535 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002536 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002537 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002538 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2539 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002540 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002541 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2542 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2543 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2544 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002545 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002546 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002547 }
2548
Tim Northover3b0846e2014-05-24 12:50:23 +00002549 Parser.Lex(); // Eat operand.
2550
2551 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2552 bool HasRegister = false;
2553
2554 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002555 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002556 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2557 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002558 HasRegister = true;
2559 }
2560
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002561 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002562 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002563 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002564 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002565
Nirav Davee833c6c2016-11-08 18:31:04 +00002566 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2567 return true;
2568
Tim Northover3b0846e2014-05-24 12:50:23 +00002569 return false;
2570}
2571
Alex Bradbury58eba092016-11-01 16:32:05 +00002572OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002573AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002574 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002575 const AsmToken &Tok = Parser.getTok();
2576
2577 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002578 if (parseOptionalToken(AsmToken::Hash) ||
2579 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002580 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002581 const MCExpr *ImmVal;
2582 SMLoc ExprLoc = getLoc();
2583 if (getParser().parseExpression(ImmVal))
2584 return MatchOperand_ParseFail;
2585 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2586 if (!MCE) {
2587 Error(ExprLoc, "immediate value expected for barrier operand");
2588 return MatchOperand_ParseFail;
2589 }
2590 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2591 Error(ExprLoc, "barrier operand out of range");
2592 return MatchOperand_ParseFail;
2593 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002594 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2595 Operands.push_back(AArch64Operand::CreateBarrier(
2596 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002597 return MatchOperand_Success;
2598 }
2599
2600 if (Tok.isNot(AsmToken::Identifier)) {
2601 TokError("invalid operand for instruction");
2602 return MatchOperand_ParseFail;
2603 }
2604
Tim Northover3b0846e2014-05-24 12:50:23 +00002605 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002606 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2607 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002608 TokError("'sy' or #imm operand expected");
2609 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002610 } else if (!DB) {
2611 TokError("invalid barrier option name");
2612 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002613 }
2614
Tim Northovere6ae6762016-07-05 21:23:04 +00002615 Operands.push_back(AArch64Operand::CreateBarrier(
2616 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002617 Parser.Lex(); // Consume the option
2618
2619 return MatchOperand_Success;
2620}
2621
Alex Bradbury58eba092016-11-01 16:32:05 +00002622OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002623AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002624 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002625 const AsmToken &Tok = Parser.getTok();
2626
2627 if (Tok.isNot(AsmToken::Identifier))
2628 return MatchOperand_NoMatch;
2629
Tim Northovere6ae6762016-07-05 21:23:04 +00002630 int MRSReg, MSRReg;
2631 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2632 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2633 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2634 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2635 } else
2636 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002637
Tim Northovere6ae6762016-07-05 21:23:04 +00002638 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2639 unsigned PStateImm = -1;
2640 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2641 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002642
Tim Northovere6ae6762016-07-05 21:23:04 +00002643 Operands.push_back(
2644 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2645 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002646 Parser.Lex(); // Eat identifier
2647
2648 return MatchOperand_Success;
2649}
2650
Florian Hahnc4422242017-11-07 13:07:50 +00002651/// tryParseNeonVectorRegister - Parse a vector register operand.
2652bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002653 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002654 if (Parser.getTok().isNot(AsmToken::Identifier))
2655 return true;
2656
2657 SMLoc S = getLoc();
2658 // Check for a vector register specifier first.
2659 StringRef Kind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002660 int Reg = -1;
2661 OperandMatchResultTy Res =
2662 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2663 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002664 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002665
2666 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2667 if (!KindRes)
2668 return true;
2669
2670 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002671 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002672 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2673 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002674
Tim Northover3b0846e2014-05-24 12:50:23 +00002675 // If there was an explicit qualifier, that goes on as a literal text
2676 // operand.
2677 if (!Kind.empty())
2678 Operands.push_back(
2679 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2680
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002681 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2682}
2683
2684OperandMatchResultTy
2685AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002686 SMLoc SIdx = getLoc();
2687 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002688 const MCExpr *ImmVal;
2689 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002690 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002691 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2692 if (!MCE) {
2693 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002694 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002695 }
2696
2697 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002698
Nirav Davee833c6c2016-11-08 18:31:04 +00002699 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002700 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002701
2702 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2703 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002704 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002705 }
2706
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002707 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002708}
2709
Sander de Smalen73937b72018-04-11 07:36:10 +00002710// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002711// optional kind specifier. If it is a register specifier, eat the token
2712// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002713OperandMatchResultTy
Sander de Smalen73937b72018-04-11 07:36:10 +00002714AArch64AsmParser::tryParseVectorRegister(int &Reg, StringRef &Kind,
2715 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002716 MCAsmParser &Parser = getParser();
2717 const AsmToken &Tok = Parser.getTok();
2718
Florian Hahn91f11e52017-11-07 16:45:48 +00002719 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002720 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002721
2722 StringRef Name = Tok.getString();
2723 // If there is a kind specifier, it's separated from the register name by
2724 // a '.'.
2725 size_t Start = 0, Next = Name.find('.');
2726 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002727 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002728
2729 if (RegNum) {
2730 if (Next != StringRef::npos) {
2731 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002732 if (!isValidVectorKind(Kind, MatchKind)) {
2733 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002734 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002735 }
2736 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002737 Parser.Lex(); // Eat the register token.
2738
2739 Reg = RegNum;
2740 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002741 }
2742
Sander de Smalen8e607342017-11-15 15:44:43 +00002743 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002744}
2745
Sander de Smalencd6be962017-12-20 11:02:42 +00002746/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2747OperandMatchResultTy
2748AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2749 // Check for a SVE predicate register specifier first.
2750 const SMLoc S = getLoc();
2751 StringRef Kind;
2752 int RegNum = -1;
Sander de Smalen73937b72018-04-11 07:36:10 +00002753 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002754 if (Res != MatchOperand_Success)
2755 return Res;
2756
Sander de Smalen73937b72018-04-11 07:36:10 +00002757 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2758 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002759 return MatchOperand_NoMatch;
2760
Sander de Smalen73937b72018-04-11 07:36:10 +00002761 unsigned ElementWidth = KindRes->second;
2762 Operands.push_back(AArch64Operand::CreateVectorReg(
2763 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2764 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002765
Sander de Smalen7868e742018-01-09 11:17:06 +00002766 // Not all predicates are followed by a '/m' or '/z'.
2767 MCAsmParser &Parser = getParser();
2768 if (Parser.getTok().isNot(AsmToken::Slash))
2769 return MatchOperand_Success;
2770
2771 // But when they do they shouldn't have an element type suffix.
2772 if (!Kind.empty()) {
2773 Error(S, "not expecting size suffix");
2774 return MatchOperand_ParseFail;
2775 }
2776
2777 // Add a literal slash as operand
2778 Operands.push_back(
2779 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2780
2781 Parser.Lex(); // Eat the slash.
2782
2783 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002784 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002785 if (Pred != "z" && Pred != "m") {
2786 Error(getLoc(), "expecting 'm' or 'z' predication");
2787 return MatchOperand_ParseFail;
2788 }
2789
2790 // Add zero/merge token.
2791 const char *ZM = Pred == "z" ? "z" : "m";
2792 Operands.push_back(
2793 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2794
2795 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002796 return MatchOperand_Success;
2797}
2798
Tim Northover3b0846e2014-05-24 12:50:23 +00002799/// parseRegister - Parse a non-vector register operand.
2800bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2801 SMLoc S = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00002802 // Try for a vector (neon) register.
2803 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002804 return false;
2805
2806 // Try for a scalar register.
2807 int64_t Reg = tryParseRegister();
2808 if (Reg == -1)
2809 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002810 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2811 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002812
Tim Northover3b0846e2014-05-24 12:50:23 +00002813 return false;
2814}
2815
2816bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002817 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002818 bool HasELFModifier = false;
2819 AArch64MCExpr::VariantKind RefKind;
2820
Nirav Davee833c6c2016-11-08 18:31:04 +00002821 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002822 HasELFModifier = true;
2823
Nirav Davee833c6c2016-11-08 18:31:04 +00002824 if (Parser.getTok().isNot(AsmToken::Identifier))
2825 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002826
2827 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2828 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2829 .Case("lo12", AArch64MCExpr::VK_LO12)
2830 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2831 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2832 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2833 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2834 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2835 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2836 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2837 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2838 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2839 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2840 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2841 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2842 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2843 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2844 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2845 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2846 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2847 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2848 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2849 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2850 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2851 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2852 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2853 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2854 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2855 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2856 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2857 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2858 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2859 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2860 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2861 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2862 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2863 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002864 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2865 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002866 .Default(AArch64MCExpr::VK_INVALID);
2867
Nirav Davee833c6c2016-11-08 18:31:04 +00002868 if (RefKind == AArch64MCExpr::VK_INVALID)
2869 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002870
2871 Parser.Lex(); // Eat identifier
2872
Nirav Davee833c6c2016-11-08 18:31:04 +00002873 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002874 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002875 }
2876
2877 if (getParser().parseExpression(ImmVal))
2878 return true;
2879
2880 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002881 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002882
2883 return false;
2884}
2885
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002886/// parseVectorList - Parse a vector list operand for vector instructions.
2887bool AArch64AsmParser::tryParseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002888 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002889 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
Sander de Smalen73937b72018-04-11 07:36:10 +00002890
2891 // Wrapper around parse function
2892 auto ParseVector = [this](int &Reg, StringRef &Kind, SMLoc Loc) {
2893 if (tryParseVectorRegister(Reg, Kind, RegKind::NeonVector) ==
2894 MatchOperand_Success) {
2895 if (parseVectorKind(Kind, RegKind::NeonVector))
2896 return true;
2897 llvm_unreachable("Expected a valid vector kind");
2898 }
2899
2900 Error(Loc, "vector register expected");
2901 return false;
2902 };
2903
Tim Northover3b0846e2014-05-24 12:50:23 +00002904 SMLoc S = getLoc();
2905 Parser.Lex(); // Eat left bracket token.
2906 StringRef Kind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002907 int FirstReg = -1;
2908 if (!ParseVector(FirstReg, Kind, getLoc()))
2909 return true;
2910
Tim Northover3b0846e2014-05-24 12:50:23 +00002911 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;
Sander de Smalen73937b72018-04-11 07:36:10 +00002917
2918 int Reg;
2919 if (!ParseVector(Reg, NextKind, getLoc()))
Tim Northover3b0846e2014-05-24 12:50:23 +00002920 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002921
Tim Northover3b0846e2014-05-24 12:50:23 +00002922 // Any Kind suffices must match on all regs in the list.
2923 if (Kind != NextKind)
2924 return Error(Loc, "mismatched register size suffix");
2925
2926 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2927
2928 if (Space == 0 || Space > 3) {
2929 return Error(Loc, "invalid number of vectors");
2930 }
2931
2932 Count += Space;
2933 }
2934 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002935 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002936 SMLoc Loc = getLoc();
2937 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002938 int Reg;
2939 if (!ParseVector(Reg, NextKind, getLoc()))
Tim Northover3b0846e2014-05-24 12:50:23 +00002940 return true;
2941 // Any Kind suffices must match on all regs in the list.
2942 if (Kind != NextKind)
2943 return Error(Loc, "mismatched register size suffix");
2944
2945 // Registers must be incremental (with wraparound at 31)
2946 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2947 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2948 return Error(Loc, "registers must be sequential");
2949
2950 PrevReg = Reg;
2951 ++Count;
2952 }
2953 }
2954
Nirav Davee833c6c2016-11-08 18:31:04 +00002955 if (parseToken(AsmToken::RCurly, "'}' expected"))
2956 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002957
2958 if (Count > 4)
2959 return Error(S, "invalid number of vectors");
2960
2961 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00002962 unsigned ElementWidth = 0;
2963 if (!Kind.empty()) {
2964 if (const auto &VK = parseVectorKind(Kind, RegKind::NeonVector))
2965 std::tie(NumElements, ElementWidth) = *VK;
2966 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002967
2968 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen73937b72018-04-11 07:36:10 +00002969 FirstReg, Count, NumElements, ElementWidth, S, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002970
Tim Northover3b0846e2014-05-24 12:50:23 +00002971 return false;
2972}
2973
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002974/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
2975bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
2976 if (tryParseVectorList(Operands))
2977 return true;
2978
2979 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2980}
2981
Alex Bradbury58eba092016-11-01 16:32:05 +00002982OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002983AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002984 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002985 const AsmToken &Tok = Parser.getTok();
2986 if (!Tok.is(AsmToken::Identifier))
2987 return MatchOperand_NoMatch;
2988
Florian Hahnc4422242017-11-07 13:07:50 +00002989 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00002990
2991 MCContext &Ctx = getContext();
2992 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
2993 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
2994 return MatchOperand_NoMatch;
2995
2996 SMLoc S = getLoc();
2997 Parser.Lex(); // Eat register
2998
Nirav Davee833c6c2016-11-08 18:31:04 +00002999 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003000 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003001 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003002 return MatchOperand_Success;
3003 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003004
Nirav Davee833c6c2016-11-08 18:31:04 +00003005 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003006
3007 if (Parser.getTok().isNot(AsmToken::Integer)) {
3008 Error(getLoc(), "index must be absent or #0");
3009 return MatchOperand_ParseFail;
3010 }
3011
3012 const MCExpr *ImmVal;
3013 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3014 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3015 Error(getLoc(), "index must be absent or #0");
3016 return MatchOperand_ParseFail;
3017 }
3018
3019 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003020 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003021 return MatchOperand_Success;
3022}
3023
3024/// parseOperand - Parse a arm instruction operand. For now this parses the
3025/// operand regardless of the mnemonic.
3026bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3027 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003028 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003029
3030 OperandMatchResultTy ResTy =
3031 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3032
Tim Northover3b0846e2014-05-24 12:50:23 +00003033 // Check if the current operand has a custom associated parser, if so, try to
3034 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003035 if (ResTy == MatchOperand_Success)
3036 return false;
3037 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3038 // there was a match, but an error occurred, in which case, just return that
3039 // the operand parsing failed.
3040 if (ResTy == MatchOperand_ParseFail)
3041 return true;
3042
3043 // Nothing custom, so do general case parsing.
3044 SMLoc S, E;
3045 switch (getLexer().getKind()) {
3046 default: {
3047 SMLoc S = getLoc();
3048 const MCExpr *Expr;
3049 if (parseSymbolicImmVal(Expr))
3050 return Error(S, "invalid operand");
3051
3052 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3053 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3054 return false;
3055 }
3056 case AsmToken::LBrac: {
3057 SMLoc Loc = Parser.getTok().getLoc();
3058 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3059 getContext()));
3060 Parser.Lex(); // Eat '['
3061
3062 // There's no comma after a '[', so we can parse the next operand
3063 // immediately.
3064 return parseOperand(Operands, false, false);
3065 }
3066 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003067 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003068 case AsmToken::Identifier: {
3069 // If we're expecting a Condition Code operand, then just parse that.
3070 if (isCondCode)
3071 return parseCondCode(Operands, invertCondCode);
3072
3073 // If it's a register name, parse it.
3074 if (!parseRegister(Operands))
3075 return false;
3076
3077 // This could be an optional "shift" or "extend" operand.
3078 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3079 // We can only continue if no tokens were eaten.
3080 if (GotShift != MatchOperand_NoMatch)
3081 return GotShift;
3082
3083 // This was not a register so parse other operands that start with an
3084 // identifier (like labels) as expressions and create them as immediates.
3085 const MCExpr *IdVal;
3086 S = getLoc();
3087 if (getParser().parseExpression(IdVal))
3088 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003089 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3090 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3091 return false;
3092 }
3093 case AsmToken::Integer:
3094 case AsmToken::Real:
3095 case AsmToken::Hash: {
3096 // #42 -> immediate.
3097 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003098
3099 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003100
3101 // Parse a negative sign
3102 bool isNegative = false;
3103 if (Parser.getTok().is(AsmToken::Minus)) {
3104 isNegative = true;
3105 // We need to consume this token only when we have a Real, otherwise
3106 // we let parseSymbolicImmVal take care of it
3107 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3108 Parser.Lex();
3109 }
3110
3111 // The only Real that should come through here is a literal #0.0 for
3112 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3113 // so convert the value.
3114 const AsmToken &Tok = Parser.getTok();
3115 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003116 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003117 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3118 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3119 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3120 Mnemonic != "fcmlt")
3121 return TokError("unexpected floating point literal");
3122 else if (IntVal != 0 || isNegative)
3123 return TokError("expected floating-point constant #0.0");
3124 Parser.Lex(); // Eat the token.
3125
3126 Operands.push_back(
3127 AArch64Operand::CreateToken("#0", false, S, getContext()));
3128 Operands.push_back(
3129 AArch64Operand::CreateToken(".0", false, S, getContext()));
3130 return false;
3131 }
3132
3133 const MCExpr *ImmVal;
3134 if (parseSymbolicImmVal(ImmVal))
3135 return true;
3136
3137 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3138 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3139 return false;
3140 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003141 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003142 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003143 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003144 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003145 Parser.Lex(); // Eat '='
3146 const MCExpr *SubExprVal;
3147 if (getParser().parseExpression(SubExprVal))
3148 return true;
3149
David Peixottoae5ba762014-07-18 16:05:14 +00003150 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003151 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003152 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003153
3154 bool IsXReg =
3155 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3156 Operands[1]->getReg());
3157
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003158 MCContext& Ctx = getContext();
3159 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3160 // 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 +00003161 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003162 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3163 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3164 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3165 ShiftAmt += 16;
3166 Imm >>= 16;
3167 }
3168 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3169 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3170 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003171 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003172 if (ShiftAmt)
3173 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3174 ShiftAmt, true, S, E, Ctx));
3175 return false;
3176 }
David Peixottoae5ba762014-07-18 16:05:14 +00003177 APInt Simm = APInt(64, Imm << ShiftAmt);
3178 // check if the immediate is an unsigned or signed 32-bit int for W regs
3179 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3180 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003181 }
3182 // 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 +00003183 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003184 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003185 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3186 return false;
3187 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003188 }
3189}
3190
3191/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3192/// operands.
3193bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3194 StringRef Name, SMLoc NameLoc,
3195 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003196 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003197 Name = StringSwitch<StringRef>(Name.lower())
3198 .Case("beq", "b.eq")
3199 .Case("bne", "b.ne")
3200 .Case("bhs", "b.hs")
3201 .Case("bcs", "b.cs")
3202 .Case("blo", "b.lo")
3203 .Case("bcc", "b.cc")
3204 .Case("bmi", "b.mi")
3205 .Case("bpl", "b.pl")
3206 .Case("bvs", "b.vs")
3207 .Case("bvc", "b.vc")
3208 .Case("bhi", "b.hi")
3209 .Case("bls", "b.ls")
3210 .Case("bge", "b.ge")
3211 .Case("blt", "b.lt")
3212 .Case("bgt", "b.gt")
3213 .Case("ble", "b.le")
3214 .Case("bal", "b.al")
3215 .Case("bnv", "b.nv")
3216 .Default(Name);
3217
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003218 // First check for the AArch64-specific .req directive.
3219 if (Parser.getTok().is(AsmToken::Identifier) &&
3220 Parser.getTok().getIdentifier() == ".req") {
3221 parseDirectiveReq(Name, NameLoc);
3222 // We always return 'error' for this, as we're done with this
3223 // statement and don't need to match the 'instruction."
3224 return true;
3225 }
3226
Tim Northover3b0846e2014-05-24 12:50:23 +00003227 // Create the leading tokens for the mnemonic, split by '.' characters.
3228 size_t Start = 0, Next = Name.find('.');
3229 StringRef Head = Name.slice(Start, Next);
3230
3231 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003232 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3233 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003234
3235 Operands.push_back(
3236 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3237 Mnemonic = Head;
3238
3239 // Handle condition codes for a branch mnemonic
3240 if (Head == "b" && Next != StringRef::npos) {
3241 Start = Next;
3242 Next = Name.find('.', Start + 1);
3243 Head = Name.slice(Start + 1, Next);
3244
3245 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3246 (Head.data() - Name.data()));
3247 AArch64CC::CondCode CC = parseCondCodeString(Head);
3248 if (CC == AArch64CC::Invalid)
3249 return Error(SuffixLoc, "invalid condition code");
3250 Operands.push_back(
3251 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3252 Operands.push_back(
3253 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3254 }
3255
3256 // Add the remaining tokens in the mnemonic.
3257 while (Next != StringRef::npos) {
3258 Start = Next;
3259 Next = Name.find('.', Start + 1);
3260 Head = Name.slice(Start, Next);
3261 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3262 (Head.data() - Name.data()) + 1);
3263 Operands.push_back(
3264 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3265 }
3266
3267 // Conditional compare instructions have a Condition Code operand, which needs
3268 // to be parsed and an immediate operand created.
3269 bool condCodeFourthOperand =
3270 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3271 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3272 Head == "csinc" || Head == "csinv" || Head == "csneg");
3273
3274 // These instructions are aliases to some of the conditional select
3275 // instructions. However, the condition code is inverted in the aliased
3276 // instruction.
3277 //
3278 // FIXME: Is this the correct way to handle these? Or should the parser
3279 // generate the aliased instructions directly?
3280 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3281 bool condCodeThirdOperand =
3282 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3283
3284 // Read the remaining operands.
3285 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3286 // Read the first operand.
3287 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003288 return true;
3289 }
3290
3291 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003292 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003293 // Parse and remember the operand.
3294 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3295 (N == 3 && condCodeThirdOperand) ||
3296 (N == 2 && condCodeSecondOperand),
3297 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003298 return true;
3299 }
3300
3301 // After successfully parsing some operands there are two special cases to
3302 // consider (i.e. notional operands not separated by commas). Both are due
3303 // to memory specifiers:
3304 // + An RBrac will end an address for load/store/prefetch
3305 // + An '!' will indicate a pre-indexed operation.
3306 //
3307 // It's someone else's responsibility to make sure these tokens are sane
3308 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003309
Nirav Davee833c6c2016-11-08 18:31:04 +00003310 SMLoc RLoc = Parser.getTok().getLoc();
3311 if (parseOptionalToken(AsmToken::RBrac))
3312 Operands.push_back(
3313 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3314 SMLoc ELoc = Parser.getTok().getLoc();
3315 if (parseOptionalToken(AsmToken::Exclaim))
3316 Operands.push_back(
3317 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003318
3319 ++N;
3320 }
3321 }
3322
Nirav Davee833c6c2016-11-08 18:31:04 +00003323 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3324 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003325
Tim Northover3b0846e2014-05-24 12:50:23 +00003326 return false;
3327}
3328
3329// FIXME: This entire function is a giant hack to provide us with decent
3330// operand range validation/diagnostics until TableGen/MC can be extended
3331// to support autogeneration of this kind of validation.
3332bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3333 SmallVectorImpl<SMLoc> &Loc) {
3334 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3335 // Check for indexed addressing modes w/ the base register being the
3336 // same as a destination/source register or pair load where
3337 // the Rt == Rt2. All of those are undefined behaviour.
3338 switch (Inst.getOpcode()) {
3339 case AArch64::LDPSWpre:
3340 case AArch64::LDPWpost:
3341 case AArch64::LDPWpre:
3342 case AArch64::LDPXpost:
3343 case AArch64::LDPXpre: {
3344 unsigned Rt = Inst.getOperand(1).getReg();
3345 unsigned Rt2 = Inst.getOperand(2).getReg();
3346 unsigned Rn = Inst.getOperand(3).getReg();
3347 if (RI->isSubRegisterEq(Rn, Rt))
3348 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3349 "is also a destination");
3350 if (RI->isSubRegisterEq(Rn, Rt2))
3351 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3352 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003353 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003354 }
3355 case AArch64::LDPDi:
3356 case AArch64::LDPQi:
3357 case AArch64::LDPSi:
3358 case AArch64::LDPSWi:
3359 case AArch64::LDPWi:
3360 case AArch64::LDPXi: {
3361 unsigned Rt = Inst.getOperand(0).getReg();
3362 unsigned Rt2 = Inst.getOperand(1).getReg();
3363 if (Rt == Rt2)
3364 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3365 break;
3366 }
3367 case AArch64::LDPDpost:
3368 case AArch64::LDPDpre:
3369 case AArch64::LDPQpost:
3370 case AArch64::LDPQpre:
3371 case AArch64::LDPSpost:
3372 case AArch64::LDPSpre:
3373 case AArch64::LDPSWpost: {
3374 unsigned Rt = Inst.getOperand(1).getReg();
3375 unsigned Rt2 = Inst.getOperand(2).getReg();
3376 if (Rt == Rt2)
3377 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3378 break;
3379 }
3380 case AArch64::STPDpost:
3381 case AArch64::STPDpre:
3382 case AArch64::STPQpost:
3383 case AArch64::STPQpre:
3384 case AArch64::STPSpost:
3385 case AArch64::STPSpre:
3386 case AArch64::STPWpost:
3387 case AArch64::STPWpre:
3388 case AArch64::STPXpost:
3389 case AArch64::STPXpre: {
3390 unsigned Rt = Inst.getOperand(1).getReg();
3391 unsigned Rt2 = Inst.getOperand(2).getReg();
3392 unsigned Rn = Inst.getOperand(3).getReg();
3393 if (RI->isSubRegisterEq(Rn, Rt))
3394 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3395 "is also a source");
3396 if (RI->isSubRegisterEq(Rn, Rt2))
3397 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3398 "is also a source");
3399 break;
3400 }
3401 case AArch64::LDRBBpre:
3402 case AArch64::LDRBpre:
3403 case AArch64::LDRHHpre:
3404 case AArch64::LDRHpre:
3405 case AArch64::LDRSBWpre:
3406 case AArch64::LDRSBXpre:
3407 case AArch64::LDRSHWpre:
3408 case AArch64::LDRSHXpre:
3409 case AArch64::LDRSWpre:
3410 case AArch64::LDRWpre:
3411 case AArch64::LDRXpre:
3412 case AArch64::LDRBBpost:
3413 case AArch64::LDRBpost:
3414 case AArch64::LDRHHpost:
3415 case AArch64::LDRHpost:
3416 case AArch64::LDRSBWpost:
3417 case AArch64::LDRSBXpost:
3418 case AArch64::LDRSHWpost:
3419 case AArch64::LDRSHXpost:
3420 case AArch64::LDRSWpost:
3421 case AArch64::LDRWpost:
3422 case AArch64::LDRXpost: {
3423 unsigned Rt = Inst.getOperand(1).getReg();
3424 unsigned Rn = Inst.getOperand(2).getReg();
3425 if (RI->isSubRegisterEq(Rn, Rt))
3426 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3427 "is also a source");
3428 break;
3429 }
3430 case AArch64::STRBBpost:
3431 case AArch64::STRBpost:
3432 case AArch64::STRHHpost:
3433 case AArch64::STRHpost:
3434 case AArch64::STRWpost:
3435 case AArch64::STRXpost:
3436 case AArch64::STRBBpre:
3437 case AArch64::STRBpre:
3438 case AArch64::STRHHpre:
3439 case AArch64::STRHpre:
3440 case AArch64::STRWpre:
3441 case AArch64::STRXpre: {
3442 unsigned Rt = Inst.getOperand(1).getReg();
3443 unsigned Rn = Inst.getOperand(2).getReg();
3444 if (RI->isSubRegisterEq(Rn, Rt))
3445 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3446 "is also a source");
3447 break;
3448 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003449 case AArch64::STXRB:
3450 case AArch64::STXRH:
3451 case AArch64::STXRW:
3452 case AArch64::STXRX:
3453 case AArch64::STLXRB:
3454 case AArch64::STLXRH:
3455 case AArch64::STLXRW:
3456 case AArch64::STLXRX: {
3457 unsigned Rs = Inst.getOperand(0).getReg();
3458 unsigned Rt = Inst.getOperand(1).getReg();
3459 unsigned Rn = Inst.getOperand(2).getReg();
3460 if (RI->isSubRegisterEq(Rt, Rs) ||
3461 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3462 return Error(Loc[0],
3463 "unpredictable STXR instruction, status is also a source");
3464 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003465 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003466 case AArch64::STXPW:
3467 case AArch64::STXPX:
3468 case AArch64::STLXPW:
3469 case AArch64::STLXPX: {
3470 unsigned Rs = Inst.getOperand(0).getReg();
3471 unsigned Rt1 = Inst.getOperand(1).getReg();
3472 unsigned Rt2 = Inst.getOperand(2).getReg();
3473 unsigned Rn = Inst.getOperand(3).getReg();
3474 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3475 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3476 return Error(Loc[0],
3477 "unpredictable STXP instruction, status is also a source");
3478 break;
3479 }
3480 }
3481
Tim Northover3b0846e2014-05-24 12:50:23 +00003482
3483 // Now check immediate ranges. Separate from the above as there is overlap
3484 // in the instructions being checked and this keeps the nested conditionals
3485 // to a minimum.
3486 switch (Inst.getOpcode()) {
3487 case AArch64::ADDSWri:
3488 case AArch64::ADDSXri:
3489 case AArch64::ADDWri:
3490 case AArch64::ADDXri:
3491 case AArch64::SUBSWri:
3492 case AArch64::SUBSXri:
3493 case AArch64::SUBWri:
3494 case AArch64::SUBXri: {
3495 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3496 // some slight duplication here.
3497 if (Inst.getOperand(2).isExpr()) {
3498 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3499 AArch64MCExpr::VariantKind ELFRefKind;
3500 MCSymbolRefExpr::VariantKind DarwinRefKind;
3501 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003502 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3503
3504 // Only allow these with ADDXri.
3505 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3506 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3507 Inst.getOpcode() == AArch64::ADDXri)
3508 return false;
3509
3510 // Only allow these with ADDXri/ADDWri
3511 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3512 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3513 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3514 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3515 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3516 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3517 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003518 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3519 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3520 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003521 (Inst.getOpcode() == AArch64::ADDXri ||
3522 Inst.getOpcode() == AArch64::ADDWri))
3523 return false;
3524
3525 // Don't allow symbol refs in the immediate field otherwise
3526 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3527 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3528 // 'cmp w0, 'borked')
3529 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003530 }
Diana Picusc93518d2016-10-11 09:17:47 +00003531 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003532 }
3533 return false;
3534 }
3535 default:
3536 return false;
3537 }
3538}
3539
Craig Topper05515562017-10-26 06:46:41 +00003540static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3541 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003542
3543bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3544 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003545 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003546 case Match_InvalidTiedOperand:
3547 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003548 case Match_MissingFeature:
3549 return Error(Loc,
3550 "instruction requires a CPU feature not currently enabled");
3551 case Match_InvalidOperand:
3552 return Error(Loc, "invalid operand for instruction");
3553 case Match_InvalidSuffix:
3554 return Error(Loc, "invalid type suffix for instruction");
3555 case Match_InvalidCondCode:
3556 return Error(Loc, "expected AArch64 condition code");
3557 case Match_AddSubRegExtendSmall:
3558 return Error(Loc,
3559 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3560 case Match_AddSubRegExtendLarge:
3561 return Error(Loc,
3562 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3563 case Match_AddSubSecondSource:
3564 return Error(Loc,
3565 "expected compatible register, symbol or integer in range [0, 4095]");
3566 case Match_LogicalSecondSource:
3567 return Error(Loc, "expected compatible register or logical immediate");
3568 case Match_InvalidMovImm32Shift:
3569 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3570 case Match_InvalidMovImm64Shift:
3571 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3572 case Match_AddSubRegShift32:
3573 return Error(Loc,
3574 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3575 case Match_AddSubRegShift64:
3576 return Error(Loc,
3577 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3578 case Match_InvalidFPImm:
3579 return Error(Loc,
3580 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003581 case Match_InvalidMemoryIndexedSImm6:
3582 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003583 case Match_InvalidMemoryIndexedSImm5:
3584 return Error(Loc, "index must be an integer in range [-16, 15].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003585 case Match_InvalidMemoryIndexedSImm9:
3586 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003587 case Match_InvalidMemoryIndexedSImm10:
3588 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003589 case Match_InvalidMemoryIndexed4SImm7:
3590 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3591 case Match_InvalidMemoryIndexed8SImm7:
3592 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3593 case Match_InvalidMemoryIndexed16SImm7:
3594 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3595 case Match_InvalidMemoryWExtend8:
3596 return Error(Loc,
3597 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3598 case Match_InvalidMemoryWExtend16:
3599 return Error(Loc,
3600 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3601 case Match_InvalidMemoryWExtend32:
3602 return Error(Loc,
3603 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3604 case Match_InvalidMemoryWExtend64:
3605 return Error(Loc,
3606 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3607 case Match_InvalidMemoryWExtend128:
3608 return Error(Loc,
3609 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3610 case Match_InvalidMemoryXExtend8:
3611 return Error(Loc,
3612 "expected 'lsl' or 'sxtx' with optional shift of #0");
3613 case Match_InvalidMemoryXExtend16:
3614 return Error(Loc,
3615 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3616 case Match_InvalidMemoryXExtend32:
3617 return Error(Loc,
3618 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3619 case Match_InvalidMemoryXExtend64:
3620 return Error(Loc,
3621 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3622 case Match_InvalidMemoryXExtend128:
3623 return Error(Loc,
3624 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3625 case Match_InvalidMemoryIndexed1:
3626 return Error(Loc, "index must be an integer in range [0, 4095].");
3627 case Match_InvalidMemoryIndexed2:
3628 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3629 case Match_InvalidMemoryIndexed4:
3630 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3631 case Match_InvalidMemoryIndexed8:
3632 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3633 case Match_InvalidMemoryIndexed16:
3634 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003635 case Match_InvalidImm0_1:
3636 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003637 case Match_InvalidImm0_7:
3638 return Error(Loc, "immediate must be an integer in range [0, 7].");
3639 case Match_InvalidImm0_15:
3640 return Error(Loc, "immediate must be an integer in range [0, 15].");
3641 case Match_InvalidImm0_31:
3642 return Error(Loc, "immediate must be an integer in range [0, 31].");
3643 case Match_InvalidImm0_63:
3644 return Error(Loc, "immediate must be an integer in range [0, 63].");
3645 case Match_InvalidImm0_127:
3646 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003647 case Match_InvalidImm0_255:
3648 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003649 case Match_InvalidImm0_65535:
3650 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3651 case Match_InvalidImm1_8:
3652 return Error(Loc, "immediate must be an integer in range [1, 8].");
3653 case Match_InvalidImm1_16:
3654 return Error(Loc, "immediate must be an integer in range [1, 16].");
3655 case Match_InvalidImm1_32:
3656 return Error(Loc, "immediate must be an integer in range [1, 32].");
3657 case Match_InvalidImm1_64:
3658 return Error(Loc, "immediate must be an integer in range [1, 64].");
3659 case Match_InvalidIndex1:
3660 return Error(Loc, "expected lane specifier '[1]'");
3661 case Match_InvalidIndexB:
3662 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3663 case Match_InvalidIndexH:
3664 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3665 case Match_InvalidIndexS:
3666 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3667 case Match_InvalidIndexD:
3668 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3669 case Match_InvalidLabel:
3670 return Error(Loc, "expected label or encodable integer pc offset");
3671 case Match_MRS:
3672 return Error(Loc, "expected readable system register");
3673 case Match_MSR:
3674 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003675 case Match_InvalidComplexRotationEven:
3676 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3677 case Match_InvalidComplexRotationOdd:
3678 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003679 case Match_MnemonicFail: {
3680 std::string Suggestion = AArch64MnemonicSpellCheck(
3681 ((AArch64Operand &)*Operands[0]).getToken(),
3682 ComputeAvailableFeatures(STI->getFeatureBits()));
3683 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3684 }
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003685 case Match_InvalidSVEPattern:
3686 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003687 case Match_InvalidSVEPredicateAnyReg:
3688 case Match_InvalidSVEPredicateBReg:
3689 case Match_InvalidSVEPredicateHReg:
3690 case Match_InvalidSVEPredicateSReg:
3691 case Match_InvalidSVEPredicateDReg:
3692 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003693 case Match_InvalidSVEPredicate3bAnyReg:
3694 case Match_InvalidSVEPredicate3bBReg:
3695 case Match_InvalidSVEPredicate3bHReg:
3696 case Match_InvalidSVEPredicate3bSReg:
3697 case Match_InvalidSVEPredicate3bDReg:
3698 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003699 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003700 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003701 }
3702}
3703
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003704static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003705
3706bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3707 OperandVector &Operands,
3708 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003709 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003710 bool MatchingInlineAsm) {
3711 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003712 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3713 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003714
David Blaikie960ea3f2014-06-08 16:18:35 +00003715 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003716 unsigned NumOperands = Operands.size();
3717
3718 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003719 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3720 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003721 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003722 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003723 if (Op3CE) {
3724 uint64_t Op3Val = Op3CE->getValue();
3725 uint64_t NewOp3Val = 0;
3726 uint64_t NewOp4Val = 0;
3727 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003728 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003729 NewOp3Val = (32 - Op3Val) & 0x1f;
3730 NewOp4Val = 31 - Op3Val;
3731 } else {
3732 NewOp3Val = (64 - Op3Val) & 0x3f;
3733 NewOp4Val = 63 - Op3Val;
3734 }
3735
Jim Grosbach13760bd2015-05-30 01:25:56 +00003736 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3737 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003738
3739 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003740 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003741 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003742 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3743 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3744 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003745 }
3746 }
Tim Northover03b99f62015-04-30 18:28:58 +00003747 } else if (NumOperands == 4 && Tok == "bfc") {
3748 // FIXME: Horrible hack to handle BFC->BFM alias.
3749 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3750 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3751 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3752
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003753 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003754 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3755 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3756
3757 if (LSBCE && WidthCE) {
3758 uint64_t LSB = LSBCE->getValue();
3759 uint64_t Width = WidthCE->getValue();
3760
3761 uint64_t RegWidth = 0;
3762 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3763 Op1.getReg()))
3764 RegWidth = 64;
3765 else
3766 RegWidth = 32;
3767
3768 if (LSB >= RegWidth)
3769 return Error(LSBOp.getStartLoc(),
3770 "expected integer in range [0, 31]");
3771 if (Width < 1 || Width > RegWidth)
3772 return Error(WidthOp.getStartLoc(),
3773 "expected integer in range [1, 32]");
3774
3775 uint64_t ImmR = 0;
3776 if (RegWidth == 32)
3777 ImmR = (32 - LSB) & 0x1f;
3778 else
3779 ImmR = (64 - LSB) & 0x3f;
3780
3781 uint64_t ImmS = Width - 1;
3782
3783 if (ImmR != 0 && ImmS >= ImmR)
3784 return Error(WidthOp.getStartLoc(),
3785 "requested insert overflows register");
3786
Jim Grosbach13760bd2015-05-30 01:25:56 +00003787 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3788 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003789 Operands[0] = AArch64Operand::CreateToken(
3790 "bfm", false, Op.getStartLoc(), getContext());
3791 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003792 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3793 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003794 Operands[3] = AArch64Operand::CreateImm(
3795 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3796 Operands.emplace_back(
3797 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3798 WidthOp.getEndLoc(), getContext()));
3799 }
3800 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003801 } else if (NumOperands == 5) {
3802 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3803 // UBFIZ -> UBFM aliases.
3804 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003805 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3806 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3807 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003808
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003809 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003810 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3811 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003812
3813 if (Op3CE && Op4CE) {
3814 uint64_t Op3Val = Op3CE->getValue();
3815 uint64_t Op4Val = Op4CE->getValue();
3816
3817 uint64_t RegWidth = 0;
3818 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003819 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003820 RegWidth = 64;
3821 else
3822 RegWidth = 32;
3823
3824 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003825 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003826 "expected integer in range [0, 31]");
3827 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003828 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003829 "expected integer in range [1, 32]");
3830
3831 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003832 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003833 NewOp3Val = (32 - Op3Val) & 0x1f;
3834 else
3835 NewOp3Val = (64 - Op3Val) & 0x3f;
3836
3837 uint64_t NewOp4Val = Op4Val - 1;
3838
3839 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003840 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003841 "requested insert overflows register");
3842
3843 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003844 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003845 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003846 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003847 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003848 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003849 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003850 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003851 if (Tok == "bfi")
3852 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003853 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003854 else if (Tok == "sbfiz")
3855 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003856 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003857 else if (Tok == "ubfiz")
3858 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003859 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003860 else
3861 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003862 }
3863 }
3864
3865 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3866 // UBFX -> UBFM aliases.
3867 } else if (NumOperands == 5 &&
3868 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003869 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3870 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3871 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003872
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003873 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003874 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3875 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003876
3877 if (Op3CE && Op4CE) {
3878 uint64_t Op3Val = Op3CE->getValue();
3879 uint64_t Op4Val = Op4CE->getValue();
3880
3881 uint64_t RegWidth = 0;
3882 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003883 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003884 RegWidth = 64;
3885 else
3886 RegWidth = 32;
3887
3888 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003889 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003890 "expected integer in range [0, 31]");
3891 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003892 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003893 "expected integer in range [1, 32]");
3894
3895 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3896
3897 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003898 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003899 "requested extract overflows register");
3900
3901 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003902 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003903 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003904 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003905 if (Tok == "bfxil")
3906 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003907 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003908 else if (Tok == "sbfx")
3909 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003910 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003911 else if (Tok == "ubfx")
3912 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003913 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003914 else
3915 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003916 }
3917 }
3918 }
3919 }
Tim Northover9097a072017-12-18 10:36:00 +00003920
3921 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
3922 // instruction for FP registers correctly in some rare circumstances. Convert
3923 // it to a safe instruction and warn (because silently changing someone's
3924 // assembly is rude).
3925 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
3926 NumOperands == 4 && Tok == "movi") {
3927 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3928 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3929 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3930 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
3931 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
3932 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
3933 if (Suffix.lower() == ".2d" &&
3934 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
3935 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
3936 " correctly on this CPU, converting to equivalent movi.16b");
3937 // Switch the suffix to .16b.
3938 unsigned Idx = Op1.isToken() ? 1 : 2;
3939 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
3940 getContext());
3941 }
3942 }
3943 }
3944
Tim Northover3b0846e2014-05-24 12:50:23 +00003945 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3946 // InstAlias can't quite handle this since the reg classes aren't
3947 // subclasses.
3948 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3949 // The source register can be Wn here, but the matcher expects a
3950 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003951 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003952 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003953 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003954 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3955 Op.getStartLoc(), Op.getEndLoc(),
3956 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003957 }
3958 }
3959 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3960 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003961 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003962 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003963 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003964 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003965 // The source register can be Wn here, but the matcher expects a
3966 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003967 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003968 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003969 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003970 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3971 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003972 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003973 }
3974 }
3975 }
3976 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3977 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003978 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003979 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003980 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003981 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003982 // The source register can be Wn here, but the matcher expects a
3983 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003984 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003985 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003986 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003987 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3988 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003989 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003990 }
3991 }
3992 }
3993
Tim Northover3b0846e2014-05-24 12:50:23 +00003994 MCInst Inst;
3995 // First try to match against the secondary set of tables containing the
3996 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3997 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003998 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003999
4000 // If that fails, try against the alternate table containing long-form NEON:
4001 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004002 if (MatchResult != Match_Success) {
4003 // But first, save the short-form match result: we can use it in case the
4004 // long-form match also fails.
4005 auto ShortFormNEONErrorInfo = ErrorInfo;
4006 auto ShortFormNEONMatchResult = MatchResult;
4007
Tim Northover3b0846e2014-05-24 12:50:23 +00004008 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004009 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004010
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004011 // Now, both matches failed, and the long-form match failed on the mnemonic
4012 // suffix token operand. The short-form match failure is probably more
4013 // relevant: use it instead.
4014 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004015 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004016 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4017 MatchResult = ShortFormNEONMatchResult;
4018 ErrorInfo = ShortFormNEONErrorInfo;
4019 }
4020 }
4021
Tim Northover3b0846e2014-05-24 12:50:23 +00004022 switch (MatchResult) {
4023 case Match_Success: {
4024 // Perform range checking and other semantic validations
4025 SmallVector<SMLoc, 8> OperandLocs;
4026 NumOperands = Operands.size();
4027 for (unsigned i = 1; i < NumOperands; ++i)
4028 OperandLocs.push_back(Operands[i]->getStartLoc());
4029 if (validateInstruction(Inst, OperandLocs))
4030 return true;
4031
4032 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004033 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004034 return false;
4035 }
4036 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004037 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004038 // Special case the error message for the very common case where only
4039 // a single subtarget feature is missing (neon, e.g.).
4040 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004041 uint64_t Mask = 1;
4042 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4043 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004044 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004045 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004046 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004047 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004048 }
4049 return Error(IDLoc, Msg);
4050 }
4051 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004052 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004053 case Match_InvalidOperand: {
4054 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004055
Tim Northover26bb14e2014-08-18 11:49:42 +00004056 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004057 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004058 return Error(IDLoc, "too few operands for instruction",
4059 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004060
David Blaikie960ea3f2014-06-08 16:18:35 +00004061 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004062 if (ErrorLoc == SMLoc())
4063 ErrorLoc = IDLoc;
4064 }
4065 // If the match failed on a suffix token operand, tweak the diagnostic
4066 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004067 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4068 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004069 MatchResult = Match_InvalidSuffix;
4070
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004071 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004072 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004073 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004074 case Match_InvalidMemoryIndexed1:
4075 case Match_InvalidMemoryIndexed2:
4076 case Match_InvalidMemoryIndexed4:
4077 case Match_InvalidMemoryIndexed8:
4078 case Match_InvalidMemoryIndexed16:
4079 case Match_InvalidCondCode:
4080 case Match_AddSubRegExtendSmall:
4081 case Match_AddSubRegExtendLarge:
4082 case Match_AddSubSecondSource:
4083 case Match_LogicalSecondSource:
4084 case Match_AddSubRegShift32:
4085 case Match_AddSubRegShift64:
4086 case Match_InvalidMovImm32Shift:
4087 case Match_InvalidMovImm64Shift:
4088 case Match_InvalidFPImm:
4089 case Match_InvalidMemoryWExtend8:
4090 case Match_InvalidMemoryWExtend16:
4091 case Match_InvalidMemoryWExtend32:
4092 case Match_InvalidMemoryWExtend64:
4093 case Match_InvalidMemoryWExtend128:
4094 case Match_InvalidMemoryXExtend8:
4095 case Match_InvalidMemoryXExtend16:
4096 case Match_InvalidMemoryXExtend32:
4097 case Match_InvalidMemoryXExtend64:
4098 case Match_InvalidMemoryXExtend128:
Sander de Smalen909cf952018-01-19 15:22:00 +00004099 case Match_InvalidMemoryIndexedSImm6:
Tim Northover3b0846e2014-05-24 12:50:23 +00004100 case Match_InvalidMemoryIndexed4SImm7:
4101 case Match_InvalidMemoryIndexed8SImm7:
4102 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen30fda452018-04-10 07:01:53 +00004103 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004104 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004105 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004106 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004107 case Match_InvalidImm0_7:
4108 case Match_InvalidImm0_15:
4109 case Match_InvalidImm0_31:
4110 case Match_InvalidImm0_63:
4111 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004112 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004113 case Match_InvalidImm0_65535:
4114 case Match_InvalidImm1_8:
4115 case Match_InvalidImm1_16:
4116 case Match_InvalidImm1_32:
4117 case Match_InvalidImm1_64:
4118 case Match_InvalidIndex1:
4119 case Match_InvalidIndexB:
4120 case Match_InvalidIndexH:
4121 case Match_InvalidIndexS:
4122 case Match_InvalidIndexD:
4123 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004124 case Match_InvalidComplexRotationEven:
4125 case Match_InvalidComplexRotationOdd:
Sander de Smalencd6be962017-12-20 11:02:42 +00004126 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004127 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004128 case Match_InvalidSVEPredicateBReg:
4129 case Match_InvalidSVEPredicateHReg:
4130 case Match_InvalidSVEPredicateSReg:
4131 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004132 case Match_InvalidSVEPredicate3bAnyReg:
4133 case Match_InvalidSVEPredicate3bBReg:
4134 case Match_InvalidSVEPredicate3bHReg:
4135 case Match_InvalidSVEPredicate3bSReg:
4136 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004137 case Match_MSR:
4138 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004139 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004140 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004141 // Any time we get here, there's nothing fancy to do. Just get the
4142 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004143 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004144 if (ErrorLoc == SMLoc())
4145 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004146 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004147 }
4148 }
4149
4150 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004151}
4152
4153/// ParseDirective parses the arm specific directives
4154bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004155 const MCObjectFileInfo::Environment Format =
4156 getContext().getObjectFileInfo()->getObjectFileType();
4157 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4158 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004159
Tim Northover3b0846e2014-05-24 12:50:23 +00004160 StringRef IDVal = DirectiveID.getIdentifier();
4161 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004162 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004163 parseDirectiveArch(Loc);
4164 else if (IDVal == ".cpu")
4165 parseDirectiveCPU(Loc);
4166 else if (IDVal == ".hword")
4167 parseDirectiveWord(2, Loc);
4168 else if (IDVal == ".word")
4169 parseDirectiveWord(4, Loc);
4170 else if (IDVal == ".xword")
4171 parseDirectiveWord(8, Loc);
4172 else if (IDVal == ".tlsdesccall")
4173 parseDirectiveTLSDescCall(Loc);
4174 else if (IDVal == ".ltorg" || IDVal == ".pool")
4175 parseDirectiveLtorg(Loc);
4176 else if (IDVal == ".unreq")
4177 parseDirectiveUnreq(Loc);
4178 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004179 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004180 parseDirectiveInst(Loc);
4181 else
4182 return true;
4183 } else if (IDVal == MCLOHDirectiveName())
4184 parseDirectiveLOH(IDVal, Loc);
4185 else
4186 return true;
4187 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004188}
4189
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004190static const struct {
4191 const char *Name;
4192 const FeatureBitset Features;
4193} ExtensionMap[] = {
4194 { "crc", {AArch64::FeatureCRC} },
4195 { "crypto", {AArch64::FeatureCrypto} },
4196 { "fp", {AArch64::FeatureFPARMv8} },
4197 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004198 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004199 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004200
4201 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004202 { "pan", {} },
4203 { "lor", {} },
4204 { "rdma", {} },
4205 { "profile", {} },
4206};
4207
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004208/// parseDirectiveArch
4209/// ::= .arch token
4210bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4211 SMLoc ArchLoc = getLoc();
4212
4213 StringRef Arch, ExtensionString;
4214 std::tie(Arch, ExtensionString) =
4215 getParser().parseStringToEndOfStatement().trim().split('+');
4216
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004217 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4218 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004219 return Error(ArchLoc, "unknown arch name");
4220
4221 if (parseToken(AsmToken::EndOfStatement))
4222 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004223
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004224 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004225 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004226 AArch64::getArchFeatures(ID, AArch64Features);
4227 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4228 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004229
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004230 MCSubtargetInfo &STI = copySTI();
4231 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4232 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4233
4234 SmallVector<StringRef, 4> RequestedExtensions;
4235 if (!ExtensionString.empty())
4236 ExtensionString.split(RequestedExtensions, '+');
4237
4238 FeatureBitset Features = STI.getFeatureBits();
4239 for (auto Name : RequestedExtensions) {
4240 bool EnableFeature = true;
4241
4242 if (Name.startswith_lower("no")) {
4243 EnableFeature = false;
4244 Name = Name.substr(2);
4245 }
4246
4247 for (const auto &Extension : ExtensionMap) {
4248 if (Extension.Name != Name)
4249 continue;
4250
4251 if (Extension.Features.none())
4252 report_fatal_error("unsupported architectural extension: " + Name);
4253
4254 FeatureBitset ToggleFeatures = EnableFeature
4255 ? (~Features & Extension.Features)
4256 : ( Features & Extension.Features);
4257 uint64_t Features =
4258 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4259 setAvailableFeatures(Features);
4260 break;
4261 }
4262 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004263 return false;
4264}
4265
Tim Northover8b96c7e2017-05-15 19:42:15 +00004266static SMLoc incrementLoc(SMLoc L, int Offset) {
4267 return SMLoc::getFromPointer(L.getPointer() + Offset);
4268}
4269
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004270/// parseDirectiveCPU
4271/// ::= .cpu id
4272bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004273 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004274
4275 StringRef CPU, ExtensionString;
4276 std::tie(CPU, ExtensionString) =
4277 getParser().parseStringToEndOfStatement().trim().split('+');
4278
Nirav Davee833c6c2016-11-08 18:31:04 +00004279 if (parseToken(AsmToken::EndOfStatement))
4280 return true;
4281
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004282 SmallVector<StringRef, 4> RequestedExtensions;
4283 if (!ExtensionString.empty())
4284 ExtensionString.split(RequestedExtensions, '+');
4285
4286 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4287 // once that is tablegen'ed
4288 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004289 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004290 return false;
4291 }
4292
4293 MCSubtargetInfo &STI = copySTI();
4294 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004295 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004296
4297 FeatureBitset Features = STI.getFeatureBits();
4298 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004299 // Advance source location past '+'.
4300 CurLoc = incrementLoc(CurLoc, 1);
4301
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004302 bool EnableFeature = true;
4303
4304 if (Name.startswith_lower("no")) {
4305 EnableFeature = false;
4306 Name = Name.substr(2);
4307 }
4308
Tim Northover8b96c7e2017-05-15 19:42:15 +00004309 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004310 for (const auto &Extension : ExtensionMap) {
4311 if (Extension.Name != Name)
4312 continue;
4313
4314 if (Extension.Features.none())
4315 report_fatal_error("unsupported architectural extension: " + Name);
4316
4317 FeatureBitset ToggleFeatures = EnableFeature
4318 ? (~Features & Extension.Features)
4319 : ( Features & Extension.Features);
4320 uint64_t Features =
4321 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4322 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004323 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004324
4325 break;
4326 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004327
4328 if (!FoundExtension)
4329 Error(CurLoc, "unsupported architectural extension");
4330
4331 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004332 }
4333 return false;
4334}
4335
Tim Northover3b0846e2014-05-24 12:50:23 +00004336/// parseDirectiveWord
4337/// ::= .word [ expression (, expression)* ]
4338bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004339 auto parseOp = [&]() -> bool {
4340 const MCExpr *Value;
4341 if (getParser().parseExpression(Value))
4342 return true;
4343 getParser().getStreamer().EmitValue(Value, Size, L);
4344 return false;
4345 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004346
Nirav Davee833c6c2016-11-08 18:31:04 +00004347 if (parseMany(parseOp))
4348 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004349 return false;
4350}
4351
Chad Rosierdcd2a302014-10-22 20:35:57 +00004352/// parseDirectiveInst
4353/// ::= .inst opcode [, ...]
4354bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004355 if (getLexer().is(AsmToken::EndOfStatement))
4356 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004357
Nirav Davee833c6c2016-11-08 18:31:04 +00004358 auto parseOp = [&]() -> bool {
4359 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004360 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004361 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4362 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004363 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004364 if (check(!Value, L, "expected constant expression"))
4365 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004366 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004367 return false;
4368 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004369
Nirav Davee833c6c2016-11-08 18:31:04 +00004370 if (parseMany(parseOp))
4371 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004372 return false;
4373}
4374
Tim Northover3b0846e2014-05-24 12:50:23 +00004375// parseDirectiveTLSDescCall:
4376// ::= .tlsdesccall symbol
4377bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4378 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004379 if (check(getParser().parseIdentifier(Name), L,
4380 "expected symbol after directive") ||
4381 parseToken(AsmToken::EndOfStatement))
4382 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004383
Jim Grosbach6f482002015-05-18 18:43:14 +00004384 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004385 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4386 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004387
4388 MCInst Inst;
4389 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004390 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004391
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004392 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004393 return false;
4394}
4395
4396/// ::= .loh <lohName | lohId> label1, ..., labelN
4397/// The number of arguments depends on the loh identifier.
4398bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004399 MCLOHType Kind;
4400 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4401 if (getParser().getTok().isNot(AsmToken::Integer))
4402 return TokError("expected an identifier or a number in directive");
4403 // We successfully get a numeric value for the identifier.
4404 // Check if it is valid.
4405 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004406 if (Id <= -1U && !isValidMCLOHType(Id))
4407 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004408 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004409 } else {
4410 StringRef Name = getTok().getIdentifier();
4411 // We successfully parse an identifier.
4412 // Check if it is a recognized one.
4413 int Id = MCLOHNameToId(Name);
4414
4415 if (Id == -1)
4416 return TokError("invalid identifier in directive");
4417 Kind = (MCLOHType)Id;
4418 }
4419 // Consume the identifier.
4420 Lex();
4421 // Get the number of arguments of this LOH.
4422 int NbArgs = MCLOHIdToNbArgs(Kind);
4423
4424 assert(NbArgs != -1 && "Invalid number of arguments");
4425
4426 SmallVector<MCSymbol *, 3> Args;
4427 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4428 StringRef Name;
4429 if (getParser().parseIdentifier(Name))
4430 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004431 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004432
4433 if (Idx + 1 == NbArgs)
4434 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004435 if (parseToken(AsmToken::Comma,
4436 "unexpected token in '" + Twine(IDVal) + "' directive"))
4437 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004438 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004439 if (parseToken(AsmToken::EndOfStatement,
4440 "unexpected token in '" + Twine(IDVal) + "' directive"))
4441 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004442
4443 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4444 return false;
4445}
4446
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004447/// parseDirectiveLtorg
4448/// ::= .ltorg | .pool
4449bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004450 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4451 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004452 getTargetStreamer().emitCurrentConstantPool();
4453 return false;
4454}
4455
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004456/// parseDirectiveReq
4457/// ::= name .req registername
4458bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004459 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004460 Parser.Lex(); // Eat the '.req' token.
4461 SMLoc SRegLoc = getLoc();
Sander de Smalen8e607342017-11-15 15:44:43 +00004462 int RegNum = tryParseRegister();
Florian Hahnc4422242017-11-07 13:07:50 +00004463 RegKind RegisterKind = RegKind::Scalar;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004464
Sander de Smalen8e607342017-11-15 15:44:43 +00004465 if (RegNum == -1) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004466 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004467 RegisterKind = RegKind::NeonVector;
Sander de Smalen73937b72018-04-11 07:36:10 +00004468 OperandMatchResultTy Res =
4469 tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
4470
4471 if (Res == MatchOperand_ParseFail)
4472 return true;
4473
4474 if (Res == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004475 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004476 }
4477
Sander de Smalen8e607342017-11-15 15:44:43 +00004478 if (RegNum == -1) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004479 StringRef Kind;
4480 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen8e607342017-11-15 15:44:43 +00004481 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004482 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004483
4484 if (Res == MatchOperand_ParseFail)
4485 return true;
4486
4487 if (Res == MatchOperand_Success && !Kind.empty())
4488 return Error(SRegLoc,
4489 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004490 }
4491
Sander de Smalencd6be962017-12-20 11:02:42 +00004492 if (RegNum == -1) {
4493 StringRef Kind;
4494 RegisterKind = RegKind::SVEPredicateVector;
4495 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004496 tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004497
4498 if (Res == MatchOperand_ParseFail)
4499 return true;
4500
4501 if (Res == MatchOperand_Success && !Kind.empty())
4502 return Error(SRegLoc,
4503 "sve predicate register without type specifier expected");
4504 }
4505
Sander de Smalen8e607342017-11-15 15:44:43 +00004506 if (RegNum == -1)
Nirav Dave2364748a2016-09-16 18:30:20 +00004507 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004508
4509 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004510 if (parseToken(AsmToken::EndOfStatement,
4511 "unexpected input in .req directive"))
4512 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004513
Sander de Smalen8e607342017-11-15 15:44:43 +00004514 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004515 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004516 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4517
Nirav Dave2364748a2016-09-16 18:30:20 +00004518 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004519}
4520
4521/// parseDirectiveUneq
4522/// ::= .unreq registername
4523bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004524 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004525 if (getTok().isNot(AsmToken::Identifier))
4526 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004527 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4528 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004529 if (parseToken(AsmToken::EndOfStatement))
4530 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004531 return false;
4532}
4533
Tim Northover3b0846e2014-05-24 12:50:23 +00004534bool
4535AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4536 AArch64MCExpr::VariantKind &ELFRefKind,
4537 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4538 int64_t &Addend) {
4539 ELFRefKind = AArch64MCExpr::VK_INVALID;
4540 DarwinRefKind = MCSymbolRefExpr::VK_None;
4541 Addend = 0;
4542
4543 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4544 ELFRefKind = AE->getKind();
4545 Expr = AE->getSubExpr();
4546 }
4547
4548 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4549 if (SE) {
4550 // It's a simple symbol reference with no addend.
4551 DarwinRefKind = SE->getKind();
4552 return true;
4553 }
4554
4555 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4556 if (!BE)
4557 return false;
4558
4559 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4560 if (!SE)
4561 return false;
4562 DarwinRefKind = SE->getKind();
4563
4564 if (BE->getOpcode() != MCBinaryExpr::Add &&
4565 BE->getOpcode() != MCBinaryExpr::Sub)
4566 return false;
4567
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004568 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004569 // on here than we can deal with.
4570 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4571 if (!AddendExpr)
4572 return false;
4573
4574 Addend = AddendExpr->getValue();
4575 if (BE->getOpcode() == MCBinaryExpr::Sub)
4576 Addend = -Addend;
4577
4578 // It's some symbol reference + a constant addend, but really
4579 // shouldn't use both Darwin and ELF syntax.
4580 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4581 DarwinRefKind == MCSymbolRefExpr::VK_None;
4582}
4583
4584/// Force static initialization.
4585extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004586 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4587 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4588 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004589}
4590
4591#define GET_REGISTER_MATCHER
4592#define GET_SUBTARGET_FEATURE_NAME
4593#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004594#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004595#include "AArch64GenAsmMatcher.inc"
4596
4597// Define this matcher function after the auto-generated include so we
4598// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004599unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004600 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004601 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004602 // If the kind is a token for a literal immediate, check if our asm
4603 // operand matches. This is for InstAliases which have a fixed-value
4604 // immediate in the syntax.
4605 int64_t ExpectedVal;
4606 switch (Kind) {
4607 default:
4608 return Match_InvalidOperand;
4609 case MCK__35_0:
4610 ExpectedVal = 0;
4611 break;
4612 case MCK__35_1:
4613 ExpectedVal = 1;
4614 break;
4615 case MCK__35_12:
4616 ExpectedVal = 12;
4617 break;
4618 case MCK__35_16:
4619 ExpectedVal = 16;
4620 break;
4621 case MCK__35_2:
4622 ExpectedVal = 2;
4623 break;
4624 case MCK__35_24:
4625 ExpectedVal = 24;
4626 break;
4627 case MCK__35_3:
4628 ExpectedVal = 3;
4629 break;
4630 case MCK__35_32:
4631 ExpectedVal = 32;
4632 break;
4633 case MCK__35_4:
4634 ExpectedVal = 4;
4635 break;
4636 case MCK__35_48:
4637 ExpectedVal = 48;
4638 break;
4639 case MCK__35_6:
4640 ExpectedVal = 6;
4641 break;
4642 case MCK__35_64:
4643 ExpectedVal = 64;
4644 break;
4645 case MCK__35_8:
4646 ExpectedVal = 8;
4647 break;
4648 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004649 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004650 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004651 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004652 if (!CE)
4653 return Match_InvalidOperand;
4654 if (CE->getValue() == ExpectedVal)
4655 return Match_Success;
4656 return Match_InvalidOperand;
4657}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004658
Alex Bradbury58eba092016-11-01 16:32:05 +00004659OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004660AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4661
4662 SMLoc S = getLoc();
4663
4664 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4665 Error(S, "expected register");
4666 return MatchOperand_ParseFail;
4667 }
4668
4669 int FirstReg = tryParseRegister();
4670 if (FirstReg == -1) {
4671 return MatchOperand_ParseFail;
4672 }
4673 const MCRegisterClass &WRegClass =
4674 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4675 const MCRegisterClass &XRegClass =
4676 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4677
4678 bool isXReg = XRegClass.contains(FirstReg),
4679 isWReg = WRegClass.contains(FirstReg);
4680 if (!isXReg && !isWReg) {
4681 Error(S, "expected first even register of a "
4682 "consecutive same-size even/odd register pair");
4683 return MatchOperand_ParseFail;
4684 }
4685
4686 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4687 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4688
4689 if (FirstEncoding & 0x1) {
4690 Error(S, "expected first even register of a "
4691 "consecutive same-size even/odd register pair");
4692 return MatchOperand_ParseFail;
4693 }
4694
4695 SMLoc M = getLoc();
4696 if (getParser().getTok().isNot(AsmToken::Comma)) {
4697 Error(M, "expected comma");
4698 return MatchOperand_ParseFail;
4699 }
4700 // Eat the comma
4701 getParser().Lex();
4702
4703 SMLoc E = getLoc();
4704 int SecondReg = tryParseRegister();
4705 if (SecondReg ==-1) {
4706 return MatchOperand_ParseFail;
4707 }
4708
Eugene Zelenko049b0172017-01-06 00:30:53 +00004709 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004710 (isXReg && !XRegClass.contains(SecondReg)) ||
4711 (isWReg && !WRegClass.contains(SecondReg))) {
4712 Error(E,"expected second odd register of a "
4713 "consecutive same-size even/odd register pair");
4714 return MatchOperand_ParseFail;
4715 }
Joel Jones504bf332016-10-24 13:37:13 +00004716
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004717 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004718 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004719 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4720 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4721 } else {
4722 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4723 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4724 }
4725
Florian Hahnc4422242017-11-07 13:07:50 +00004726 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4727 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004728
4729 return MatchOperand_Success;
4730}
Florian Hahn91f11e52017-11-07 16:45:48 +00004731
4732template <bool ParseSuffix>
4733OperandMatchResultTy
4734AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004735 const SMLoc S = getLoc();
4736 // Check for a SVE vector register specifier first.
Sander de Smalen8e607342017-11-15 15:44:43 +00004737 int RegNum = -1;
Florian Hahn91f11e52017-11-07 16:45:48 +00004738 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004739
Sander de Smalen8e607342017-11-15 15:44:43 +00004740 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004741 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004742
4743 if (Res != MatchOperand_Success)
4744 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004745
4746 if (ParseSuffix && Kind.empty())
4747 return MatchOperand_NoMatch;
4748
Sander de Smalen73937b72018-04-11 07:36:10 +00004749 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
4750 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00004751 return MatchOperand_NoMatch;
4752
Sander de Smalen73937b72018-04-11 07:36:10 +00004753 unsigned ElementWidth = KindRes->second;
4754 Operands.push_back(AArch64Operand::CreateVectorReg(
4755 RegNum, RegKind::SVEDataVector, ElementWidth, S, S,
4756 getContext()));
Florian Hahn91f11e52017-11-07 16:45:48 +00004757
4758 return MatchOperand_Success;
4759}
Sander de Smalen245e0e62018-01-22 10:46:00 +00004760
4761OperandMatchResultTy
4762AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
4763 MCAsmParser &Parser = getParser();
4764
4765 SMLoc SS = getLoc();
4766 const AsmToken &TokE = Parser.getTok();
4767 bool IsHash = TokE.is(AsmToken::Hash);
4768
4769 if (!IsHash && TokE.isNot(AsmToken::Identifier))
4770 return MatchOperand_NoMatch;
4771
4772 int64_t Pattern;
4773 if (IsHash) {
4774 Parser.Lex(); // Eat hash
4775
4776 // Parse the immediate operand.
4777 const MCExpr *ImmVal;
4778 SS = getLoc();
4779 if (Parser.parseExpression(ImmVal))
4780 return MatchOperand_ParseFail;
4781
4782 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4783 if (!MCE)
4784 return MatchOperand_ParseFail;
4785
4786 Pattern = MCE->getValue();
4787 } else {
4788 // Parse the pattern
4789 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
4790 if (!Pat)
4791 return MatchOperand_NoMatch;
4792
4793 Parser.Lex();
4794 Pattern = Pat->Encoding;
4795 assert(Pattern >= 0 && Pattern < 32);
4796 }
4797
4798 Operands.push_back(
4799 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
4800 SS, getLoc(), getContext()));
4801
4802 return MatchOperand_Success;
4803}