blob: ff553ecd16f8cf20bc82ea2cf9142085edc21f4a [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/AArch64AddressingModes.h"
11#include "MCTargetDesc/AArch64MCExpr.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000012#include "MCTargetDesc/AArch64MCTargetDesc.h"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000013#include "MCTargetDesc/AArch64TargetStreamer.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000014#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000015#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000016#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000017#include "llvm/ADT/ArrayRef.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000018#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "llvm/ADT/SmallVector.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000020#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000021#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000023#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000025#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000028#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000029#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000030#include "llvm/MC/MCParser/MCAsmLexer.h"
31#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000032#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000033#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000034#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000035#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSubtargetInfo.h"
38#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000039#include "llvm/MC/MCTargetOptions.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000043#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000044#include "llvm/Support/MathExtras.h"
45#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000046#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000047#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000049#include <cassert>
50#include <cctype>
51#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000052#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000053#include <string>
54#include <tuple>
55#include <utility>
56#include <vector>
57
Tim Northover3b0846e2014-05-24 12:50:23 +000058using namespace llvm;
59
60namespace {
61
Sander de Smalencd6be962017-12-20 11:02:42 +000062enum class RegKind {
63 Scalar,
64 NeonVector,
65 SVEDataVector,
66 SVEPredicateVector
67};
Florian Hahnc4422242017-11-07 13:07:50 +000068
Tim Northover3b0846e2014-05-24 12:50:23 +000069class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000070private:
71 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000072
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000073 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000074 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000075
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000076 AArch64TargetStreamer &getTargetStreamer() {
77 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
78 return static_cast<AArch64TargetStreamer &>(TS);
79 }
80
Rafael Espindola961d4692014-11-11 05:18:41 +000081 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000082
83 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +000084 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +000085 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
86 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +000087 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +000088 int tryParseRegister();
89 int tryMatchVectorRegister(StringRef &Kind, bool expected);
90 bool parseRegister(OperandVector &Operands);
91 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
92 bool parseVectorList(OperandVector &Operands);
93 bool parseOperand(OperandVector &Operands, bool isCondCode,
94 bool invertCondCode);
95
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +000096 bool showMatchError(SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000097
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000098 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000099 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000100 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +0000101 bool parseDirectiveInst(SMLoc L);
102
Tim Northover3b0846e2014-05-24 12:50:23 +0000103 bool parseDirectiveTLSDescCall(SMLoc L);
104
105 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000106 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000107
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000108 bool parseDirectiveReq(StringRef Name, SMLoc L);
109 bool parseDirectiveUnreq(SMLoc L);
110
Tim Northover3b0846e2014-05-24 12:50:23 +0000111 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
112 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
113 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000114 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000115 bool MatchingInlineAsm) override;
116/// @name Auto-generated Match Functions
117/// {
118
119#define GET_ASSEMBLER_HEADER
120#include "AArch64GenAsmMatcher.inc"
121
122 /// }
123
Sander de Smalen8e607342017-11-15 15:44:43 +0000124 OperandMatchResultTy tryParseSVERegister(int &Reg, StringRef &Kind,
125 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000126 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
127 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
128 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
129 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
130 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
131 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000132 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000133 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
134 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
135 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
136 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
137 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000138 bool tryParseNeonVectorRegister(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000139 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Florian Hahn91f11e52017-11-07 16:45:48 +0000140 template <bool ParseSuffix>
141 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000142 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen245e0e62018-01-22 10:46:00 +0000143 LLVM_ATTRIBUTE_UNUSED OperandMatchResultTy
144 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 ||
522 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) {
523 // Note that we don't range-check the addend. It's adjusted modulo page
524 // size when converted, so there is no "out of range" condition when using
525 // @pageoff.
526 return Addend >= 0 && (Addend % Scale) == 0;
527 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
528 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
529 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
530 return Addend == 0;
531 }
532
533 return false;
534 }
535
536 template <int Scale> bool isUImm12Offset() const {
537 if (!isImm())
538 return false;
539
540 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
541 if (!MCE)
542 return isSymbolicUImm12Offset(getImm(), Scale);
543
544 int64_t Val = MCE->getValue();
545 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
546 }
547
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000548 template <int N, int M>
549 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000550 if (!isImm())
551 return false;
552 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
553 if (!MCE)
554 return false;
555 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000556 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000557 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000558
Tim Northover3b0846e2014-05-24 12:50:23 +0000559 bool isLogicalImm32() const {
560 if (!isImm())
561 return false;
562 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
563 if (!MCE)
564 return false;
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000565 int64_t Val = MCE->getValue();
566 if (Val >> 32 != 0 && Val >> 32 != ~0LL)
567 return false;
568 Val &= 0xFFFFFFFF;
569 return AArch64_AM::isLogicalImmediate(Val, 32);
Tim Northover3b0846e2014-05-24 12:50:23 +0000570 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000571
Tim Northover3b0846e2014-05-24 12:50:23 +0000572 bool isLogicalImm64() const {
573 if (!isImm())
574 return false;
575 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
576 if (!MCE)
577 return false;
578 return AArch64_AM::isLogicalImmediate(MCE->getValue(), 64);
579 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000580
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000581 bool isLogicalImm32Not() const {
582 if (!isImm())
583 return false;
584 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
585 if (!MCE)
586 return false;
587 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
588 return AArch64_AM::isLogicalImmediate(Val, 32);
589 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000590
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000591 bool isLogicalImm64Not() const {
592 if (!isImm())
593 return false;
594 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
595 if (!MCE)
596 return false;
597 return AArch64_AM::isLogicalImmediate(~MCE->getValue(), 64);
598 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000599
Tim Northover3b0846e2014-05-24 12:50:23 +0000600 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000601
Tim Northover3b0846e2014-05-24 12:50:23 +0000602 bool isAddSubImm() const {
603 if (!isShiftedImm() && !isImm())
604 return false;
605
606 const MCExpr *Expr;
607
608 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
609 if (isShiftedImm()) {
610 unsigned Shift = ShiftedImm.ShiftAmount;
611 Expr = ShiftedImm.Val;
612 if (Shift != 0 && Shift != 12)
613 return false;
614 } else {
615 Expr = getImm();
616 }
617
618 AArch64MCExpr::VariantKind ELFRefKind;
619 MCSymbolRefExpr::VariantKind DarwinRefKind;
620 int64_t Addend;
621 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
622 DarwinRefKind, Addend)) {
623 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
624 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
625 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
626 || ELFRefKind == AArch64MCExpr::VK_LO12
627 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
628 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
629 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
630 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
631 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
632 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
633 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12;
634 }
635
Diana Picusc93518d2016-10-11 09:17:47 +0000636 // If it's a constant, it should be a real immediate in range:
637 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
638 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
639
640 // If it's an expression, we hope for the best and let the fixup/relocation
641 // code deal with it.
642 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000643 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000644
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000645 bool isAddSubImmNeg() const {
646 if (!isShiftedImm() && !isImm())
647 return false;
648
649 const MCExpr *Expr;
650
651 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
652 if (isShiftedImm()) {
653 unsigned Shift = ShiftedImm.ShiftAmount;
654 Expr = ShiftedImm.Val;
655 if (Shift != 0 && Shift != 12)
656 return false;
657 } else
658 Expr = getImm();
659
660 // Otherwise it should be a real negative immediate in range:
661 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
662 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
663 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000664
Tim Northover3b0846e2014-05-24 12:50:23 +0000665 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000666
Tim Northover3b0846e2014-05-24 12:50:23 +0000667 bool isSIMDImmType10() const {
668 if (!isImm())
669 return false;
670 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
671 if (!MCE)
672 return false;
673 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
674 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000675
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000676 template<int N>
677 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000678 if (!isImm())
679 return false;
680 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
681 if (!MCE)
682 return true;
683 int64_t Val = MCE->getValue();
684 if (Val & 0x3)
685 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000686 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
687 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000688 }
689
690 bool
691 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
692 if (!isImm())
693 return false;
694
695 AArch64MCExpr::VariantKind ELFRefKind;
696 MCSymbolRefExpr::VariantKind DarwinRefKind;
697 int64_t Addend;
698 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
699 DarwinRefKind, Addend)) {
700 return false;
701 }
702 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
703 return false;
704
705 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
706 if (ELFRefKind == AllowedModifiers[i])
707 return Addend == 0;
708 }
709
710 return false;
711 }
712
713 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000714 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000715 }
716
717 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000718 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
719 AArch64MCExpr::VK_TPREL_G2,
720 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000721 }
722
723 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000724 return isMovWSymbol({
725 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000726 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
727 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000728 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000729 }
730
731 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000732 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
733 AArch64MCExpr::VK_TPREL_G0,
734 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000735 }
736
737 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000738 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000739 }
740
741 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000742 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000743 }
744
745 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000746 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
747 AArch64MCExpr::VK_TPREL_G1_NC,
748 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000749 }
750
751 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000752 return isMovWSymbol(
753 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
754 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000755 }
756
757 template<int RegWidth, int Shift>
758 bool isMOVZMovAlias() const {
759 if (!isImm()) return false;
760
761 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
762 if (!CE) return false;
763 uint64_t Value = CE->getValue();
764
Tim Northoverdaa1c012016-06-16 01:42:25 +0000765 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000766 }
767
768 template<int RegWidth, int Shift>
769 bool isMOVNMovAlias() const {
770 if (!isImm()) return false;
771
772 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
773 if (!CE) return false;
774 uint64_t Value = CE->getValue();
775
Tim Northoverdaa1c012016-06-16 01:42:25 +0000776 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000777 }
778
779 bool isFPImm() const { return Kind == k_FPImm; }
780 bool isBarrier() const { return Kind == k_Barrier; }
781 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000782
Tim Northover3b0846e2014-05-24 12:50:23 +0000783 bool isMRSSystemRegister() const {
784 if (!isSysReg()) return false;
785
Tim Northover7cd58932015-01-22 17:23:04 +0000786 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000787 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000788
Tim Northover3b0846e2014-05-24 12:50:23 +0000789 bool isMSRSystemRegister() const {
790 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000791 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000792 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000793
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000794 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000795 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000796 return (SysReg.PStateField == AArch64PState::PAN ||
797 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000798 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000799
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000800 bool isSystemPStateFieldWithImm0_15() const {
801 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000802 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000803 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000804
Florian Hahnc4422242017-11-07 13:07:50 +0000805 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000806 return Kind == k_Register;
807 }
808
809 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000810 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
811 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000812
Florian Hahnc4422242017-11-07 13:07:50 +0000813 bool isNeonVectorReg() const {
814 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
815 }
816
817 bool isNeonVectorRegLo() const {
818 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000819 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
820 Reg.RegNum);
821 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000822
Sander de Smalencd6be962017-12-20 11:02:42 +0000823 template <unsigned Class> bool isSVEVectorReg() const {
824 RegKind RK;
825 switch (Class) {
826 case AArch64::ZPRRegClassID:
827 RK = RegKind::SVEDataVector;
828 break;
829 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000830 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000831 RK = RegKind::SVEPredicateVector;
832 break;
833 default:
834 llvm_unreachable("Unsupport register class");
835 }
836
837 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000838 AArch64MCRegisterClasses[Class].contains(getReg());
839 }
840
Sander de Smalencd6be962017-12-20 11:02:42 +0000841 template <int ElementWidth, unsigned Class>
842 bool isSVEVectorRegOfWidth() const {
843 return isSVEVectorReg<Class>() &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000844 (ElementWidth == -1 || Reg.ElementWidth == ElementWidth);
845 }
846
Tim Northover3b0846e2014-05-24 12:50:23 +0000847 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000848 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000849 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
850 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000851
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000852 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000853 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000854 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
855 Reg.RegNum);
856 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000857
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000858 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000859 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000860 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
861 Reg.RegNum);
862 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000863
864 bool isGPR64sp0() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000865 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000866 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
867 }
868
Sam Parker5f934642017-08-31 09:27:04 +0000869 template<int64_t Angle, int64_t Remainder>
870 bool isComplexRotation() const {
871 if (!isImm()) return false;
872
873 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
874 if (!CE) return false;
875 uint64_t Value = CE->getValue();
876
877 return (Value % Angle == Remainder && Value <= 270);
878 }
879
Tim Northover3b0846e2014-05-24 12:50:23 +0000880 /// Is this a vector list with the type implicit (presumably attached to the
881 /// instruction itself)?
882 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
883 return Kind == k_VectorList && VectorList.Count == NumRegs &&
884 !VectorList.ElementKind;
885 }
886
887 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
888 bool isTypedVectorList() const {
889 if (Kind != k_VectorList)
890 return false;
891 if (VectorList.Count != NumRegs)
892 return false;
893 if (VectorList.ElementKind != ElementKind)
894 return false;
895 return VectorList.NumElements == NumElements;
896 }
897
898 bool isVectorIndex1() const {
899 return Kind == k_VectorIndex && VectorIndex.Val == 1;
900 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000901
Tim Northover3b0846e2014-05-24 12:50:23 +0000902 bool isVectorIndexB() const {
903 return Kind == k_VectorIndex && VectorIndex.Val < 16;
904 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000905
Tim Northover3b0846e2014-05-24 12:50:23 +0000906 bool isVectorIndexH() const {
907 return Kind == k_VectorIndex && VectorIndex.Val < 8;
908 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000909
Tim Northover3b0846e2014-05-24 12:50:23 +0000910 bool isVectorIndexS() const {
911 return Kind == k_VectorIndex && VectorIndex.Val < 4;
912 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000913
Tim Northover3b0846e2014-05-24 12:50:23 +0000914 bool isVectorIndexD() const {
915 return Kind == k_VectorIndex && VectorIndex.Val < 2;
916 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000917
Tim Northover3b0846e2014-05-24 12:50:23 +0000918 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000919
Tim Northover3b0846e2014-05-24 12:50:23 +0000920 bool isTokenEqual(StringRef Str) const {
921 return Kind == k_Token && getToken() == Str;
922 }
923 bool isSysCR() const { return Kind == k_SysCR; }
924 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000925 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000926 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
927 bool isShifter() const {
928 if (!isShiftExtend())
929 return false;
930
931 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
932 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
933 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
934 ST == AArch64_AM::MSL);
935 }
936 bool isExtend() const {
937 if (!isShiftExtend())
938 return false;
939
940 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
941 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
942 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
943 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
944 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
945 ET == AArch64_AM::LSL) &&
946 getShiftExtendAmount() <= 4;
947 }
948
949 bool isExtend64() const {
950 if (!isExtend())
951 return false;
952 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
953 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
954 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
955 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000956
Tim Northover3b0846e2014-05-24 12:50:23 +0000957 bool isExtendLSL64() const {
958 if (!isExtend())
959 return false;
960 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
961 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
962 ET == AArch64_AM::LSL) &&
963 getShiftExtendAmount() <= 4;
964 }
965
966 template<int Width> bool isMemXExtend() const {
967 if (!isExtend())
968 return false;
969 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
970 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
971 (getShiftExtendAmount() == Log2_32(Width / 8) ||
972 getShiftExtendAmount() == 0);
973 }
974
975 template<int Width> bool isMemWExtend() const {
976 if (!isExtend())
977 return false;
978 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
979 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
980 (getShiftExtendAmount() == Log2_32(Width / 8) ||
981 getShiftExtendAmount() == 0);
982 }
983
984 template <unsigned width>
985 bool isArithmeticShifter() const {
986 if (!isShifter())
987 return false;
988
989 // An arithmetic shifter is LSL, LSR, or ASR.
990 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
991 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
992 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
993 }
994
995 template <unsigned width>
996 bool isLogicalShifter() const {
997 if (!isShifter())
998 return false;
999
1000 // A logical shifter is LSL, LSR, ASR or ROR.
1001 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1002 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1003 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1004 getShiftExtendAmount() < width;
1005 }
1006
1007 bool isMovImm32Shifter() const {
1008 if (!isShifter())
1009 return false;
1010
1011 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1012 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1013 if (ST != AArch64_AM::LSL)
1014 return false;
1015 uint64_t Val = getShiftExtendAmount();
1016 return (Val == 0 || Val == 16);
1017 }
1018
1019 bool isMovImm64Shifter() const {
1020 if (!isShifter())
1021 return false;
1022
1023 // A MOVi shifter is LSL of 0 or 16.
1024 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1025 if (ST != AArch64_AM::LSL)
1026 return false;
1027 uint64_t Val = getShiftExtendAmount();
1028 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1029 }
1030
1031 bool isLogicalVecShifter() const {
1032 if (!isShifter())
1033 return false;
1034
1035 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1036 unsigned Shift = getShiftExtendAmount();
1037 return getShiftExtendType() == AArch64_AM::LSL &&
1038 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1039 }
1040
1041 bool isLogicalVecHalfWordShifter() const {
1042 if (!isLogicalVecShifter())
1043 return false;
1044
1045 // A logical vector shifter is a left shift by 0 or 8.
1046 unsigned Shift = getShiftExtendAmount();
1047 return getShiftExtendType() == AArch64_AM::LSL &&
1048 (Shift == 0 || Shift == 8);
1049 }
1050
1051 bool isMoveVecShifter() const {
1052 if (!isShiftExtend())
1053 return false;
1054
1055 // A logical vector shifter is a left shift by 8 or 16.
1056 unsigned Shift = getShiftExtendAmount();
1057 return getShiftExtendType() == AArch64_AM::MSL &&
1058 (Shift == 8 || Shift == 16);
1059 }
1060
1061 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1062 // to LDUR/STUR when the offset is not legal for the former but is for
1063 // the latter. As such, in addition to checking for being a legal unscaled
1064 // address, also check that it is not a legal scaled address. This avoids
1065 // ambiguity in the matcher.
1066 template<int Width>
1067 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001068 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001069 }
1070
1071 bool isAdrpLabel() const {
1072 // Validation was handled during parsing, so we just sanity check that
1073 // something didn't go haywire.
1074 if (!isImm())
1075 return false;
1076
1077 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1078 int64_t Val = CE->getValue();
1079 int64_t Min = - (4096 * (1LL << (21 - 1)));
1080 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1081 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1082 }
1083
1084 return true;
1085 }
1086
1087 bool isAdrLabel() const {
1088 // Validation was handled during parsing, so we just sanity check that
1089 // something didn't go haywire.
1090 if (!isImm())
1091 return false;
1092
1093 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1094 int64_t Val = CE->getValue();
1095 int64_t Min = - (1LL << (21 - 1));
1096 int64_t Max = ((1LL << (21 - 1)) - 1);
1097 return Val >= Min && Val <= Max;
1098 }
1099
1100 return true;
1101 }
1102
1103 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1104 // Add as immediates when possible. Null MCExpr = 0.
1105 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001106 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001107 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001108 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001109 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001110 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001111 }
1112
1113 void addRegOperands(MCInst &Inst, unsigned N) const {
1114 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001115 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001116 }
1117
1118 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1119 assert(N == 1 && "Invalid number of operands!");
1120 assert(
1121 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1122
1123 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1124 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1125 RI->getEncodingValue(getReg()));
1126
Jim Grosbache9119e42015-05-13 18:37:00 +00001127 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001128 }
1129
1130 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1131 assert(N == 1 && "Invalid number of operands!");
1132 assert(
1133 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001134 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001135 }
1136
1137 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1138 assert(N == 1 && "Invalid number of operands!");
1139 assert(
1140 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001141 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001142 }
1143
1144 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1145 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001146 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001147 }
1148
1149 template <unsigned NumRegs>
1150 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1151 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001152 static const unsigned FirstRegs[] = { AArch64::D0,
1153 AArch64::D0_D1,
1154 AArch64::D0_D1_D2,
1155 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001156 unsigned FirstReg = FirstRegs[NumRegs - 1];
1157
1158 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001159 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001160 }
1161
1162 template <unsigned NumRegs>
1163 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1164 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001165 static const unsigned FirstRegs[] = { AArch64::Q0,
1166 AArch64::Q0_Q1,
1167 AArch64::Q0_Q1_Q2,
1168 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001169 unsigned FirstReg = FirstRegs[NumRegs - 1];
1170
1171 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001172 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001173 }
1174
1175 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1176 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001177 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001178 }
1179
1180 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1181 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001182 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001183 }
1184
1185 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1186 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001187 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001188 }
1189
1190 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1191 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001192 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001193 }
1194
1195 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1196 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001197 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001198 }
1199
1200 void addImmOperands(MCInst &Inst, unsigned N) const {
1201 assert(N == 1 && "Invalid number of operands!");
1202 // If this is a pageoff symrefexpr with an addend, adjust the addend
1203 // to be only the page-offset portion. Otherwise, just add the expr
1204 // as-is.
1205 addExpr(Inst, getImm());
1206 }
1207
1208 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1209 assert(N == 2 && "Invalid number of operands!");
1210 if (isShiftedImm()) {
1211 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001212 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001213 } else {
1214 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001215 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001216 }
1217 }
1218
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001219 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1220 assert(N == 2 && "Invalid number of operands!");
1221
1222 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1223 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1224 int64_t Val = -CE->getValue();
1225 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1226
1227 Inst.addOperand(MCOperand::createImm(Val));
1228 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1229 }
1230
Tim Northover3b0846e2014-05-24 12:50:23 +00001231 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1232 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001233 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001234 }
1235
1236 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1237 assert(N == 1 && "Invalid number of operands!");
1238 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1239 if (!MCE)
1240 addExpr(Inst, getImm());
1241 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001242 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001243 }
1244
1245 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1246 addImmOperands(Inst, N);
1247 }
1248
1249 template<int Scale>
1250 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1251 assert(N == 1 && "Invalid number of operands!");
1252 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1253
1254 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001255 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001256 return;
1257 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001258 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001259 }
1260
1261 void addSImm9Operands(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()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001265 }
1266
Sam Parker6d42de72017-08-11 13:14:00 +00001267 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1268 assert(N == 1 && "Invalid number of operands!");
1269 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1270 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1271 }
1272
Tim Northover3b0846e2014-05-24 12:50:23 +00001273 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1274 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001275 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001276 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001277 }
1278
1279 void addSImm7s8Operands(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() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001283 }
1284
1285 void addSImm7s16Operands(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() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001289 }
1290
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001291 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1292 assert(N == 1 && "Invalid number of operands!");
1293 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1294 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1295 }
1296
Tim Northover3b0846e2014-05-24 12:50:23 +00001297 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1298 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001299 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001300 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001301 }
1302
1303 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1304 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001305 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001306 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001307 }
1308
1309 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1310 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001311 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001312 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001313 }
1314
1315 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1316 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001317 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001318 assert(MCE && "Invalid constant immediate operand!");
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_31Operands(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_31Operands(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_32Operands(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_63Operands(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 addImm1_63Operands(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 addImm1_64Operands(MCInst &Inst, unsigned N) const {
1353 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001354 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001355 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001356 }
1357
1358 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1359 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001360 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001361 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001362 }
1363
1364 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1365 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001366 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001367 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001368 }
1369
1370 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1371 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001372 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001373 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001374 }
1375
1376 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1377 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001378 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001379 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001380 }
1381
1382 void addLogicalImm32Operands(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());
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +00001385 uint64_t encoding =
1386 AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001387 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001388 }
1389
1390 void addLogicalImm64Operands(MCInst &Inst, unsigned N) const {
1391 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001392 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001393 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001394 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001395 }
1396
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001397 void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
1398 assert(N == 1 && "Invalid number of operands!");
1399 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1400 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
1401 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001402 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001403 }
1404
1405 void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
1406 assert(N == 1 && "Invalid number of operands!");
1407 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1408 uint64_t encoding =
1409 AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001410 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001411 }
1412
Tim Northover3b0846e2014-05-24 12:50:23 +00001413 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1414 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001415 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001416 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001417 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001418 }
1419
1420 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1421 // Branch operands don't encode the low bits, so shift them off
1422 // here. If it's a label, however, just put it on directly as there's
1423 // not enough information now to do anything.
1424 assert(N == 1 && "Invalid number of operands!");
1425 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1426 if (!MCE) {
1427 addExpr(Inst, getImm());
1428 return;
1429 }
1430 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001431 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001432 }
1433
1434 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1435 // Branch operands don't encode the low bits, so shift them off
1436 // here. If it's a label, however, just put it on directly as there's
1437 // not enough information now to do anything.
1438 assert(N == 1 && "Invalid number of operands!");
1439 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1440 if (!MCE) {
1441 addExpr(Inst, getImm());
1442 return;
1443 }
1444 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001445 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001446 }
1447
1448 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1449 // Branch operands don't encode the low bits, so shift them off
1450 // here. If it's a label, however, just put it on directly as there's
1451 // not enough information now to do anything.
1452 assert(N == 1 && "Invalid number of operands!");
1453 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1454 if (!MCE) {
1455 addExpr(Inst, getImm());
1456 return;
1457 }
1458 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001459 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001460 }
1461
1462 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1463 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001464 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001465 }
1466
1467 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1468 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001469 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001470 }
1471
1472 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1473 assert(N == 1 && "Invalid number of operands!");
1474
Jim Grosbache9119e42015-05-13 18:37:00 +00001475 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001476 }
1477
1478 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1479 assert(N == 1 && "Invalid number of operands!");
1480
Jim Grosbache9119e42015-05-13 18:37:00 +00001481 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001482 }
1483
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001484 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1485 assert(N == 1 && "Invalid number of operands!");
1486
1487 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1488 }
1489
1490 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001491 assert(N == 1 && "Invalid number of operands!");
1492
Jim Grosbache9119e42015-05-13 18:37:00 +00001493 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001494 }
1495
1496 void addSysCROperands(MCInst &Inst, unsigned N) const {
1497 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001498 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001499 }
1500
1501 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1502 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001503 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001504 }
1505
Oliver Stannarda34e4702015-12-01 10:48:51 +00001506 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1507 assert(N == 1 && "Invalid number of operands!");
1508 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1509 }
1510
Tim Northover3b0846e2014-05-24 12:50:23 +00001511 void addShifterOperands(MCInst &Inst, unsigned N) const {
1512 assert(N == 1 && "Invalid number of operands!");
1513 unsigned Imm =
1514 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001515 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001516 }
1517
1518 void addExtendOperands(MCInst &Inst, unsigned N) const {
1519 assert(N == 1 && "Invalid number of operands!");
1520 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1521 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1522 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001523 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001524 }
1525
1526 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1527 assert(N == 1 && "Invalid number of operands!");
1528 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1529 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1530 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001531 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001532 }
1533
1534 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1535 assert(N == 2 && "Invalid number of operands!");
1536 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1537 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001538 Inst.addOperand(MCOperand::createImm(IsSigned));
1539 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001540 }
1541
1542 // For 8-bit load/store instructions with a register offset, both the
1543 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1544 // they're disambiguated by whether the shift was explicit or implicit rather
1545 // than its size.
1546 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1547 assert(N == 2 && "Invalid number of operands!");
1548 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1549 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001550 Inst.addOperand(MCOperand::createImm(IsSigned));
1551 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001552 }
1553
1554 template<int Shift>
1555 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1556 assert(N == 1 && "Invalid number of operands!");
1557
1558 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1559 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001560 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001561 }
1562
1563 template<int Shift>
1564 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1565 assert(N == 1 && "Invalid number of operands!");
1566
1567 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1568 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001569 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001570 }
1571
Sam Parker5f934642017-08-31 09:27:04 +00001572 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1573 assert(N == 1 && "Invalid number of operands!");
1574 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1575 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1576 }
1577
1578 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1579 assert(N == 1 && "Invalid number of operands!");
1580 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1581 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1582 }
1583
Tim Northover3b0846e2014-05-24 12:50:23 +00001584 void print(raw_ostream &OS) const override;
1585
David Blaikie960ea3f2014-06-08 16:18:35 +00001586 static std::unique_ptr<AArch64Operand>
1587 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1588 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001589 Op->Tok.Data = Str.data();
1590 Op->Tok.Length = Str.size();
1591 Op->Tok.IsSuffix = IsSuffix;
1592 Op->StartLoc = S;
1593 Op->EndLoc = S;
1594 return Op;
1595 }
1596
David Blaikie960ea3f2014-06-08 16:18:35 +00001597 static std::unique_ptr<AArch64Operand>
Florian Hahnc4422242017-11-07 13:07:50 +00001598 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001599 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001600 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001601 Op->Reg.Kind = Kind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001602 Op->StartLoc = S;
1603 Op->EndLoc = E;
1604 return Op;
1605 }
1606
David Blaikie960ea3f2014-06-08 16:18:35 +00001607 static std::unique_ptr<AArch64Operand>
Florian Hahn91f11e52017-11-07 16:45:48 +00001608 CreateReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1609 SMLoc S, SMLoc E, MCContext &Ctx) {
1610 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1611 Op->Reg.RegNum = RegNum;
1612 Op->Reg.ElementWidth = ElementWidth;
1613 Op->Reg.Kind = Kind;
1614 Op->StartLoc = S;
1615 Op->EndLoc = E;
1616 return Op;
1617 }
1618
1619 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001620 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1621 char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1622 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001623 Op->VectorList.RegNum = RegNum;
1624 Op->VectorList.Count = Count;
1625 Op->VectorList.NumElements = NumElements;
1626 Op->VectorList.ElementKind = ElementKind;
1627 Op->StartLoc = S;
1628 Op->EndLoc = E;
1629 return Op;
1630 }
1631
David Blaikie960ea3f2014-06-08 16:18:35 +00001632 static std::unique_ptr<AArch64Operand>
1633 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1634 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001635 Op->VectorIndex.Val = Idx;
1636 Op->StartLoc = S;
1637 Op->EndLoc = E;
1638 return Op;
1639 }
1640
David Blaikie960ea3f2014-06-08 16:18:35 +00001641 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1642 SMLoc E, MCContext &Ctx) {
1643 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001644 Op->Imm.Val = Val;
1645 Op->StartLoc = S;
1646 Op->EndLoc = E;
1647 return Op;
1648 }
1649
David Blaikie960ea3f2014-06-08 16:18:35 +00001650 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1651 unsigned ShiftAmount,
1652 SMLoc S, SMLoc E,
1653 MCContext &Ctx) {
1654 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001655 Op->ShiftedImm .Val = Val;
1656 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1657 Op->StartLoc = S;
1658 Op->EndLoc = E;
1659 return Op;
1660 }
1661
David Blaikie960ea3f2014-06-08 16:18:35 +00001662 static std::unique_ptr<AArch64Operand>
1663 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1664 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001665 Op->CondCode.Code = Code;
1666 Op->StartLoc = S;
1667 Op->EndLoc = E;
1668 return Op;
1669 }
1670
David Blaikie960ea3f2014-06-08 16:18:35 +00001671 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1672 MCContext &Ctx) {
1673 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001674 Op->FPImm.Val = Val;
1675 Op->StartLoc = S;
1676 Op->EndLoc = S;
1677 return Op;
1678 }
1679
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001680 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1681 StringRef Str,
1682 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001683 MCContext &Ctx) {
1684 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001685 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001686 Op->Barrier.Data = Str.data();
1687 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001688 Op->StartLoc = S;
1689 Op->EndLoc = S;
1690 return Op;
1691 }
1692
Tim Northover7cd58932015-01-22 17:23:04 +00001693 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1694 uint32_t MRSReg,
1695 uint32_t MSRReg,
1696 uint32_t PStateField,
1697 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001698 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001699 Op->SysReg.Data = Str.data();
1700 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001701 Op->SysReg.MRSReg = MRSReg;
1702 Op->SysReg.MSRReg = MSRReg;
1703 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001704 Op->StartLoc = S;
1705 Op->EndLoc = S;
1706 return Op;
1707 }
1708
David Blaikie960ea3f2014-06-08 16:18:35 +00001709 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1710 SMLoc E, MCContext &Ctx) {
1711 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001712 Op->SysCRImm.Val = Val;
1713 Op->StartLoc = S;
1714 Op->EndLoc = E;
1715 return Op;
1716 }
1717
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001718 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1719 StringRef Str,
1720 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001721 MCContext &Ctx) {
1722 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001723 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001724 Op->Barrier.Data = Str.data();
1725 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001726 Op->StartLoc = S;
1727 Op->EndLoc = S;
1728 return Op;
1729 }
1730
Oliver Stannarda34e4702015-12-01 10:48:51 +00001731 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1732 StringRef Str,
1733 SMLoc S,
1734 MCContext &Ctx) {
1735 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1736 Op->PSBHint.Val = Val;
1737 Op->PSBHint.Data = Str.data();
1738 Op->PSBHint.Length = Str.size();
1739 Op->StartLoc = S;
1740 Op->EndLoc = S;
1741 return Op;
1742 }
1743
David Blaikie960ea3f2014-06-08 16:18:35 +00001744 static std::unique_ptr<AArch64Operand>
1745 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1746 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1747 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001748 Op->ShiftExtend.Type = ShOp;
1749 Op->ShiftExtend.Amount = Val;
1750 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1751 Op->StartLoc = S;
1752 Op->EndLoc = E;
1753 return Op;
1754 }
1755};
1756
1757} // end anonymous namespace.
1758
1759void AArch64Operand::print(raw_ostream &OS) const {
1760 switch (Kind) {
1761 case k_FPImm:
1762 OS << "<fpimm " << getFPImm() << "("
1763 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1764 break;
1765 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001766 StringRef Name = getBarrierName();
1767 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001768 OS << "<barrier " << Name << ">";
1769 else
1770 OS << "<barrier invalid #" << getBarrier() << ">";
1771 break;
1772 }
1773 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001774 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001775 break;
1776 case k_ShiftedImm: {
1777 unsigned Shift = getShiftedImmShift();
1778 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001779 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001780 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1781 break;
1782 }
1783 case k_CondCode:
1784 OS << "<condcode " << getCondCode() << ">";
1785 break;
1786 case k_Register:
1787 OS << "<register " << getReg() << ">";
1788 break;
1789 case k_VectorList: {
1790 OS << "<vectorlist ";
1791 unsigned Reg = getVectorListStart();
1792 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1793 OS << Reg + i << " ";
1794 OS << ">";
1795 break;
1796 }
1797 case k_VectorIndex:
1798 OS << "<vectorindex " << getVectorIndex() << ">";
1799 break;
1800 case k_SysReg:
1801 OS << "<sysreg: " << getSysReg() << '>';
1802 break;
1803 case k_Token:
1804 OS << "'" << getToken() << "'";
1805 break;
1806 case k_SysCR:
1807 OS << "c" << getSysCR();
1808 break;
1809 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001810 StringRef Name = getPrefetchName();
1811 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001812 OS << "<prfop " << Name << ">";
1813 else
1814 OS << "<prfop invalid #" << getPrefetch() << ">";
1815 break;
1816 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001817 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001818 OS << getPSBHintName();
1819 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001820 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001821 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1822 << getShiftExtendAmount();
1823 if (!hasShiftExtendAmount())
1824 OS << "<imp>";
1825 OS << '>';
1826 break;
1827 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001828}
1829
1830/// @name Auto-generated Match Functions
1831/// {
1832
1833static unsigned MatchRegisterName(StringRef Name);
1834
1835/// }
1836
Florian Hahnc4422242017-11-07 13:07:50 +00001837static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001838 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001839 .Case("v0", AArch64::Q0)
1840 .Case("v1", AArch64::Q1)
1841 .Case("v2", AArch64::Q2)
1842 .Case("v3", AArch64::Q3)
1843 .Case("v4", AArch64::Q4)
1844 .Case("v5", AArch64::Q5)
1845 .Case("v6", AArch64::Q6)
1846 .Case("v7", AArch64::Q7)
1847 .Case("v8", AArch64::Q8)
1848 .Case("v9", AArch64::Q9)
1849 .Case("v10", AArch64::Q10)
1850 .Case("v11", AArch64::Q11)
1851 .Case("v12", AArch64::Q12)
1852 .Case("v13", AArch64::Q13)
1853 .Case("v14", AArch64::Q14)
1854 .Case("v15", AArch64::Q15)
1855 .Case("v16", AArch64::Q16)
1856 .Case("v17", AArch64::Q17)
1857 .Case("v18", AArch64::Q18)
1858 .Case("v19", AArch64::Q19)
1859 .Case("v20", AArch64::Q20)
1860 .Case("v21", AArch64::Q21)
1861 .Case("v22", AArch64::Q22)
1862 .Case("v23", AArch64::Q23)
1863 .Case("v24", AArch64::Q24)
1864 .Case("v25", AArch64::Q25)
1865 .Case("v26", AArch64::Q26)
1866 .Case("v27", AArch64::Q27)
1867 .Case("v28", AArch64::Q28)
1868 .Case("v29", AArch64::Q29)
1869 .Case("v30", AArch64::Q30)
1870 .Case("v31", AArch64::Q31)
1871 .Default(0);
1872}
1873
1874static bool isValidVectorKind(StringRef Name) {
1875 return StringSwitch<bool>(Name.lower())
1876 .Case(".8b", true)
1877 .Case(".16b", true)
1878 .Case(".4h", true)
1879 .Case(".8h", true)
1880 .Case(".2s", true)
1881 .Case(".4s", true)
1882 .Case(".1d", true)
1883 .Case(".2d", true)
1884 .Case(".1q", true)
1885 // Accept the width neutral ones, too, for verbose syntax. If those
1886 // aren't used in the right places, the token operand won't match so
1887 // all will work out.
1888 .Case(".b", true)
1889 .Case(".h", true)
1890 .Case(".s", true)
1891 .Case(".d", true)
Oliver Stannarde4c3d212015-12-08 12:16:10 +00001892 // Needed for fp16 scalar pairwise reductions
1893 .Case(".2h", true)
Sjoerd Meijer79876332017-08-09 14:59:54 +00001894 // another special case for the ARMv8.2a dot product operand
1895 .Case(".4b", true)
Tim Northover3b0846e2014-05-24 12:50:23 +00001896 .Default(false);
1897}
1898
Florian Hahn91f11e52017-11-07 16:45:48 +00001899static unsigned matchSVEDataVectorRegName(StringRef Name) {
1900 return StringSwitch<unsigned>(Name.lower())
1901 .Case("z0", AArch64::Z0)
1902 .Case("z1", AArch64::Z1)
1903 .Case("z2", AArch64::Z2)
1904 .Case("z3", AArch64::Z3)
1905 .Case("z4", AArch64::Z4)
1906 .Case("z5", AArch64::Z5)
1907 .Case("z6", AArch64::Z6)
1908 .Case("z7", AArch64::Z7)
1909 .Case("z8", AArch64::Z8)
1910 .Case("z9", AArch64::Z9)
1911 .Case("z10", AArch64::Z10)
1912 .Case("z11", AArch64::Z11)
1913 .Case("z12", AArch64::Z12)
1914 .Case("z13", AArch64::Z13)
1915 .Case("z14", AArch64::Z14)
1916 .Case("z15", AArch64::Z15)
1917 .Case("z16", AArch64::Z16)
1918 .Case("z17", AArch64::Z17)
1919 .Case("z18", AArch64::Z18)
1920 .Case("z19", AArch64::Z19)
1921 .Case("z20", AArch64::Z20)
1922 .Case("z21", AArch64::Z21)
1923 .Case("z22", AArch64::Z22)
1924 .Case("z23", AArch64::Z23)
1925 .Case("z24", AArch64::Z24)
1926 .Case("z25", AArch64::Z25)
1927 .Case("z26", AArch64::Z26)
1928 .Case("z27", AArch64::Z27)
1929 .Case("z28", AArch64::Z28)
1930 .Case("z29", AArch64::Z29)
1931 .Case("z30", AArch64::Z30)
1932 .Case("z31", AArch64::Z31)
1933 .Default(0);
1934}
1935
Sander de Smalencd6be962017-12-20 11:02:42 +00001936static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1937 return StringSwitch<unsigned>(Name.lower())
1938 .Case("p0", AArch64::P0)
1939 .Case("p1", AArch64::P1)
1940 .Case("p2", AArch64::P2)
1941 .Case("p3", AArch64::P3)
1942 .Case("p4", AArch64::P4)
1943 .Case("p5", AArch64::P5)
1944 .Case("p6", AArch64::P6)
1945 .Case("p7", AArch64::P7)
1946 .Case("p8", AArch64::P8)
1947 .Case("p9", AArch64::P9)
1948 .Case("p10", AArch64::P10)
1949 .Case("p11", AArch64::P11)
1950 .Case("p12", AArch64::P12)
1951 .Case("p13", AArch64::P13)
1952 .Case("p14", AArch64::P14)
1953 .Case("p15", AArch64::P15)
1954 .Default(0);
1955}
1956
Florian Hahn91f11e52017-11-07 16:45:48 +00001957static bool isValidSVEKind(StringRef Name) {
1958 return StringSwitch<bool>(Name.lower())
1959 .Case(".b", true)
1960 .Case(".h", true)
1961 .Case(".s", true)
1962 .Case(".d", true)
1963 .Case(".q", true)
1964 .Default(false);
1965}
1966
Tim Northover3b0846e2014-05-24 12:50:23 +00001967static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1968 char &ElementKind) {
1969 assert(isValidVectorKind(Name));
1970
1971 ElementKind = Name.lower()[Name.size() - 1];
1972 NumElements = 0;
1973
1974 if (Name.size() == 2)
1975 return;
1976
1977 // Parse the lane count
1978 Name = Name.drop_front();
1979 while (isdigit(Name.front())) {
1980 NumElements = 10 * NumElements + (Name.front() - '0');
1981 Name = Name.drop_front();
1982 }
1983}
1984
1985bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1986 SMLoc &EndLoc) {
1987 StartLoc = getLoc();
1988 RegNo = tryParseRegister();
1989 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1990 return (RegNo == (unsigned)-1);
1991}
1992
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001993// Matches a register name or register alias previously defined by '.req'
1994unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001995 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001996 unsigned RegNum = 0;
1997 if ((RegNum = matchSVEDataVectorRegName(Name)))
1998 return Kind == RegKind::SVEDataVector ? RegNum : 0;
1999
Sander de Smalencd6be962017-12-20 11:02:42 +00002000 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2001 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2002
Sander de Smalenc067c302017-12-20 09:45:45 +00002003 if ((RegNum = MatchNeonVectorRegName(Name)))
2004 return Kind == RegKind::NeonVector ? RegNum : 0;
2005
2006 // The parsed register must be of RegKind Scalar
2007 if ((RegNum = MatchRegisterName(Name)))
2008 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002009
Florian Hahnc4422242017-11-07 13:07:50 +00002010 if (!RegNum) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002011 // Check for aliases registered via .req. Canonicalize to lower case.
2012 // That's more consistent since register names are case insensitive, and
2013 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2014 auto Entry = RegisterReqs.find(Name.lower());
2015 if (Entry == RegisterReqs.end())
2016 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002017
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002018 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002019 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002020 RegNum = Entry->getValue().second;
2021 }
2022 return RegNum;
2023}
2024
Tim Northover3b0846e2014-05-24 12:50:23 +00002025/// tryParseRegister - Try to parse a register name. The token must be an
2026/// Identifier when called, and if it is a register name the token is eaten and
2027/// the register is added to the operand list.
2028int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002029 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002030 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002031 if (Tok.isNot(AsmToken::Identifier))
2032 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00002033
2034 std::string lowerCase = Tok.getString().lower();
Florian Hahnc4422242017-11-07 13:07:50 +00002035 unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
Sander de Smalenc067c302017-12-20 09:45:45 +00002036
Tim Northover3b0846e2014-05-24 12:50:23 +00002037 // Also handle a few aliases of registers.
2038 if (RegNum == 0)
2039 RegNum = StringSwitch<unsigned>(lowerCase)
2040 .Case("fp", AArch64::FP)
2041 .Case("lr", AArch64::LR)
2042 .Case("x31", AArch64::XZR)
2043 .Case("w31", AArch64::WZR)
2044 .Default(0);
2045
2046 if (RegNum == 0)
2047 return -1;
2048
2049 Parser.Lex(); // Eat identifier token.
2050 return RegNum;
2051}
2052
2053/// tryMatchVectorRegister - Try to parse a vector register name with optional
2054/// kind specifier. If it is a register specifier, eat the token and return it.
2055int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002056 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002057 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2058 TokError("vector register expected");
2059 return -1;
2060 }
2061
2062 StringRef Name = Parser.getTok().getString();
2063 // If there is a kind specifier, it's separated from the register name by
2064 // a '.'.
2065 size_t Start = 0, Next = Name.find('.');
2066 StringRef Head = Name.slice(Start, Next);
Florian Hahnc4422242017-11-07 13:07:50 +00002067 unsigned RegNum = matchRegisterNameAlias(Head, RegKind::NeonVector);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002068
Tim Northover3b0846e2014-05-24 12:50:23 +00002069 if (RegNum) {
2070 if (Next != StringRef::npos) {
2071 Kind = Name.slice(Next, StringRef::npos);
2072 if (!isValidVectorKind(Kind)) {
2073 TokError("invalid vector kind qualifier");
2074 return -1;
2075 }
2076 }
2077 Parser.Lex(); // Eat the register token.
2078 return RegNum;
2079 }
2080
2081 if (expected)
2082 TokError("vector register expected");
2083 return -1;
2084}
2085
2086/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002087OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002088AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002089 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002090 SMLoc S = getLoc();
2091
2092 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2093 Error(S, "Expected cN operand where 0 <= N <= 15");
2094 return MatchOperand_ParseFail;
2095 }
2096
2097 StringRef Tok = Parser.getTok().getIdentifier();
2098 if (Tok[0] != 'c' && Tok[0] != 'C') {
2099 Error(S, "Expected cN operand where 0 <= N <= 15");
2100 return MatchOperand_ParseFail;
2101 }
2102
2103 uint32_t CRNum;
2104 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2105 if (BadNum || CRNum > 15) {
2106 Error(S, "Expected cN operand where 0 <= N <= 15");
2107 return MatchOperand_ParseFail;
2108 }
2109
2110 Parser.Lex(); // Eat identifier token.
2111 Operands.push_back(
2112 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2113 return MatchOperand_Success;
2114}
2115
2116/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002117OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002118AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002119 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002120 SMLoc S = getLoc();
2121 const AsmToken &Tok = Parser.getTok();
2122 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002123 // Eat optional hash.
2124 if (parseOptionalToken(AsmToken::Hash) ||
2125 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002126 const MCExpr *ImmVal;
2127 if (getParser().parseExpression(ImmVal))
2128 return MatchOperand_ParseFail;
2129
2130 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2131 if (!MCE) {
2132 TokError("immediate value expected for prefetch operand");
2133 return MatchOperand_ParseFail;
2134 }
2135 unsigned prfop = MCE->getValue();
2136 if (prfop > 31) {
2137 TokError("prefetch operand out of range, [0,31] expected");
2138 return MatchOperand_ParseFail;
2139 }
2140
Tim Northovere6ae6762016-07-05 21:23:04 +00002141 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2142 Operands.push_back(AArch64Operand::CreatePrefetch(
2143 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002144 return MatchOperand_Success;
2145 }
2146
2147 if (Tok.isNot(AsmToken::Identifier)) {
2148 TokError("pre-fetch hint expected");
2149 return MatchOperand_ParseFail;
2150 }
2151
Tim Northovere6ae6762016-07-05 21:23:04 +00002152 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2153 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002154 TokError("pre-fetch hint expected");
2155 return MatchOperand_ParseFail;
2156 }
2157
2158 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002159 Operands.push_back(AArch64Operand::CreatePrefetch(
2160 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002161 return MatchOperand_Success;
2162}
2163
Oliver Stannarda34e4702015-12-01 10:48:51 +00002164/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002165OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002166AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2167 MCAsmParser &Parser = getParser();
2168 SMLoc S = getLoc();
2169 const AsmToken &Tok = Parser.getTok();
2170 if (Tok.isNot(AsmToken::Identifier)) {
2171 TokError("invalid operand for instruction");
2172 return MatchOperand_ParseFail;
2173 }
2174
Tim Northovere6ae6762016-07-05 21:23:04 +00002175 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2176 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002177 TokError("invalid operand for instruction");
2178 return MatchOperand_ParseFail;
2179 }
2180
2181 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002182 Operands.push_back(AArch64Operand::CreatePSBHint(
2183 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002184 return MatchOperand_Success;
2185}
2186
Tim Northover3b0846e2014-05-24 12:50:23 +00002187/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2188/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002189OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002190AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002191 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002192 SMLoc S = getLoc();
2193 const MCExpr *Expr;
2194
2195 if (Parser.getTok().is(AsmToken::Hash)) {
2196 Parser.Lex(); // Eat hash token.
2197 }
2198
2199 if (parseSymbolicImmVal(Expr))
2200 return MatchOperand_ParseFail;
2201
2202 AArch64MCExpr::VariantKind ELFRefKind;
2203 MCSymbolRefExpr::VariantKind DarwinRefKind;
2204 int64_t Addend;
2205 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2206 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2207 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2208 // No modifier was specified at all; this is the syntax for an ELF basic
2209 // ADRP relocation (unfortunately).
2210 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002211 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002212 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2213 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2214 Addend != 0) {
2215 Error(S, "gotpage label reference not allowed an addend");
2216 return MatchOperand_ParseFail;
2217 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2218 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2219 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2220 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2221 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2222 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2223 // The operand must be an @page or @gotpage qualified symbolref.
2224 Error(S, "page or gotpage label reference expected");
2225 return MatchOperand_ParseFail;
2226 }
2227 }
2228
2229 // We have either a label reference possibly with addend or an immediate. The
2230 // addend is a raw value here. The linker will adjust it to only reference the
2231 // page.
2232 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2233 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2234
2235 return MatchOperand_Success;
2236}
2237
2238/// tryParseAdrLabel - Parse and validate a source label for the ADR
2239/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002240OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002241AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2242 SMLoc S = getLoc();
2243 const MCExpr *Expr;
2244
Nirav Davee833c6c2016-11-08 18:31:04 +00002245 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002246 if (getParser().parseExpression(Expr))
2247 return MatchOperand_ParseFail;
2248
2249 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2250 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2251
2252 return MatchOperand_Success;
2253}
2254
2255/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002256OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002257AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002258 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002259 SMLoc S = getLoc();
2260
Nirav Davee833c6c2016-11-08 18:31:04 +00002261 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002262
2263 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002264 bool isNegative = parseOptionalToken(AsmToken::Minus);
2265
Tim Northover3b0846e2014-05-24 12:50:23 +00002266 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002267 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002268 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002269 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002270 Val = Tok.getIntVal();
2271 if (Val > 255 || Val < 0) {
2272 TokError("encoded floating point value out of range");
2273 return MatchOperand_ParseFail;
2274 }
2275 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002276 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002277 if (isNegative)
2278 RealVal.changeSign();
2279
Tim Northover3b0846e2014-05-24 12:50:23 +00002280 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002281 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002282
John Brawn5ca5daa2017-04-20 10:13:54 +00002283 // Check for out of range values. As an exception we let Zero through,
2284 // but as tokens instead of an FPImm so that it can be matched by the
2285 // appropriate alias if one exists.
2286 if (RealVal.isPosZero()) {
2287 Parser.Lex(); // Eat the token.
2288 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2289 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2290 return MatchOperand_Success;
2291 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002292 TokError("expected compatible register or floating-point constant");
2293 return MatchOperand_ParseFail;
2294 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002295 }
2296 Parser.Lex(); // Eat the token.
2297 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2298 return MatchOperand_Success;
2299 }
2300
2301 if (!Hash)
2302 return MatchOperand_NoMatch;
2303
2304 TokError("invalid floating point immediate");
2305 return MatchOperand_ParseFail;
2306}
2307
2308/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002309OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002310AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002311 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002312 SMLoc S = getLoc();
2313
2314 if (Parser.getTok().is(AsmToken::Hash))
2315 Parser.Lex(); // Eat '#'
2316 else if (Parser.getTok().isNot(AsmToken::Integer))
2317 // Operand should start from # or should be integer, emit error otherwise.
2318 return MatchOperand_NoMatch;
2319
2320 const MCExpr *Imm;
2321 if (parseSymbolicImmVal(Imm))
2322 return MatchOperand_ParseFail;
2323 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2324 uint64_t ShiftAmount = 0;
2325 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2326 if (MCE) {
2327 int64_t Val = MCE->getValue();
2328 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002329 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002330 ShiftAmount = 12;
2331 }
2332 }
2333 SMLoc E = Parser.getTok().getLoc();
2334 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2335 getContext()));
2336 return MatchOperand_Success;
2337 }
2338
2339 // Eat ','
2340 Parser.Lex();
2341
2342 // The optional operand must be "lsl #N" where N is non-negative.
2343 if (!Parser.getTok().is(AsmToken::Identifier) ||
2344 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2345 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2346 return MatchOperand_ParseFail;
2347 }
2348
2349 // Eat 'lsl'
2350 Parser.Lex();
2351
Nirav Davee833c6c2016-11-08 18:31:04 +00002352 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002353
2354 if (Parser.getTok().isNot(AsmToken::Integer)) {
2355 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2356 return MatchOperand_ParseFail;
2357 }
2358
2359 int64_t ShiftAmount = Parser.getTok().getIntVal();
2360
2361 if (ShiftAmount < 0) {
2362 Error(Parser.getTok().getLoc(), "positive shift amount required");
2363 return MatchOperand_ParseFail;
2364 }
2365 Parser.Lex(); // Eat the number
2366
2367 SMLoc E = Parser.getTok().getLoc();
2368 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2369 S, E, getContext()));
2370 return MatchOperand_Success;
2371}
2372
2373/// parseCondCodeString - Parse a Condition Code string.
2374AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2375 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2376 .Case("eq", AArch64CC::EQ)
2377 .Case("ne", AArch64CC::NE)
2378 .Case("cs", AArch64CC::HS)
2379 .Case("hs", AArch64CC::HS)
2380 .Case("cc", AArch64CC::LO)
2381 .Case("lo", AArch64CC::LO)
2382 .Case("mi", AArch64CC::MI)
2383 .Case("pl", AArch64CC::PL)
2384 .Case("vs", AArch64CC::VS)
2385 .Case("vc", AArch64CC::VC)
2386 .Case("hi", AArch64CC::HI)
2387 .Case("ls", AArch64CC::LS)
2388 .Case("ge", AArch64CC::GE)
2389 .Case("lt", AArch64CC::LT)
2390 .Case("gt", AArch64CC::GT)
2391 .Case("le", AArch64CC::LE)
2392 .Case("al", AArch64CC::AL)
2393 .Case("nv", AArch64CC::NV)
2394 .Default(AArch64CC::Invalid);
2395 return CC;
2396}
2397
2398/// parseCondCode - Parse a Condition Code operand.
2399bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2400 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002401 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002402 SMLoc S = getLoc();
2403 const AsmToken &Tok = Parser.getTok();
2404 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2405
2406 StringRef Cond = Tok.getString();
2407 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2408 if (CC == AArch64CC::Invalid)
2409 return TokError("invalid condition code");
2410 Parser.Lex(); // Eat identifier token.
2411
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002412 if (invertCondCode) {
2413 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2414 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002415 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002416 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002417
2418 Operands.push_back(
2419 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2420 return false;
2421}
2422
2423/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2424/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002425OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002426AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002427 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002428 const AsmToken &Tok = Parser.getTok();
2429 std::string LowerID = Tok.getString().lower();
2430 AArch64_AM::ShiftExtendType ShOp =
2431 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2432 .Case("lsl", AArch64_AM::LSL)
2433 .Case("lsr", AArch64_AM::LSR)
2434 .Case("asr", AArch64_AM::ASR)
2435 .Case("ror", AArch64_AM::ROR)
2436 .Case("msl", AArch64_AM::MSL)
2437 .Case("uxtb", AArch64_AM::UXTB)
2438 .Case("uxth", AArch64_AM::UXTH)
2439 .Case("uxtw", AArch64_AM::UXTW)
2440 .Case("uxtx", AArch64_AM::UXTX)
2441 .Case("sxtb", AArch64_AM::SXTB)
2442 .Case("sxth", AArch64_AM::SXTH)
2443 .Case("sxtw", AArch64_AM::SXTW)
2444 .Case("sxtx", AArch64_AM::SXTX)
2445 .Default(AArch64_AM::InvalidShiftExtend);
2446
2447 if (ShOp == AArch64_AM::InvalidShiftExtend)
2448 return MatchOperand_NoMatch;
2449
2450 SMLoc S = Tok.getLoc();
2451 Parser.Lex();
2452
Nirav Davee833c6c2016-11-08 18:31:04 +00002453 bool Hash = parseOptionalToken(AsmToken::Hash);
2454
Tim Northover3b0846e2014-05-24 12:50:23 +00002455 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2456 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2457 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2458 ShOp == AArch64_AM::MSL) {
2459 // We expect a number here.
2460 TokError("expected #imm after shift specifier");
2461 return MatchOperand_ParseFail;
2462 }
2463
Chad Rosier2ff37b82016-12-27 16:58:09 +00002464 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002465 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2466 Operands.push_back(
2467 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2468 return MatchOperand_Success;
2469 }
2470
Chad Rosier2ff37b82016-12-27 16:58:09 +00002471 // Make sure we do actually have a number, identifier or a parenthesized
2472 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002473 SMLoc E = Parser.getTok().getLoc();
2474 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002475 !Parser.getTok().is(AsmToken::LParen) &&
2476 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002477 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002478 return MatchOperand_ParseFail;
2479 }
2480
2481 const MCExpr *ImmVal;
2482 if (getParser().parseExpression(ImmVal))
2483 return MatchOperand_ParseFail;
2484
2485 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2486 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002487 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002488 return MatchOperand_ParseFail;
2489 }
2490
Jim Grosbach57fd2622014-09-23 22:16:02 +00002491 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002492 Operands.push_back(AArch64Operand::CreateShiftExtend(
2493 ShOp, MCE->getValue(), true, S, E, getContext()));
2494 return MatchOperand_Success;
2495}
2496
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002497static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2498 if (FBS[AArch64::HasV8_1aOps])
2499 Str += "ARMv8.1a";
2500 else if (FBS[AArch64::HasV8_2aOps])
2501 Str += "ARMv8.2a";
2502 else
2503 Str += "(unknown)";
2504}
2505
2506void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2507 SMLoc S) {
2508 const uint16_t Op2 = Encoding & 7;
2509 const uint16_t Cm = (Encoding & 0x78) >> 3;
2510 const uint16_t Cn = (Encoding & 0x780) >> 7;
2511 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2512
2513 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2514
2515 Operands.push_back(
2516 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2517 Operands.push_back(
2518 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2519 Operands.push_back(
2520 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2521 Expr = MCConstantExpr::create(Op2, getContext());
2522 Operands.push_back(
2523 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2524}
2525
Tim Northover3b0846e2014-05-24 12:50:23 +00002526/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2527/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2528bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2529 OperandVector &Operands) {
2530 if (Name.find('.') != StringRef::npos)
2531 return TokError("invalid operand");
2532
2533 Mnemonic = Name;
2534 Operands.push_back(
2535 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2536
Rafael Espindola961d4692014-11-11 05:18:41 +00002537 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002538 const AsmToken &Tok = Parser.getTok();
2539 StringRef Op = Tok.getString();
2540 SMLoc S = Tok.getLoc();
2541
Tim Northover3b0846e2014-05-24 12:50:23 +00002542 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002543 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2544 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002545 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002546 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2547 std::string Str("IC " + std::string(IC->Name) + " requires ");
2548 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2549 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002550 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002551 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002552 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002553 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2554 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002555 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002556 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2557 std::string Str("DC " + std::string(DC->Name) + " requires ");
2558 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2559 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002560 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002561 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002562 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002563 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2564 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002565 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002566 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2567 std::string Str("AT " + std::string(AT->Name) + " requires ");
2568 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2569 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002570 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002571 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002572 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002573 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2574 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002575 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002576 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2577 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2578 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2579 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002580 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002581 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002582 }
2583
Tim Northover3b0846e2014-05-24 12:50:23 +00002584 Parser.Lex(); // Eat operand.
2585
2586 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2587 bool HasRegister = false;
2588
2589 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002590 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002591 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2592 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002593 HasRegister = true;
2594 }
2595
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002596 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002597 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002598 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002599 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002600
Nirav Davee833c6c2016-11-08 18:31:04 +00002601 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2602 return true;
2603
Tim Northover3b0846e2014-05-24 12:50:23 +00002604 return false;
2605}
2606
Alex Bradbury58eba092016-11-01 16:32:05 +00002607OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002608AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002609 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002610 const AsmToken &Tok = Parser.getTok();
2611
2612 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002613 if (parseOptionalToken(AsmToken::Hash) ||
2614 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002615 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002616 const MCExpr *ImmVal;
2617 SMLoc ExprLoc = getLoc();
2618 if (getParser().parseExpression(ImmVal))
2619 return MatchOperand_ParseFail;
2620 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2621 if (!MCE) {
2622 Error(ExprLoc, "immediate value expected for barrier operand");
2623 return MatchOperand_ParseFail;
2624 }
2625 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2626 Error(ExprLoc, "barrier operand out of range");
2627 return MatchOperand_ParseFail;
2628 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002629 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2630 Operands.push_back(AArch64Operand::CreateBarrier(
2631 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002632 return MatchOperand_Success;
2633 }
2634
2635 if (Tok.isNot(AsmToken::Identifier)) {
2636 TokError("invalid operand for instruction");
2637 return MatchOperand_ParseFail;
2638 }
2639
Tim Northover3b0846e2014-05-24 12:50:23 +00002640 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002641 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2642 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002643 TokError("'sy' or #imm operand expected");
2644 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002645 } else if (!DB) {
2646 TokError("invalid barrier option name");
2647 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002648 }
2649
Tim Northovere6ae6762016-07-05 21:23:04 +00002650 Operands.push_back(AArch64Operand::CreateBarrier(
2651 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002652 Parser.Lex(); // Consume the option
2653
2654 return MatchOperand_Success;
2655}
2656
Alex Bradbury58eba092016-11-01 16:32:05 +00002657OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002658AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002659 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002660 const AsmToken &Tok = Parser.getTok();
2661
2662 if (Tok.isNot(AsmToken::Identifier))
2663 return MatchOperand_NoMatch;
2664
Tim Northovere6ae6762016-07-05 21:23:04 +00002665 int MRSReg, MSRReg;
2666 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2667 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2668 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2669 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2670 } else
2671 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002672
Tim Northovere6ae6762016-07-05 21:23:04 +00002673 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2674 unsigned PStateImm = -1;
2675 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2676 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002677
Tim Northovere6ae6762016-07-05 21:23:04 +00002678 Operands.push_back(
2679 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2680 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002681 Parser.Lex(); // Eat identifier
2682
2683 return MatchOperand_Success;
2684}
2685
Florian Hahnc4422242017-11-07 13:07:50 +00002686/// tryParseNeonVectorRegister - Parse a vector register operand.
2687bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002688 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002689 if (Parser.getTok().isNot(AsmToken::Identifier))
2690 return true;
2691
2692 SMLoc S = getLoc();
2693 // Check for a vector register specifier first.
2694 StringRef Kind;
2695 int64_t Reg = tryMatchVectorRegister(Kind, false);
2696 if (Reg == -1)
2697 return true;
2698 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00002699 AArch64Operand::CreateReg(Reg, RegKind::NeonVector, S, getLoc(),
2700 getContext()));
2701
Tim Northover3b0846e2014-05-24 12:50:23 +00002702 // If there was an explicit qualifier, that goes on as a literal text
2703 // operand.
2704 if (!Kind.empty())
2705 Operands.push_back(
2706 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2707
2708 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002709 SMLoc SIdx = getLoc();
2710 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002711 const MCExpr *ImmVal;
2712 if (getParser().parseExpression(ImmVal))
2713 return false;
2714 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2715 if (!MCE) {
2716 TokError("immediate value expected for vector index");
2717 return false;
2718 }
2719
2720 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002721
Nirav Davee833c6c2016-11-08 18:31:04 +00002722 if (parseToken(AsmToken::RBrac, "']' expected"))
2723 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002724
2725 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2726 E, getContext()));
2727 }
2728
2729 return false;
2730}
2731
Florian Hahn91f11e52017-11-07 16:45:48 +00002732// tryParseSVEDataVectorRegister - Try to parse a SVE vector register name with
2733// optional kind specifier. If it is a register specifier, eat the token
2734// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002735OperandMatchResultTy
2736AArch64AsmParser::tryParseSVERegister(int &Reg, StringRef &Kind,
2737 RegKind MatchKind) {
2738 MCAsmParser &Parser = getParser();
2739 const AsmToken &Tok = Parser.getTok();
2740
Florian Hahn91f11e52017-11-07 16:45:48 +00002741 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002742 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002743
2744 StringRef Name = Tok.getString();
2745 // If there is a kind specifier, it's separated from the register name by
2746 // a '.'.
2747 size_t Start = 0, Next = Name.find('.');
2748 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002749 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002750
2751 if (RegNum) {
2752 if (Next != StringRef::npos) {
2753 Kind = Name.slice(Next, StringRef::npos);
2754 if (!isValidSVEKind(Kind)) {
2755 TokError("invalid sve vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002756 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002757 }
2758 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002759 Parser.Lex(); // Eat the register token.
2760
2761 Reg = RegNum;
2762 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002763 }
2764
Sander de Smalen8e607342017-11-15 15:44:43 +00002765 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002766}
2767
Sander de Smalencd6be962017-12-20 11:02:42 +00002768/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2769OperandMatchResultTy
2770AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2771 // Check for a SVE predicate register specifier first.
2772 const SMLoc S = getLoc();
2773 StringRef Kind;
2774 int RegNum = -1;
2775 auto Res = tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
2776 if (Res != MatchOperand_Success)
2777 return Res;
2778
2779 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
2780 .Case("", -1)
2781 .Case(".b", 8)
2782 .Case(".h", 16)
2783 .Case(".s", 32)
2784 .Case(".d", 64)
2785 .Case(".q", 128)
2786 .Default(0);
2787
2788 if (!ElementWidth)
2789 return MatchOperand_NoMatch;
2790
2791 Operands.push_back(
2792 AArch64Operand::CreateReg(RegNum, RegKind::SVEPredicateVector,
2793 ElementWidth, S, getLoc(), getContext()));
2794
Sander de Smalen7868e742018-01-09 11:17:06 +00002795 // Not all predicates are followed by a '/m' or '/z'.
2796 MCAsmParser &Parser = getParser();
2797 if (Parser.getTok().isNot(AsmToken::Slash))
2798 return MatchOperand_Success;
2799
2800 // But when they do they shouldn't have an element type suffix.
2801 if (!Kind.empty()) {
2802 Error(S, "not expecting size suffix");
2803 return MatchOperand_ParseFail;
2804 }
2805
2806 // Add a literal slash as operand
2807 Operands.push_back(
2808 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2809
2810 Parser.Lex(); // Eat the slash.
2811
2812 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002813 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002814 if (Pred != "z" && Pred != "m") {
2815 Error(getLoc(), "expecting 'm' or 'z' predication");
2816 return MatchOperand_ParseFail;
2817 }
2818
2819 // Add zero/merge token.
2820 const char *ZM = Pred == "z" ? "z" : "m";
2821 Operands.push_back(
2822 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2823
2824 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002825 return MatchOperand_Success;
2826}
2827
Tim Northover3b0846e2014-05-24 12:50:23 +00002828/// parseRegister - Parse a non-vector register operand.
2829bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2830 SMLoc S = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00002831 // Try for a vector (neon) register.
2832 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002833 return false;
2834
2835 // Try for a scalar register.
2836 int64_t Reg = tryParseRegister();
2837 if (Reg == -1)
2838 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002839 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2840 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002841
Tim Northover3b0846e2014-05-24 12:50:23 +00002842 return false;
2843}
2844
2845bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002846 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002847 bool HasELFModifier = false;
2848 AArch64MCExpr::VariantKind RefKind;
2849
Nirav Davee833c6c2016-11-08 18:31:04 +00002850 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002851 HasELFModifier = true;
2852
Nirav Davee833c6c2016-11-08 18:31:04 +00002853 if (Parser.getTok().isNot(AsmToken::Identifier))
2854 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002855
2856 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2857 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2858 .Case("lo12", AArch64MCExpr::VK_LO12)
2859 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2860 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2861 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2862 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2863 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2864 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2865 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2866 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2867 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2868 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2869 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2870 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2871 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2872 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2873 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2874 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2875 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2876 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2877 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2878 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2879 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2880 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2881 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2882 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2883 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2884 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2885 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2886 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2887 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2888 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2889 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2890 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2891 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2892 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2893 .Default(AArch64MCExpr::VK_INVALID);
2894
Nirav Davee833c6c2016-11-08 18:31:04 +00002895 if (RefKind == AArch64MCExpr::VK_INVALID)
2896 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002897
2898 Parser.Lex(); // Eat identifier
2899
Nirav Davee833c6c2016-11-08 18:31:04 +00002900 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002901 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002902 }
2903
2904 if (getParser().parseExpression(ImmVal))
2905 return true;
2906
2907 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002908 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002909
2910 return false;
2911}
2912
2913/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2914bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002915 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002916 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2917 SMLoc S = getLoc();
2918 Parser.Lex(); // Eat left bracket token.
2919 StringRef Kind;
2920 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2921 if (FirstReg == -1)
2922 return true;
2923 int64_t PrevReg = FirstReg;
2924 unsigned Count = 1;
2925
Nirav Davee833c6c2016-11-08 18:31:04 +00002926 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002927 SMLoc Loc = getLoc();
2928 StringRef NextKind;
2929 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2930 if (Reg == -1)
2931 return true;
2932 // Any Kind suffices must match on all regs in the list.
2933 if (Kind != NextKind)
2934 return Error(Loc, "mismatched register size suffix");
2935
2936 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2937
2938 if (Space == 0 || Space > 3) {
2939 return Error(Loc, "invalid number of vectors");
2940 }
2941
2942 Count += Space;
2943 }
2944 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002945 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002946 SMLoc Loc = getLoc();
2947 StringRef NextKind;
2948 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2949 if (Reg == -1)
2950 return true;
2951 // Any Kind suffices must match on all regs in the list.
2952 if (Kind != NextKind)
2953 return Error(Loc, "mismatched register size suffix");
2954
2955 // Registers must be incremental (with wraparound at 31)
2956 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2957 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2958 return Error(Loc, "registers must be sequential");
2959
2960 PrevReg = Reg;
2961 ++Count;
2962 }
2963 }
2964
Nirav Davee833c6c2016-11-08 18:31:04 +00002965 if (parseToken(AsmToken::RCurly, "'}' expected"))
2966 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002967
2968 if (Count > 4)
2969 return Error(S, "invalid number of vectors");
2970
2971 unsigned NumElements = 0;
2972 char ElementKind = 0;
2973 if (!Kind.empty())
2974 parseValidVectorKind(Kind, NumElements, ElementKind);
2975
2976 Operands.push_back(AArch64Operand::CreateVectorList(
2977 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
2978
2979 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002980 SMLoc SIdx = getLoc();
2981 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002982 const MCExpr *ImmVal;
2983 if (getParser().parseExpression(ImmVal))
2984 return false;
2985 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2986 if (!MCE) {
2987 TokError("immediate value expected for vector index");
2988 return false;
2989 }
2990
2991 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002992 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002993 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002994
2995 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2996 E, getContext()));
2997 }
2998 return false;
2999}
3000
Alex Bradbury58eba092016-11-01 16:32:05 +00003001OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003002AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003003 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003004 const AsmToken &Tok = Parser.getTok();
3005 if (!Tok.is(AsmToken::Identifier))
3006 return MatchOperand_NoMatch;
3007
Florian Hahnc4422242017-11-07 13:07:50 +00003008 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00003009
3010 MCContext &Ctx = getContext();
3011 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
3012 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
3013 return MatchOperand_NoMatch;
3014
3015 SMLoc S = getLoc();
3016 Parser.Lex(); // Eat register
3017
Nirav Davee833c6c2016-11-08 18:31:04 +00003018 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003019 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 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003023
Nirav Davee833c6c2016-11-08 18:31:04 +00003024 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003025
3026 if (Parser.getTok().isNot(AsmToken::Integer)) {
3027 Error(getLoc(), "index must be absent or #0");
3028 return MatchOperand_ParseFail;
3029 }
3030
3031 const MCExpr *ImmVal;
3032 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3033 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3034 Error(getLoc(), "index must be absent or #0");
3035 return MatchOperand_ParseFail;
3036 }
3037
3038 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003039 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003040 return MatchOperand_Success;
3041}
3042
3043/// parseOperand - Parse a arm instruction operand. For now this parses the
3044/// operand regardless of the mnemonic.
3045bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3046 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003047 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003048
3049 OperandMatchResultTy ResTy =
3050 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3051
Tim Northover3b0846e2014-05-24 12:50:23 +00003052 // Check if the current operand has a custom associated parser, if so, try to
3053 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003054 if (ResTy == MatchOperand_Success)
3055 return false;
3056 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3057 // there was a match, but an error occurred, in which case, just return that
3058 // the operand parsing failed.
3059 if (ResTy == MatchOperand_ParseFail)
3060 return true;
3061
3062 // Nothing custom, so do general case parsing.
3063 SMLoc S, E;
3064 switch (getLexer().getKind()) {
3065 default: {
3066 SMLoc S = getLoc();
3067 const MCExpr *Expr;
3068 if (parseSymbolicImmVal(Expr))
3069 return Error(S, "invalid operand");
3070
3071 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3072 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3073 return false;
3074 }
3075 case AsmToken::LBrac: {
3076 SMLoc Loc = Parser.getTok().getLoc();
3077 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3078 getContext()));
3079 Parser.Lex(); // Eat '['
3080
3081 // There's no comma after a '[', so we can parse the next operand
3082 // immediately.
3083 return parseOperand(Operands, false, false);
3084 }
3085 case AsmToken::LCurly:
3086 return parseVectorList(Operands);
3087 case AsmToken::Identifier: {
3088 // If we're expecting a Condition Code operand, then just parse that.
3089 if (isCondCode)
3090 return parseCondCode(Operands, invertCondCode);
3091
3092 // If it's a register name, parse it.
3093 if (!parseRegister(Operands))
3094 return false;
3095
3096 // This could be an optional "shift" or "extend" operand.
3097 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3098 // We can only continue if no tokens were eaten.
3099 if (GotShift != MatchOperand_NoMatch)
3100 return GotShift;
3101
3102 // This was not a register so parse other operands that start with an
3103 // identifier (like labels) as expressions and create them as immediates.
3104 const MCExpr *IdVal;
3105 S = getLoc();
3106 if (getParser().parseExpression(IdVal))
3107 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003108 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3109 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3110 return false;
3111 }
3112 case AsmToken::Integer:
3113 case AsmToken::Real:
3114 case AsmToken::Hash: {
3115 // #42 -> immediate.
3116 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003117
3118 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003119
3120 // Parse a negative sign
3121 bool isNegative = false;
3122 if (Parser.getTok().is(AsmToken::Minus)) {
3123 isNegative = true;
3124 // We need to consume this token only when we have a Real, otherwise
3125 // we let parseSymbolicImmVal take care of it
3126 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3127 Parser.Lex();
3128 }
3129
3130 // The only Real that should come through here is a literal #0.0 for
3131 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3132 // so convert the value.
3133 const AsmToken &Tok = Parser.getTok();
3134 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003135 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003136 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3137 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3138 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3139 Mnemonic != "fcmlt")
3140 return TokError("unexpected floating point literal");
3141 else if (IntVal != 0 || isNegative)
3142 return TokError("expected floating-point constant #0.0");
3143 Parser.Lex(); // Eat the token.
3144
3145 Operands.push_back(
3146 AArch64Operand::CreateToken("#0", false, S, getContext()));
3147 Operands.push_back(
3148 AArch64Operand::CreateToken(".0", false, S, getContext()));
3149 return false;
3150 }
3151
3152 const MCExpr *ImmVal;
3153 if (parseSymbolicImmVal(ImmVal))
3154 return true;
3155
3156 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3157 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3158 return false;
3159 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003160 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003161 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003162 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003163 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003164 Parser.Lex(); // Eat '='
3165 const MCExpr *SubExprVal;
3166 if (getParser().parseExpression(SubExprVal))
3167 return true;
3168
David Peixottoae5ba762014-07-18 16:05:14 +00003169 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003170 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003171 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003172
3173 bool IsXReg =
3174 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3175 Operands[1]->getReg());
3176
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003177 MCContext& Ctx = getContext();
3178 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3179 // 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 +00003180 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003181 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3182 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3183 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3184 ShiftAmt += 16;
3185 Imm >>= 16;
3186 }
3187 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3188 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3189 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003190 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003191 if (ShiftAmt)
3192 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3193 ShiftAmt, true, S, E, Ctx));
3194 return false;
3195 }
David Peixottoae5ba762014-07-18 16:05:14 +00003196 APInt Simm = APInt(64, Imm << ShiftAmt);
3197 // check if the immediate is an unsigned or signed 32-bit int for W regs
3198 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3199 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003200 }
3201 // 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 +00003202 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003203 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003204 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3205 return false;
3206 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003207 }
3208}
3209
3210/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3211/// operands.
3212bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3213 StringRef Name, SMLoc NameLoc,
3214 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003215 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003216 Name = StringSwitch<StringRef>(Name.lower())
3217 .Case("beq", "b.eq")
3218 .Case("bne", "b.ne")
3219 .Case("bhs", "b.hs")
3220 .Case("bcs", "b.cs")
3221 .Case("blo", "b.lo")
3222 .Case("bcc", "b.cc")
3223 .Case("bmi", "b.mi")
3224 .Case("bpl", "b.pl")
3225 .Case("bvs", "b.vs")
3226 .Case("bvc", "b.vc")
3227 .Case("bhi", "b.hi")
3228 .Case("bls", "b.ls")
3229 .Case("bge", "b.ge")
3230 .Case("blt", "b.lt")
3231 .Case("bgt", "b.gt")
3232 .Case("ble", "b.le")
3233 .Case("bal", "b.al")
3234 .Case("bnv", "b.nv")
3235 .Default(Name);
3236
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003237 // First check for the AArch64-specific .req directive.
3238 if (Parser.getTok().is(AsmToken::Identifier) &&
3239 Parser.getTok().getIdentifier() == ".req") {
3240 parseDirectiveReq(Name, NameLoc);
3241 // We always return 'error' for this, as we're done with this
3242 // statement and don't need to match the 'instruction."
3243 return true;
3244 }
3245
Tim Northover3b0846e2014-05-24 12:50:23 +00003246 // Create the leading tokens for the mnemonic, split by '.' characters.
3247 size_t Start = 0, Next = Name.find('.');
3248 StringRef Head = Name.slice(Start, Next);
3249
3250 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003251 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3252 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003253
3254 Operands.push_back(
3255 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3256 Mnemonic = Head;
3257
3258 // Handle condition codes for a branch mnemonic
3259 if (Head == "b" && Next != StringRef::npos) {
3260 Start = Next;
3261 Next = Name.find('.', Start + 1);
3262 Head = Name.slice(Start + 1, Next);
3263
3264 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3265 (Head.data() - Name.data()));
3266 AArch64CC::CondCode CC = parseCondCodeString(Head);
3267 if (CC == AArch64CC::Invalid)
3268 return Error(SuffixLoc, "invalid condition code");
3269 Operands.push_back(
3270 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3271 Operands.push_back(
3272 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3273 }
3274
3275 // Add the remaining tokens in the mnemonic.
3276 while (Next != StringRef::npos) {
3277 Start = Next;
3278 Next = Name.find('.', Start + 1);
3279 Head = Name.slice(Start, Next);
3280 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3281 (Head.data() - Name.data()) + 1);
3282 Operands.push_back(
3283 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3284 }
3285
3286 // Conditional compare instructions have a Condition Code operand, which needs
3287 // to be parsed and an immediate operand created.
3288 bool condCodeFourthOperand =
3289 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3290 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3291 Head == "csinc" || Head == "csinv" || Head == "csneg");
3292
3293 // These instructions are aliases to some of the conditional select
3294 // instructions. However, the condition code is inverted in the aliased
3295 // instruction.
3296 //
3297 // FIXME: Is this the correct way to handle these? Or should the parser
3298 // generate the aliased instructions directly?
3299 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3300 bool condCodeThirdOperand =
3301 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3302
3303 // Read the remaining operands.
3304 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3305 // Read the first operand.
3306 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003307 return true;
3308 }
3309
3310 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003311 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003312 // Parse and remember the operand.
3313 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3314 (N == 3 && condCodeThirdOperand) ||
3315 (N == 2 && condCodeSecondOperand),
3316 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003317 return true;
3318 }
3319
3320 // After successfully parsing some operands there are two special cases to
3321 // consider (i.e. notional operands not separated by commas). Both are due
3322 // to memory specifiers:
3323 // + An RBrac will end an address for load/store/prefetch
3324 // + An '!' will indicate a pre-indexed operation.
3325 //
3326 // It's someone else's responsibility to make sure these tokens are sane
3327 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003328
Nirav Davee833c6c2016-11-08 18:31:04 +00003329 SMLoc RLoc = Parser.getTok().getLoc();
3330 if (parseOptionalToken(AsmToken::RBrac))
3331 Operands.push_back(
3332 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3333 SMLoc ELoc = Parser.getTok().getLoc();
3334 if (parseOptionalToken(AsmToken::Exclaim))
3335 Operands.push_back(
3336 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003337
3338 ++N;
3339 }
3340 }
3341
Nirav Davee833c6c2016-11-08 18:31:04 +00003342 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3343 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003344
Tim Northover3b0846e2014-05-24 12:50:23 +00003345 return false;
3346}
3347
3348// FIXME: This entire function is a giant hack to provide us with decent
3349// operand range validation/diagnostics until TableGen/MC can be extended
3350// to support autogeneration of this kind of validation.
3351bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3352 SmallVectorImpl<SMLoc> &Loc) {
3353 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3354 // Check for indexed addressing modes w/ the base register being the
3355 // same as a destination/source register or pair load where
3356 // the Rt == Rt2. All of those are undefined behaviour.
3357 switch (Inst.getOpcode()) {
3358 case AArch64::LDPSWpre:
3359 case AArch64::LDPWpost:
3360 case AArch64::LDPWpre:
3361 case AArch64::LDPXpost:
3362 case AArch64::LDPXpre: {
3363 unsigned Rt = Inst.getOperand(1).getReg();
3364 unsigned Rt2 = Inst.getOperand(2).getReg();
3365 unsigned Rn = Inst.getOperand(3).getReg();
3366 if (RI->isSubRegisterEq(Rn, Rt))
3367 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3368 "is also a destination");
3369 if (RI->isSubRegisterEq(Rn, Rt2))
3370 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3371 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003372 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003373 }
3374 case AArch64::LDPDi:
3375 case AArch64::LDPQi:
3376 case AArch64::LDPSi:
3377 case AArch64::LDPSWi:
3378 case AArch64::LDPWi:
3379 case AArch64::LDPXi: {
3380 unsigned Rt = Inst.getOperand(0).getReg();
3381 unsigned Rt2 = Inst.getOperand(1).getReg();
3382 if (Rt == Rt2)
3383 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3384 break;
3385 }
3386 case AArch64::LDPDpost:
3387 case AArch64::LDPDpre:
3388 case AArch64::LDPQpost:
3389 case AArch64::LDPQpre:
3390 case AArch64::LDPSpost:
3391 case AArch64::LDPSpre:
3392 case AArch64::LDPSWpost: {
3393 unsigned Rt = Inst.getOperand(1).getReg();
3394 unsigned Rt2 = Inst.getOperand(2).getReg();
3395 if (Rt == Rt2)
3396 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3397 break;
3398 }
3399 case AArch64::STPDpost:
3400 case AArch64::STPDpre:
3401 case AArch64::STPQpost:
3402 case AArch64::STPQpre:
3403 case AArch64::STPSpost:
3404 case AArch64::STPSpre:
3405 case AArch64::STPWpost:
3406 case AArch64::STPWpre:
3407 case AArch64::STPXpost:
3408 case AArch64::STPXpre: {
3409 unsigned Rt = Inst.getOperand(1).getReg();
3410 unsigned Rt2 = Inst.getOperand(2).getReg();
3411 unsigned Rn = Inst.getOperand(3).getReg();
3412 if (RI->isSubRegisterEq(Rn, Rt))
3413 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3414 "is also a source");
3415 if (RI->isSubRegisterEq(Rn, Rt2))
3416 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3417 "is also a source");
3418 break;
3419 }
3420 case AArch64::LDRBBpre:
3421 case AArch64::LDRBpre:
3422 case AArch64::LDRHHpre:
3423 case AArch64::LDRHpre:
3424 case AArch64::LDRSBWpre:
3425 case AArch64::LDRSBXpre:
3426 case AArch64::LDRSHWpre:
3427 case AArch64::LDRSHXpre:
3428 case AArch64::LDRSWpre:
3429 case AArch64::LDRWpre:
3430 case AArch64::LDRXpre:
3431 case AArch64::LDRBBpost:
3432 case AArch64::LDRBpost:
3433 case AArch64::LDRHHpost:
3434 case AArch64::LDRHpost:
3435 case AArch64::LDRSBWpost:
3436 case AArch64::LDRSBXpost:
3437 case AArch64::LDRSHWpost:
3438 case AArch64::LDRSHXpost:
3439 case AArch64::LDRSWpost:
3440 case AArch64::LDRWpost:
3441 case AArch64::LDRXpost: {
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 LDR instruction, writeback base "
3446 "is also a source");
3447 break;
3448 }
3449 case AArch64::STRBBpost:
3450 case AArch64::STRBpost:
3451 case AArch64::STRHHpost:
3452 case AArch64::STRHpost:
3453 case AArch64::STRWpost:
3454 case AArch64::STRXpost:
3455 case AArch64::STRBBpre:
3456 case AArch64::STRBpre:
3457 case AArch64::STRHHpre:
3458 case AArch64::STRHpre:
3459 case AArch64::STRWpre:
3460 case AArch64::STRXpre: {
3461 unsigned Rt = Inst.getOperand(1).getReg();
3462 unsigned Rn = Inst.getOperand(2).getReg();
3463 if (RI->isSubRegisterEq(Rn, Rt))
3464 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3465 "is also a source");
3466 break;
3467 }
3468 }
3469
3470 // Now check immediate ranges. Separate from the above as there is overlap
3471 // in the instructions being checked and this keeps the nested conditionals
3472 // to a minimum.
3473 switch (Inst.getOpcode()) {
3474 case AArch64::ADDSWri:
3475 case AArch64::ADDSXri:
3476 case AArch64::ADDWri:
3477 case AArch64::ADDXri:
3478 case AArch64::SUBSWri:
3479 case AArch64::SUBSXri:
3480 case AArch64::SUBWri:
3481 case AArch64::SUBXri: {
3482 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3483 // some slight duplication here.
3484 if (Inst.getOperand(2).isExpr()) {
3485 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3486 AArch64MCExpr::VariantKind ELFRefKind;
3487 MCSymbolRefExpr::VariantKind DarwinRefKind;
3488 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003489 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3490
3491 // Only allow these with ADDXri.
3492 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3493 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3494 Inst.getOpcode() == AArch64::ADDXri)
3495 return false;
3496
3497 // Only allow these with ADDXri/ADDWri
3498 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3499 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3500 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3501 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3502 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3503 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3504 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3505 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3506 (Inst.getOpcode() == AArch64::ADDXri ||
3507 Inst.getOpcode() == AArch64::ADDWri))
3508 return false;
3509
3510 // Don't allow symbol refs in the immediate field otherwise
3511 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3512 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3513 // 'cmp w0, 'borked')
3514 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003515 }
Diana Picusc93518d2016-10-11 09:17:47 +00003516 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003517 }
3518 return false;
3519 }
3520 default:
3521 return false;
3522 }
3523}
3524
Craig Topper05515562017-10-26 06:46:41 +00003525static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3526 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003527
3528bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3529 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003530 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003531 case Match_InvalidTiedOperand:
3532 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003533 case Match_MissingFeature:
3534 return Error(Loc,
3535 "instruction requires a CPU feature not currently enabled");
3536 case Match_InvalidOperand:
3537 return Error(Loc, "invalid operand for instruction");
3538 case Match_InvalidSuffix:
3539 return Error(Loc, "invalid type suffix for instruction");
3540 case Match_InvalidCondCode:
3541 return Error(Loc, "expected AArch64 condition code");
3542 case Match_AddSubRegExtendSmall:
3543 return Error(Loc,
3544 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3545 case Match_AddSubRegExtendLarge:
3546 return Error(Loc,
3547 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3548 case Match_AddSubSecondSource:
3549 return Error(Loc,
3550 "expected compatible register, symbol or integer in range [0, 4095]");
3551 case Match_LogicalSecondSource:
3552 return Error(Loc, "expected compatible register or logical immediate");
3553 case Match_InvalidMovImm32Shift:
3554 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3555 case Match_InvalidMovImm64Shift:
3556 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3557 case Match_AddSubRegShift32:
3558 return Error(Loc,
3559 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3560 case Match_AddSubRegShift64:
3561 return Error(Loc,
3562 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3563 case Match_InvalidFPImm:
3564 return Error(Loc,
3565 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003566 case Match_InvalidMemoryIndexedSImm6:
3567 return Error(Loc, "index must be an integer in range [-32, 31].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003568 case Match_InvalidMemoryIndexedSImm9:
3569 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003570 case Match_InvalidMemoryIndexedSImm10:
3571 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003572 case Match_InvalidMemoryIndexed4SImm7:
3573 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3574 case Match_InvalidMemoryIndexed8SImm7:
3575 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3576 case Match_InvalidMemoryIndexed16SImm7:
3577 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3578 case Match_InvalidMemoryWExtend8:
3579 return Error(Loc,
3580 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3581 case Match_InvalidMemoryWExtend16:
3582 return Error(Loc,
3583 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3584 case Match_InvalidMemoryWExtend32:
3585 return Error(Loc,
3586 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3587 case Match_InvalidMemoryWExtend64:
3588 return Error(Loc,
3589 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3590 case Match_InvalidMemoryWExtend128:
3591 return Error(Loc,
3592 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3593 case Match_InvalidMemoryXExtend8:
3594 return Error(Loc,
3595 "expected 'lsl' or 'sxtx' with optional shift of #0");
3596 case Match_InvalidMemoryXExtend16:
3597 return Error(Loc,
3598 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3599 case Match_InvalidMemoryXExtend32:
3600 return Error(Loc,
3601 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3602 case Match_InvalidMemoryXExtend64:
3603 return Error(Loc,
3604 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3605 case Match_InvalidMemoryXExtend128:
3606 return Error(Loc,
3607 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3608 case Match_InvalidMemoryIndexed1:
3609 return Error(Loc, "index must be an integer in range [0, 4095].");
3610 case Match_InvalidMemoryIndexed2:
3611 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3612 case Match_InvalidMemoryIndexed4:
3613 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3614 case Match_InvalidMemoryIndexed8:
3615 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3616 case Match_InvalidMemoryIndexed16:
3617 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003618 case Match_InvalidImm0_1:
3619 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003620 case Match_InvalidImm0_7:
3621 return Error(Loc, "immediate must be an integer in range [0, 7].");
3622 case Match_InvalidImm0_15:
3623 return Error(Loc, "immediate must be an integer in range [0, 15].");
3624 case Match_InvalidImm0_31:
3625 return Error(Loc, "immediate must be an integer in range [0, 31].");
3626 case Match_InvalidImm0_63:
3627 return Error(Loc, "immediate must be an integer in range [0, 63].");
3628 case Match_InvalidImm0_127:
3629 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003630 case Match_InvalidImm0_255:
3631 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003632 case Match_InvalidImm0_65535:
3633 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3634 case Match_InvalidImm1_8:
3635 return Error(Loc, "immediate must be an integer in range [1, 8].");
3636 case Match_InvalidImm1_16:
3637 return Error(Loc, "immediate must be an integer in range [1, 16].");
3638 case Match_InvalidImm1_32:
3639 return Error(Loc, "immediate must be an integer in range [1, 32].");
3640 case Match_InvalidImm1_64:
3641 return Error(Loc, "immediate must be an integer in range [1, 64].");
3642 case Match_InvalidIndex1:
3643 return Error(Loc, "expected lane specifier '[1]'");
3644 case Match_InvalidIndexB:
3645 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3646 case Match_InvalidIndexH:
3647 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3648 case Match_InvalidIndexS:
3649 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3650 case Match_InvalidIndexD:
3651 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3652 case Match_InvalidLabel:
3653 return Error(Loc, "expected label or encodable integer pc offset");
3654 case Match_MRS:
3655 return Error(Loc, "expected readable system register");
3656 case Match_MSR:
3657 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003658 case Match_InvalidComplexRotationEven:
3659 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3660 case Match_InvalidComplexRotationOdd:
3661 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003662 case Match_MnemonicFail: {
3663 std::string Suggestion = AArch64MnemonicSpellCheck(
3664 ((AArch64Operand &)*Operands[0]).getToken(),
3665 ComputeAvailableFeatures(STI->getFeatureBits()));
3666 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3667 }
Sander de Smalencd6be962017-12-20 11:02:42 +00003668 case Match_InvalidSVEPredicateAnyReg:
3669 case Match_InvalidSVEPredicateBReg:
3670 case Match_InvalidSVEPredicateHReg:
3671 case Match_InvalidSVEPredicateSReg:
3672 case Match_InvalidSVEPredicateDReg:
3673 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003674 case Match_InvalidSVEPredicate3bAnyReg:
3675 case Match_InvalidSVEPredicate3bBReg:
3676 case Match_InvalidSVEPredicate3bHReg:
3677 case Match_InvalidSVEPredicate3bSReg:
3678 case Match_InvalidSVEPredicate3bDReg:
3679 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003680 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003681 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003682 }
3683}
3684
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003685static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003686
3687bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3688 OperandVector &Operands,
3689 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003690 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003691 bool MatchingInlineAsm) {
3692 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003693 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3694 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003695
David Blaikie960ea3f2014-06-08 16:18:35 +00003696 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003697 unsigned NumOperands = Operands.size();
3698
3699 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003700 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3701 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003702 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003703 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003704 if (Op3CE) {
3705 uint64_t Op3Val = Op3CE->getValue();
3706 uint64_t NewOp3Val = 0;
3707 uint64_t NewOp4Val = 0;
3708 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003709 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003710 NewOp3Val = (32 - Op3Val) & 0x1f;
3711 NewOp4Val = 31 - Op3Val;
3712 } else {
3713 NewOp3Val = (64 - Op3Val) & 0x3f;
3714 NewOp4Val = 63 - Op3Val;
3715 }
3716
Jim Grosbach13760bd2015-05-30 01:25:56 +00003717 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3718 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003719
3720 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003721 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003722 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003723 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3724 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3725 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003726 }
3727 }
Tim Northover03b99f62015-04-30 18:28:58 +00003728 } else if (NumOperands == 4 && Tok == "bfc") {
3729 // FIXME: Horrible hack to handle BFC->BFM alias.
3730 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3731 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3732 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3733
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003734 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003735 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3736 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3737
3738 if (LSBCE && WidthCE) {
3739 uint64_t LSB = LSBCE->getValue();
3740 uint64_t Width = WidthCE->getValue();
3741
3742 uint64_t RegWidth = 0;
3743 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3744 Op1.getReg()))
3745 RegWidth = 64;
3746 else
3747 RegWidth = 32;
3748
3749 if (LSB >= RegWidth)
3750 return Error(LSBOp.getStartLoc(),
3751 "expected integer in range [0, 31]");
3752 if (Width < 1 || Width > RegWidth)
3753 return Error(WidthOp.getStartLoc(),
3754 "expected integer in range [1, 32]");
3755
3756 uint64_t ImmR = 0;
3757 if (RegWidth == 32)
3758 ImmR = (32 - LSB) & 0x1f;
3759 else
3760 ImmR = (64 - LSB) & 0x3f;
3761
3762 uint64_t ImmS = Width - 1;
3763
3764 if (ImmR != 0 && ImmS >= ImmR)
3765 return Error(WidthOp.getStartLoc(),
3766 "requested insert overflows register");
3767
Jim Grosbach13760bd2015-05-30 01:25:56 +00003768 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3769 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003770 Operands[0] = AArch64Operand::CreateToken(
3771 "bfm", false, Op.getStartLoc(), getContext());
3772 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003773 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3774 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003775 Operands[3] = AArch64Operand::CreateImm(
3776 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3777 Operands.emplace_back(
3778 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3779 WidthOp.getEndLoc(), getContext()));
3780 }
3781 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003782 } else if (NumOperands == 5) {
3783 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3784 // UBFIZ -> UBFM aliases.
3785 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003786 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3787 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3788 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003789
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003790 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003791 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3792 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003793
3794 if (Op3CE && Op4CE) {
3795 uint64_t Op3Val = Op3CE->getValue();
3796 uint64_t Op4Val = Op4CE->getValue();
3797
3798 uint64_t RegWidth = 0;
3799 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003800 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003801 RegWidth = 64;
3802 else
3803 RegWidth = 32;
3804
3805 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003806 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003807 "expected integer in range [0, 31]");
3808 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003809 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003810 "expected integer in range [1, 32]");
3811
3812 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003813 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003814 NewOp3Val = (32 - Op3Val) & 0x1f;
3815 else
3816 NewOp3Val = (64 - Op3Val) & 0x3f;
3817
3818 uint64_t NewOp4Val = Op4Val - 1;
3819
3820 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003821 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003822 "requested insert overflows register");
3823
3824 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003825 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003826 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003827 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003828 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003829 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003830 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003831 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003832 if (Tok == "bfi")
3833 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003834 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003835 else if (Tok == "sbfiz")
3836 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003837 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003838 else if (Tok == "ubfiz")
3839 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003840 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003841 else
3842 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003843 }
3844 }
3845
3846 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3847 // UBFX -> UBFM aliases.
3848 } else if (NumOperands == 5 &&
3849 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003850 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3851 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3852 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003853
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003854 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003855 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3856 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003857
3858 if (Op3CE && Op4CE) {
3859 uint64_t Op3Val = Op3CE->getValue();
3860 uint64_t Op4Val = Op4CE->getValue();
3861
3862 uint64_t RegWidth = 0;
3863 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003864 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003865 RegWidth = 64;
3866 else
3867 RegWidth = 32;
3868
3869 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003870 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003871 "expected integer in range [0, 31]");
3872 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003873 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003874 "expected integer in range [1, 32]");
3875
3876 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3877
3878 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003879 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003880 "requested extract overflows register");
3881
3882 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003883 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003884 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003885 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003886 if (Tok == "bfxil")
3887 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003888 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003889 else if (Tok == "sbfx")
3890 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003891 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003892 else if (Tok == "ubfx")
3893 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003894 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003895 else
3896 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003897 }
3898 }
3899 }
3900 }
Tim Northover9097a072017-12-18 10:36:00 +00003901
3902 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
3903 // instruction for FP registers correctly in some rare circumstances. Convert
3904 // it to a safe instruction and warn (because silently changing someone's
3905 // assembly is rude).
3906 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
3907 NumOperands == 4 && Tok == "movi") {
3908 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3909 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3910 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3911 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
3912 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
3913 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
3914 if (Suffix.lower() == ".2d" &&
3915 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
3916 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
3917 " correctly on this CPU, converting to equivalent movi.16b");
3918 // Switch the suffix to .16b.
3919 unsigned Idx = Op1.isToken() ? 1 : 2;
3920 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
3921 getContext());
3922 }
3923 }
3924 }
3925
Tim Northover3b0846e2014-05-24 12:50:23 +00003926 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3927 // InstAlias can't quite handle this since the reg classes aren't
3928 // subclasses.
3929 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3930 // The source register can be Wn here, but the matcher expects a
3931 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003932 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003933 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003934 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003935 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3936 Op.getStartLoc(), Op.getEndLoc(),
3937 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003938 }
3939 }
3940 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3941 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003942 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003943 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003944 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003945 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003946 // The source register can be Wn here, but the matcher expects a
3947 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003948 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003949 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003950 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003951 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3952 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003953 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003954 }
3955 }
3956 }
3957 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3958 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003959 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003960 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003961 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003962 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003963 // The source register can be Wn here, but the matcher expects a
3964 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003965 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003966 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003967 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00003968 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
3969 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003970 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003971 }
3972 }
3973 }
3974
Tim Northover3b0846e2014-05-24 12:50:23 +00003975 MCInst Inst;
3976 // First try to match against the secondary set of tables containing the
3977 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3978 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003979 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003980
3981 // If that fails, try against the alternate table containing long-form NEON:
3982 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003983 if (MatchResult != Match_Success) {
3984 // But first, save the short-form match result: we can use it in case the
3985 // long-form match also fails.
3986 auto ShortFormNEONErrorInfo = ErrorInfo;
3987 auto ShortFormNEONMatchResult = MatchResult;
3988
Tim Northover3b0846e2014-05-24 12:50:23 +00003989 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003990 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003991
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003992 // Now, both matches failed, and the long-form match failed on the mnemonic
3993 // suffix token operand. The short-form match failure is probably more
3994 // relevant: use it instead.
3995 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003996 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003997 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3998 MatchResult = ShortFormNEONMatchResult;
3999 ErrorInfo = ShortFormNEONErrorInfo;
4000 }
4001 }
4002
Tim Northover3b0846e2014-05-24 12:50:23 +00004003 switch (MatchResult) {
4004 case Match_Success: {
4005 // Perform range checking and other semantic validations
4006 SmallVector<SMLoc, 8> OperandLocs;
4007 NumOperands = Operands.size();
4008 for (unsigned i = 1; i < NumOperands; ++i)
4009 OperandLocs.push_back(Operands[i]->getStartLoc());
4010 if (validateInstruction(Inst, OperandLocs))
4011 return true;
4012
4013 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004014 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004015 return false;
4016 }
4017 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004018 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004019 // Special case the error message for the very common case where only
4020 // a single subtarget feature is missing (neon, e.g.).
4021 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004022 uint64_t Mask = 1;
4023 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4024 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004025 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004026 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004027 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004028 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004029 }
4030 return Error(IDLoc, Msg);
4031 }
4032 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004033 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004034 case Match_InvalidOperand: {
4035 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004036
Tim Northover26bb14e2014-08-18 11:49:42 +00004037 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004038 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004039 return Error(IDLoc, "too few operands for instruction",
4040 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004041
David Blaikie960ea3f2014-06-08 16:18:35 +00004042 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004043 if (ErrorLoc == SMLoc())
4044 ErrorLoc = IDLoc;
4045 }
4046 // If the match failed on a suffix token operand, tweak the diagnostic
4047 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004048 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4049 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004050 MatchResult = Match_InvalidSuffix;
4051
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004052 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004053 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004054 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004055 case Match_InvalidMemoryIndexed1:
4056 case Match_InvalidMemoryIndexed2:
4057 case Match_InvalidMemoryIndexed4:
4058 case Match_InvalidMemoryIndexed8:
4059 case Match_InvalidMemoryIndexed16:
4060 case Match_InvalidCondCode:
4061 case Match_AddSubRegExtendSmall:
4062 case Match_AddSubRegExtendLarge:
4063 case Match_AddSubSecondSource:
4064 case Match_LogicalSecondSource:
4065 case Match_AddSubRegShift32:
4066 case Match_AddSubRegShift64:
4067 case Match_InvalidMovImm32Shift:
4068 case Match_InvalidMovImm64Shift:
4069 case Match_InvalidFPImm:
4070 case Match_InvalidMemoryWExtend8:
4071 case Match_InvalidMemoryWExtend16:
4072 case Match_InvalidMemoryWExtend32:
4073 case Match_InvalidMemoryWExtend64:
4074 case Match_InvalidMemoryWExtend128:
4075 case Match_InvalidMemoryXExtend8:
4076 case Match_InvalidMemoryXExtend16:
4077 case Match_InvalidMemoryXExtend32:
4078 case Match_InvalidMemoryXExtend64:
4079 case Match_InvalidMemoryXExtend128:
Sander de Smalen909cf952018-01-19 15:22:00 +00004080 case Match_InvalidMemoryIndexedSImm6:
Tim Northover3b0846e2014-05-24 12:50:23 +00004081 case Match_InvalidMemoryIndexed4SImm7:
4082 case Match_InvalidMemoryIndexed8SImm7:
4083 case Match_InvalidMemoryIndexed16SImm7:
4084 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004085 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004086 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004087 case Match_InvalidImm0_7:
4088 case Match_InvalidImm0_15:
4089 case Match_InvalidImm0_31:
4090 case Match_InvalidImm0_63:
4091 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004092 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004093 case Match_InvalidImm0_65535:
4094 case Match_InvalidImm1_8:
4095 case Match_InvalidImm1_16:
4096 case Match_InvalidImm1_32:
4097 case Match_InvalidImm1_64:
4098 case Match_InvalidIndex1:
4099 case Match_InvalidIndexB:
4100 case Match_InvalidIndexH:
4101 case Match_InvalidIndexS:
4102 case Match_InvalidIndexD:
4103 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004104 case Match_InvalidComplexRotationEven:
4105 case Match_InvalidComplexRotationOdd:
Sander de Smalencd6be962017-12-20 11:02:42 +00004106 case Match_InvalidSVEPredicateAnyReg:
4107 case Match_InvalidSVEPredicateBReg:
4108 case Match_InvalidSVEPredicateHReg:
4109 case Match_InvalidSVEPredicateSReg:
4110 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004111 case Match_InvalidSVEPredicate3bAnyReg:
4112 case Match_InvalidSVEPredicate3bBReg:
4113 case Match_InvalidSVEPredicate3bHReg:
4114 case Match_InvalidSVEPredicate3bSReg:
4115 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004116 case Match_MSR:
4117 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004118 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004119 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004120 // Any time we get here, there's nothing fancy to do. Just get the
4121 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004122 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004123 if (ErrorLoc == SMLoc())
4124 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004125 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004126 }
4127 }
4128
4129 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004130}
4131
4132/// ParseDirective parses the arm specific directives
4133bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004134 const MCObjectFileInfo::Environment Format =
4135 getContext().getObjectFileInfo()->getObjectFileType();
4136 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4137 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004138
Tim Northover3b0846e2014-05-24 12:50:23 +00004139 StringRef IDVal = DirectiveID.getIdentifier();
4140 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004141 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004142 parseDirectiveArch(Loc);
4143 else if (IDVal == ".cpu")
4144 parseDirectiveCPU(Loc);
4145 else if (IDVal == ".hword")
4146 parseDirectiveWord(2, Loc);
4147 else if (IDVal == ".word")
4148 parseDirectiveWord(4, Loc);
4149 else if (IDVal == ".xword")
4150 parseDirectiveWord(8, Loc);
4151 else if (IDVal == ".tlsdesccall")
4152 parseDirectiveTLSDescCall(Loc);
4153 else if (IDVal == ".ltorg" || IDVal == ".pool")
4154 parseDirectiveLtorg(Loc);
4155 else if (IDVal == ".unreq")
4156 parseDirectiveUnreq(Loc);
4157 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004158 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004159 parseDirectiveInst(Loc);
4160 else
4161 return true;
4162 } else if (IDVal == MCLOHDirectiveName())
4163 parseDirectiveLOH(IDVal, Loc);
4164 else
4165 return true;
4166 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004167}
4168
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004169static const struct {
4170 const char *Name;
4171 const FeatureBitset Features;
4172} ExtensionMap[] = {
4173 { "crc", {AArch64::FeatureCRC} },
4174 { "crypto", {AArch64::FeatureCrypto} },
4175 { "fp", {AArch64::FeatureFPARMv8} },
4176 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004177 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004178 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004179
4180 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004181 { "pan", {} },
4182 { "lor", {} },
4183 { "rdma", {} },
4184 { "profile", {} },
4185};
4186
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004187/// parseDirectiveArch
4188/// ::= .arch token
4189bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4190 SMLoc ArchLoc = getLoc();
4191
4192 StringRef Arch, ExtensionString;
4193 std::tie(Arch, ExtensionString) =
4194 getParser().parseStringToEndOfStatement().trim().split('+');
4195
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004196 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4197 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004198 return Error(ArchLoc, "unknown arch name");
4199
4200 if (parseToken(AsmToken::EndOfStatement))
4201 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004202
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004203 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004204 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004205 AArch64::getArchFeatures(ID, AArch64Features);
4206 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4207 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004208
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004209 MCSubtargetInfo &STI = copySTI();
4210 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4211 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4212
4213 SmallVector<StringRef, 4> RequestedExtensions;
4214 if (!ExtensionString.empty())
4215 ExtensionString.split(RequestedExtensions, '+');
4216
4217 FeatureBitset Features = STI.getFeatureBits();
4218 for (auto Name : RequestedExtensions) {
4219 bool EnableFeature = true;
4220
4221 if (Name.startswith_lower("no")) {
4222 EnableFeature = false;
4223 Name = Name.substr(2);
4224 }
4225
4226 for (const auto &Extension : ExtensionMap) {
4227 if (Extension.Name != Name)
4228 continue;
4229
4230 if (Extension.Features.none())
4231 report_fatal_error("unsupported architectural extension: " + Name);
4232
4233 FeatureBitset ToggleFeatures = EnableFeature
4234 ? (~Features & Extension.Features)
4235 : ( Features & Extension.Features);
4236 uint64_t Features =
4237 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4238 setAvailableFeatures(Features);
4239 break;
4240 }
4241 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004242 return false;
4243}
4244
Tim Northover8b96c7e2017-05-15 19:42:15 +00004245static SMLoc incrementLoc(SMLoc L, int Offset) {
4246 return SMLoc::getFromPointer(L.getPointer() + Offset);
4247}
4248
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004249/// parseDirectiveCPU
4250/// ::= .cpu id
4251bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004252 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004253
4254 StringRef CPU, ExtensionString;
4255 std::tie(CPU, ExtensionString) =
4256 getParser().parseStringToEndOfStatement().trim().split('+');
4257
Nirav Davee833c6c2016-11-08 18:31:04 +00004258 if (parseToken(AsmToken::EndOfStatement))
4259 return true;
4260
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004261 SmallVector<StringRef, 4> RequestedExtensions;
4262 if (!ExtensionString.empty())
4263 ExtensionString.split(RequestedExtensions, '+');
4264
4265 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4266 // once that is tablegen'ed
4267 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004268 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004269 return false;
4270 }
4271
4272 MCSubtargetInfo &STI = copySTI();
4273 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004274 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004275
4276 FeatureBitset Features = STI.getFeatureBits();
4277 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004278 // Advance source location past '+'.
4279 CurLoc = incrementLoc(CurLoc, 1);
4280
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004281 bool EnableFeature = true;
4282
4283 if (Name.startswith_lower("no")) {
4284 EnableFeature = false;
4285 Name = Name.substr(2);
4286 }
4287
Tim Northover8b96c7e2017-05-15 19:42:15 +00004288 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004289 for (const auto &Extension : ExtensionMap) {
4290 if (Extension.Name != Name)
4291 continue;
4292
4293 if (Extension.Features.none())
4294 report_fatal_error("unsupported architectural extension: " + Name);
4295
4296 FeatureBitset ToggleFeatures = EnableFeature
4297 ? (~Features & Extension.Features)
4298 : ( Features & Extension.Features);
4299 uint64_t Features =
4300 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4301 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004302 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004303
4304 break;
4305 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004306
4307 if (!FoundExtension)
4308 Error(CurLoc, "unsupported architectural extension");
4309
4310 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004311 }
4312 return false;
4313}
4314
Tim Northover3b0846e2014-05-24 12:50:23 +00004315/// parseDirectiveWord
4316/// ::= .word [ expression (, expression)* ]
4317bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004318 auto parseOp = [&]() -> bool {
4319 const MCExpr *Value;
4320 if (getParser().parseExpression(Value))
4321 return true;
4322 getParser().getStreamer().EmitValue(Value, Size, L);
4323 return false;
4324 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004325
Nirav Davee833c6c2016-11-08 18:31:04 +00004326 if (parseMany(parseOp))
4327 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004328 return false;
4329}
4330
Chad Rosierdcd2a302014-10-22 20:35:57 +00004331/// parseDirectiveInst
4332/// ::= .inst opcode [, ...]
4333bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004334 if (getLexer().is(AsmToken::EndOfStatement))
4335 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004336
Nirav Davee833c6c2016-11-08 18:31:04 +00004337 auto parseOp = [&]() -> bool {
4338 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004339 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004340 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4341 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004342 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004343 if (check(!Value, L, "expected constant expression"))
4344 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004345 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004346 return false;
4347 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004348
Nirav Davee833c6c2016-11-08 18:31:04 +00004349 if (parseMany(parseOp))
4350 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004351 return false;
4352}
4353
Tim Northover3b0846e2014-05-24 12:50:23 +00004354// parseDirectiveTLSDescCall:
4355// ::= .tlsdesccall symbol
4356bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4357 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004358 if (check(getParser().parseIdentifier(Name), L,
4359 "expected symbol after directive") ||
4360 parseToken(AsmToken::EndOfStatement))
4361 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004362
Jim Grosbach6f482002015-05-18 18:43:14 +00004363 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004364 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4365 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004366
4367 MCInst Inst;
4368 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004369 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004370
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004371 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004372 return false;
4373}
4374
4375/// ::= .loh <lohName | lohId> label1, ..., labelN
4376/// The number of arguments depends on the loh identifier.
4377bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004378 MCLOHType Kind;
4379 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4380 if (getParser().getTok().isNot(AsmToken::Integer))
4381 return TokError("expected an identifier or a number in directive");
4382 // We successfully get a numeric value for the identifier.
4383 // Check if it is valid.
4384 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004385 if (Id <= -1U && !isValidMCLOHType(Id))
4386 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004387 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004388 } else {
4389 StringRef Name = getTok().getIdentifier();
4390 // We successfully parse an identifier.
4391 // Check if it is a recognized one.
4392 int Id = MCLOHNameToId(Name);
4393
4394 if (Id == -1)
4395 return TokError("invalid identifier in directive");
4396 Kind = (MCLOHType)Id;
4397 }
4398 // Consume the identifier.
4399 Lex();
4400 // Get the number of arguments of this LOH.
4401 int NbArgs = MCLOHIdToNbArgs(Kind);
4402
4403 assert(NbArgs != -1 && "Invalid number of arguments");
4404
4405 SmallVector<MCSymbol *, 3> Args;
4406 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4407 StringRef Name;
4408 if (getParser().parseIdentifier(Name))
4409 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004410 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004411
4412 if (Idx + 1 == NbArgs)
4413 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004414 if (parseToken(AsmToken::Comma,
4415 "unexpected token in '" + Twine(IDVal) + "' directive"))
4416 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004417 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004418 if (parseToken(AsmToken::EndOfStatement,
4419 "unexpected token in '" + Twine(IDVal) + "' directive"))
4420 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004421
4422 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4423 return false;
4424}
4425
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004426/// parseDirectiveLtorg
4427/// ::= .ltorg | .pool
4428bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004429 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4430 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004431 getTargetStreamer().emitCurrentConstantPool();
4432 return false;
4433}
4434
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004435/// parseDirectiveReq
4436/// ::= name .req registername
4437bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004438 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004439 Parser.Lex(); // Eat the '.req' token.
4440 SMLoc SRegLoc = getLoc();
Sander de Smalen8e607342017-11-15 15:44:43 +00004441 int RegNum = tryParseRegister();
Florian Hahnc4422242017-11-07 13:07:50 +00004442 RegKind RegisterKind = RegKind::Scalar;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004443
Sander de Smalen8e607342017-11-15 15:44:43 +00004444 if (RegNum == -1) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004445 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004446 RegisterKind = RegKind::NeonVector;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004447 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004448 if (!Kind.empty())
4449 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004450 }
4451
Sander de Smalen8e607342017-11-15 15:44:43 +00004452 if (RegNum == -1) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004453 StringRef Kind;
4454 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen8e607342017-11-15 15:44:43 +00004455 OperandMatchResultTy Res =
4456 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4457
4458 if (Res == MatchOperand_ParseFail)
4459 return true;
4460
4461 if (Res == MatchOperand_Success && !Kind.empty())
4462 return Error(SRegLoc,
4463 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004464 }
4465
Sander de Smalencd6be962017-12-20 11:02:42 +00004466 if (RegNum == -1) {
4467 StringRef Kind;
4468 RegisterKind = RegKind::SVEPredicateVector;
4469 OperandMatchResultTy Res =
4470 tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
4471
4472 if (Res == MatchOperand_ParseFail)
4473 return true;
4474
4475 if (Res == MatchOperand_Success && !Kind.empty())
4476 return Error(SRegLoc,
4477 "sve predicate register without type specifier expected");
4478 }
4479
Sander de Smalen8e607342017-11-15 15:44:43 +00004480 if (RegNum == -1)
Nirav Dave2364748a2016-09-16 18:30:20 +00004481 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004482
4483 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004484 if (parseToken(AsmToken::EndOfStatement,
4485 "unexpected input in .req directive"))
4486 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004487
Sander de Smalen8e607342017-11-15 15:44:43 +00004488 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004489 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004490 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4491
Nirav Dave2364748a2016-09-16 18:30:20 +00004492 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004493}
4494
4495/// parseDirectiveUneq
4496/// ::= .unreq registername
4497bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004498 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004499 if (getTok().isNot(AsmToken::Identifier))
4500 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004501 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4502 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004503 if (parseToken(AsmToken::EndOfStatement))
4504 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004505 return false;
4506}
4507
Tim Northover3b0846e2014-05-24 12:50:23 +00004508bool
4509AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4510 AArch64MCExpr::VariantKind &ELFRefKind,
4511 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4512 int64_t &Addend) {
4513 ELFRefKind = AArch64MCExpr::VK_INVALID;
4514 DarwinRefKind = MCSymbolRefExpr::VK_None;
4515 Addend = 0;
4516
4517 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4518 ELFRefKind = AE->getKind();
4519 Expr = AE->getSubExpr();
4520 }
4521
4522 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4523 if (SE) {
4524 // It's a simple symbol reference with no addend.
4525 DarwinRefKind = SE->getKind();
4526 return true;
4527 }
4528
4529 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4530 if (!BE)
4531 return false;
4532
4533 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4534 if (!SE)
4535 return false;
4536 DarwinRefKind = SE->getKind();
4537
4538 if (BE->getOpcode() != MCBinaryExpr::Add &&
4539 BE->getOpcode() != MCBinaryExpr::Sub)
4540 return false;
4541
4542 // See if the addend is is a constant, otherwise there's more going
4543 // on here than we can deal with.
4544 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4545 if (!AddendExpr)
4546 return false;
4547
4548 Addend = AddendExpr->getValue();
4549 if (BE->getOpcode() == MCBinaryExpr::Sub)
4550 Addend = -Addend;
4551
4552 // It's some symbol reference + a constant addend, but really
4553 // shouldn't use both Darwin and ELF syntax.
4554 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4555 DarwinRefKind == MCSymbolRefExpr::VK_None;
4556}
4557
4558/// Force static initialization.
4559extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004560 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4561 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4562 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004563}
4564
4565#define GET_REGISTER_MATCHER
4566#define GET_SUBTARGET_FEATURE_NAME
4567#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004568#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004569#include "AArch64GenAsmMatcher.inc"
4570
4571// Define this matcher function after the auto-generated include so we
4572// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004573unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004574 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004575 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004576 // If the kind is a token for a literal immediate, check if our asm
4577 // operand matches. This is for InstAliases which have a fixed-value
4578 // immediate in the syntax.
4579 int64_t ExpectedVal;
4580 switch (Kind) {
4581 default:
4582 return Match_InvalidOperand;
4583 case MCK__35_0:
4584 ExpectedVal = 0;
4585 break;
4586 case MCK__35_1:
4587 ExpectedVal = 1;
4588 break;
4589 case MCK__35_12:
4590 ExpectedVal = 12;
4591 break;
4592 case MCK__35_16:
4593 ExpectedVal = 16;
4594 break;
4595 case MCK__35_2:
4596 ExpectedVal = 2;
4597 break;
4598 case MCK__35_24:
4599 ExpectedVal = 24;
4600 break;
4601 case MCK__35_3:
4602 ExpectedVal = 3;
4603 break;
4604 case MCK__35_32:
4605 ExpectedVal = 32;
4606 break;
4607 case MCK__35_4:
4608 ExpectedVal = 4;
4609 break;
4610 case MCK__35_48:
4611 ExpectedVal = 48;
4612 break;
4613 case MCK__35_6:
4614 ExpectedVal = 6;
4615 break;
4616 case MCK__35_64:
4617 ExpectedVal = 64;
4618 break;
4619 case MCK__35_8:
4620 ExpectedVal = 8;
4621 break;
4622 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004623 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004624 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004625 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004626 if (!CE)
4627 return Match_InvalidOperand;
4628 if (CE->getValue() == ExpectedVal)
4629 return Match_Success;
4630 return Match_InvalidOperand;
4631}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004632
Alex Bradbury58eba092016-11-01 16:32:05 +00004633OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004634AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4635
4636 SMLoc S = getLoc();
4637
4638 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4639 Error(S, "expected register");
4640 return MatchOperand_ParseFail;
4641 }
4642
4643 int FirstReg = tryParseRegister();
4644 if (FirstReg == -1) {
4645 return MatchOperand_ParseFail;
4646 }
4647 const MCRegisterClass &WRegClass =
4648 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4649 const MCRegisterClass &XRegClass =
4650 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4651
4652 bool isXReg = XRegClass.contains(FirstReg),
4653 isWReg = WRegClass.contains(FirstReg);
4654 if (!isXReg && !isWReg) {
4655 Error(S, "expected first even register of a "
4656 "consecutive same-size even/odd register pair");
4657 return MatchOperand_ParseFail;
4658 }
4659
4660 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4661 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4662
4663 if (FirstEncoding & 0x1) {
4664 Error(S, "expected first even register of a "
4665 "consecutive same-size even/odd register pair");
4666 return MatchOperand_ParseFail;
4667 }
4668
4669 SMLoc M = getLoc();
4670 if (getParser().getTok().isNot(AsmToken::Comma)) {
4671 Error(M, "expected comma");
4672 return MatchOperand_ParseFail;
4673 }
4674 // Eat the comma
4675 getParser().Lex();
4676
4677 SMLoc E = getLoc();
4678 int SecondReg = tryParseRegister();
4679 if (SecondReg ==-1) {
4680 return MatchOperand_ParseFail;
4681 }
4682
Eugene Zelenko049b0172017-01-06 00:30:53 +00004683 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004684 (isXReg && !XRegClass.contains(SecondReg)) ||
4685 (isWReg && !WRegClass.contains(SecondReg))) {
4686 Error(E,"expected second odd register of a "
4687 "consecutive same-size even/odd register pair");
4688 return MatchOperand_ParseFail;
4689 }
Joel Jones504bf332016-10-24 13:37:13 +00004690
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004691 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004692 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004693 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4694 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4695 } else {
4696 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4697 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4698 }
4699
Florian Hahnc4422242017-11-07 13:07:50 +00004700 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4701 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004702
4703 return MatchOperand_Success;
4704}
Florian Hahn91f11e52017-11-07 16:45:48 +00004705
4706template <bool ParseSuffix>
4707OperandMatchResultTy
4708AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004709 const SMLoc S = getLoc();
4710 // Check for a SVE vector register specifier first.
Sander de Smalen8e607342017-11-15 15:44:43 +00004711 int RegNum = -1;
Florian Hahn91f11e52017-11-07 16:45:48 +00004712 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004713
Sander de Smalen8e607342017-11-15 15:44:43 +00004714 OperandMatchResultTy Res =
4715 tryParseSVERegister(RegNum, Kind, RegKind::SVEDataVector);
4716
4717 if (Res != MatchOperand_Success)
4718 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004719
4720 if (ParseSuffix && Kind.empty())
4721 return MatchOperand_NoMatch;
4722
4723 unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
4724 .Case("", -1)
4725 .Case(".b", 8)
4726 .Case(".h", 16)
4727 .Case(".s", 32)
4728 .Case(".d", 64)
4729 .Case(".q", 128)
4730 .Default(0);
4731 if (!ElementWidth)
4732 return MatchOperand_NoMatch;
4733
4734 Operands.push_back(
4735 AArch64Operand::CreateReg(RegNum, RegKind::SVEDataVector, ElementWidth,
4736 S, S, getContext()));
4737
4738 return MatchOperand_Success;
4739}
Sander de Smalen245e0e62018-01-22 10:46:00 +00004740
4741OperandMatchResultTy
4742AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
4743 MCAsmParser &Parser = getParser();
4744
4745 SMLoc SS = getLoc();
4746 const AsmToken &TokE = Parser.getTok();
4747 bool IsHash = TokE.is(AsmToken::Hash);
4748
4749 if (!IsHash && TokE.isNot(AsmToken::Identifier))
4750 return MatchOperand_NoMatch;
4751
4752 int64_t Pattern;
4753 if (IsHash) {
4754 Parser.Lex(); // Eat hash
4755
4756 // Parse the immediate operand.
4757 const MCExpr *ImmVal;
4758 SS = getLoc();
4759 if (Parser.parseExpression(ImmVal))
4760 return MatchOperand_ParseFail;
4761
4762 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4763 if (!MCE)
4764 return MatchOperand_ParseFail;
4765
4766 Pattern = MCE->getValue();
4767 } else {
4768 // Parse the pattern
4769 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
4770 if (!Pat)
4771 return MatchOperand_NoMatch;
4772
4773 Parser.Lex();
4774 Pattern = Pat->Encoding;
4775 assert(Pattern >= 0 && Pattern < 32);
4776 }
4777
4778 Operands.push_back(
4779 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
4780 SS, getLoc(), getContext()));
4781
4782 return MatchOperand_Success;
4783}